Merge "Assume clang's *LONG_LONG*_ macros." into main
diff --git a/libc/Android.bp b/libc/Android.bp
index 8407a60..5d1a2f2 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1085,7 +1085,6 @@
                 "arch-arm/kryo/bionic/memcpy.S",
 
                 "bionic/strchr.cpp",
-                "bionic/strchrnul.cpp",
                 "bionic/strnlen.cpp",
             ],
         },
@@ -1140,8 +1139,6 @@
                 "arch-riscv64/string/strncmp.c",
                 "arch-riscv64/string/strncpy.c",
                 "arch-riscv64/string/strnlen.c",
-
-                "bionic/strchrnul.cpp",
             ],
         },
 
@@ -1173,8 +1170,6 @@
                 "arch-x86/string/ssse3-strncmp-atom.S",
 
                 "arch-x86/string/sse4-memcmp-slm.S",
-
-                "bionic/strchrnul.cpp",
             ],
         },
         x86_64: {
diff --git a/libc/bionic/strchrnul.cpp b/libc/bionic/strchrnul.cpp
deleted file mode 100644
index 55422e0..0000000
--- a/libc/bionic/strchrnul.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-extern "C" const char* strchrnul(const char* s, int ch) {
-  while (*s && *s != ch) {
-    ++s;
-  }
-  return s;
-}
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index c183897..a662529 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -1091,18 +1091,20 @@
 
 void debug_malloc_disable() {
   ScopedConcurrentLock lock;
-  g_dispatch->malloc_disable();
   if (g_debug->pointer) {
+    // Acquire the pointer locks first, otherwise, the code can be holding
+    // the allocation lock and deadlock trying to acquire a pointer lock.
     g_debug->pointer->PrepareFork();
   }
+  g_dispatch->malloc_disable();
 }
 
 void debug_malloc_enable() {
   ScopedConcurrentLock lock;
+  g_dispatch->malloc_enable();
   if (g_debug->pointer) {
     g_debug->pointer->PostForkParent();
   }
-  g_dispatch->malloc_enable();
 }
 
 ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t max_frames) {
diff --git a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
index d7a7a4f..080242c 100644
--- a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp
@@ -57,6 +57,12 @@
 #include <bionic/malloc.h>
 #include <tests/utils.h>
 
+// exported from bionic
+__BEGIN_DECLS
+extern void malloc_disable();
+extern void malloc_enable();
+__END_DECLS
+
 // All DISABLED_ tests are designed to be executed after malloc debug
 // is enabled. These tests don't run be default, and are executed
 // by wrappers that will enable various malloc debug features.
@@ -788,3 +794,34 @@
   unexpected_log_strings_.push_back("Timed out waiting for ");
   Exec("MallocTests.DISABLED_malloc_and_backtrace_deadlock", "verbose verify_pointers", 0);
 }
+
+// Creates two threads: one that calls malloc_disable() and malloc_enable() in a loop and
+// the other that performs a bunch of allocations.
+TEST(MallocTests, DISABLED_malloc_disable_deadlock) {
+  std::atomic_bool running(true);
+
+  std::thread t1([&] {
+    while (running) {
+      malloc_disable();
+      malloc_enable();
+    }
+  });
+
+  std::thread t2([&] {
+    while (running) {
+      void* p = malloc(100);
+      free(p);
+    }
+  });
+
+  // let the threads run for a while, then tell them to stop and wait for shutdown
+  std::this_thread::sleep_for(std::chrono::seconds(5));
+
+  running = false;
+  t1.join();
+  t2.join();
+}
+
+TEST_F(MallocDebugSystemTest, malloc_disable_deadlock) {
+  Exec("MallocTests.DISABLED_malloc_disable_deadlock", "verbose backtrace");
+}
diff --git a/libc/platform/bionic/macros.h b/libc/platform/bionic/macros.h
index b2d6f96..1e7ca88 100644
--- a/libc/platform/bionic/macros.h
+++ b/libc/platform/bionic/macros.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <stddef.h>
 #include <stdint.h>
 
 #define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index e5369ac..8bcd76c 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -159,8 +159,8 @@
 ElfReader::ElfReader()
     : did_read_(false), did_load_(false), fd_(-1), file_offset_(0), file_size_(0), phdr_num_(0),
       phdr_table_(nullptr), shdr_table_(nullptr), shdr_num_(0), dynamic_(nullptr), strtab_(nullptr),
-      strtab_size_(0), load_start_(nullptr), load_size_(0), load_bias_(0), loaded_phdr_(nullptr),
-      mapped_by_caller_(false) {
+      strtab_size_(0), load_start_(nullptr), load_size_(0), load_bias_(0), max_align_(0), min_align_(0),
+      loaded_phdr_(nullptr), mapped_by_caller_(false) {
 }
 
 bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file_size) {
@@ -175,13 +175,14 @@
   if (ReadElfHeader() &&
       VerifyElfHeader() &&
       ReadProgramHeaders() &&
+      CheckProgramHeaderAlignment() &&
       ReadSectionHeaders() &&
       ReadDynamicSection() &&
       ReadPadSegmentNote()) {
     did_read_ = true;
   }
 
-  if (kPageSize == 0x4000 && phdr_table_get_minimum_alignment(phdr_table_, phdr_num_) == 0x1000) {
+  if (kPageSize == 16*1024 && min_align_ == 4096) {
     // This prop needs to be read on 16KiB devices for each ELF where min_palign is 4KiB.
     // It cannot be cached since the developer may toggle app compat on/off.
     // This check will be removed once app compat is made the default on 16KiB devices.
@@ -562,52 +563,28 @@
   return max_vaddr - min_vaddr;
 }
 
-// Returns the maximum p_align associated with a loadable segment in the ELF
-// program header table. Used to determine whether the file should be loaded at
-// a specific virtual address alignment for use with huge pages.
-size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) {
-  size_t maximum_alignment = page_size();
+bool ElfReader::CheckProgramHeaderAlignment() {
+  max_align_ = min_align_ = page_size();
 
-  for (size_t i = 0; i < phdr_count; ++i) {
-    const ElfW(Phdr)* phdr = &phdr_table[i];
+  for (size_t i = 0; i < phdr_num_; ++i) {
+    const ElfW(Phdr)* phdr = &phdr_table_[i];
 
     // p_align must be 0, 1, or a positive, integral power of two.
     if (phdr->p_type != PT_LOAD || ((phdr->p_align & (phdr->p_align - 1)) != 0)) {
+      // TODO: reject ELF files with bad p_align values.
       continue;
     }
 
-    maximum_alignment = std::max(maximum_alignment, static_cast<size_t>(phdr->p_align));
-  }
-
-#if defined(__LP64__)
-  return maximum_alignment;
-#else
-  return page_size();
+#if defined(__LP64__) // TODO: remove this historical accident #if
+    max_align_ = std::max(max_align_, static_cast<size_t>(phdr->p_align));
 #endif
-}
 
-// Returns the minimum p_align associated with a loadable segment in the ELF
-// program header table. Used to determine if the program alignment is compatible
-// with the page size of this system.
-size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) {
-  size_t minimum_alignment = page_size();
-
-  for (size_t i = 0; i < phdr_count; ++i) {
-    const ElfW(Phdr)* phdr = &phdr_table[i];
-
-    // p_align must be 0, 1, or a positive, integral power of two.
-    if (phdr->p_type != PT_LOAD || ((phdr->p_align & (phdr->p_align - 1)) != 0)) {
-      continue;
+    if (phdr->p_align > 1) {
+      min_align_ = std::min(min_align_, static_cast<size_t>(phdr->p_align));
     }
-
-    if (phdr->p_align <= 1) {
-      continue;
-    }
-
-    minimum_alignment = std::min(minimum_alignment, static_cast<size_t>(phdr->p_align));
   }
 
-  return minimum_alignment;
+  return true;
 }
 
 // Reserve a virtual address range such that if it's limits were extended to the next 2**align
@@ -628,7 +605,7 @@
   // Minimum alignment of shared library gap. For efficiency, this should match the second level
   // page size of the platform.
 #if defined(__LP64__)
-  constexpr size_t kGapAlignment = 1ul << 21;  // 2MB
+  constexpr size_t kGapAlignment = 2 * 1024 * 1024;
 #else
   constexpr size_t kGapAlignment = 0;
 #endif
@@ -717,10 +694,9 @@
     }
     size_t start_alignment = page_size();
     if (get_transparent_hugepages_supported() && get_application_target_sdk_version() >= 31) {
-      size_t maximum_alignment = phdr_table_get_maximum_alignment(phdr_table_, phdr_num_);
       // Limit alignment to PMD size as other alignments reduce the number of
       // bits available for ASLR for no benefit.
-      start_alignment = maximum_alignment == kPmdSize ? kPmdSize : page_size();
+      start_alignment = max_align_ == kPmdSize ? kPmdSize : page_size();
     }
     start = ReserveWithAlignmentPadding(load_size_, kLibraryAlignment, start_alignment, &gap_start_,
                                         &gap_size_);
@@ -1011,13 +987,12 @@
   // are not 16KiB aligned.
   size_t seg_align = should_use_16kib_app_compat_ ? kCompatPageSize : kPageSize;
 
-  size_t min_palign = phdr_table_get_minimum_alignment(phdr_table_, phdr_num_);
   // Only enforce this on 16 KB systems with app compat disabled.
   // Apps may rely on undefined behavior here on 4 KB systems,
   // which is the norm before this change is introduced
-  if (kPageSize >= 16384 && min_palign < kPageSize && !should_use_16kib_app_compat_) {
+  if (kPageSize >= 16384 && min_align_ < kPageSize && !should_use_16kib_app_compat_) {
     DL_ERR("\"%s\" program alignment (%zu) cannot be smaller than system page size (%zu)",
-           name_.c_str(), min_palign, kPageSize);
+           name_.c_str(), min_align_, kPageSize);
     return false;
   }
 
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index e15ece4..3b68528 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -76,6 +76,7 @@
   [[nodiscard]] bool ReadElfHeader();
   [[nodiscard]] bool VerifyElfHeader();
   [[nodiscard]] bool ReadProgramHeaders();
+  [[nodiscard]] bool CheckProgramHeaderAlignment();
   [[nodiscard]] bool ReadSectionHeaders();
   [[nodiscard]] bool ReadDynamicSection();
   [[nodiscard]] bool ReadPadSegmentNote();
@@ -130,6 +131,10 @@
   // Load bias.
   ElfW(Addr) load_bias_;
 
+  // Maximum and minimum alignment requirements across all phdrs.
+  size_t max_align_;
+  size_t min_align_;
+
   // Loaded phdr.
   const ElfW(Phdr)* loaded_phdr_;
 
@@ -153,9 +158,6 @@
 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 
-size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
-size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
-
 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr) load_bias, bool should_pad_segments,
                                 bool should_use_16kib_app_compat,