Merge "tlsdesc_resolver.S: use L() macro for local labels." into main
diff --git a/libc/arch-arm64/bionic/__bionic_clone.S b/libc/arch-arm64/bionic/__bionic_clone.S
index e9932ad..581b47a 100644
--- a/libc/arch-arm64/bionic/__bionic_clone.S
+++ b/libc/arch-arm64/bionic/__bionic_clone.S
@@ -39,7 +39,7 @@
     svc     #0
 
     # Are we the child?
-    cbz     x0, .L_bc_child
+    cbz     x0, L(child)
 
     # Set errno if something went wrong.
     cmn     x0, #(MAX_ERRNO + 1)
@@ -48,7 +48,7 @@
 
     ret
 
-.L_bc_child:
+L(child):
     # We're in the child now. Set the end of the frame record chain.
     mov     x29, #0
     # Setting x30 to 0 will make the unwinder stop at __start_thread.
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index dd16349..26ac255 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -72,7 +72,7 @@
     mov     x8, __NR_clone
     svc     #0
 
-    cbz     x0, .L_exit
+    cbz     x0, L(done)
 
     // rc != 0: reset cached_pid_ and vforked_.
     str     w10, [x9, #20]
@@ -80,7 +80,7 @@
     cneg    x0, x0, hi
     b.hi    __set_errno_internal
 
-.L_exit:
+L(done):
     ret
 END(vfork)
 
diff --git a/libc/arch-arm64/dynamic_function_dispatch.cpp b/libc/arch-arm64/dynamic_function_dispatch.cpp
index db002b8..a42c361 100644
--- a/libc/arch-arm64/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm64/dynamic_function_dispatch.cpp
@@ -30,18 +30,22 @@
 #include <stddef.h>
 #include <sys/auxv.h>
 
-#define MIDR_IMPL_ID_SHIFT 24u
-#define MIDR_IMPL_ID_MASK 0xFF
-#define CPU_VARIANT_SHIFT 20u
-#define CPU_VARIANT_MASK 0xF
+static inline bool __bionic_is_oryon(unsigned long hwcap) {
+    if (!(hwcap & HWCAP_CPUID)) return false;
 
-/* Macro to identify CPU implementer */
-#define QCOM_IMPL_ID 0x51
+    // Extract the implementor and variant bits from MIDR_EL1.
+    // https://www.kernel.org/doc/html/latest/arch/arm64/cpu-feature-registers.html#list-of-registers-with-visible-features
+    unsigned long midr;
+    __asm__ __volatile__("mrs %0, MIDR_EL1" : "=r"(midr));
+    uint16_t cpu = (midr >> 20) & 0xfff;
 
-/* Macro to indentify qualcomm CPU variants which supports
- * __memcpy_aarch64_nt routine
- */
-#define QCOM_ORYON_CPU_VARIANTS 0x5
+    auto make_cpu = [](unsigned implementor, unsigned variant) {
+        return (implementor << 4) | variant;
+    };
+
+    // Check for implementor Qualcomm's variants 0x1..0x5 (Oryon).
+    return cpu >= make_cpu('Q', 0x1) && cpu <= make_cpu('Q', 0x5);
+}
 
 extern "C" {
 
@@ -62,68 +66,20 @@
 
 typedef void* memcpy_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memcpy) {
-  unsigned long midr;
-  unsigned int impl_id, cpu_variant;
-
-  /* Check if hardware capability CPUID is available */
-  if (arg->_hwcap & HWCAP_CPUID) {
-    /* Read the MIDR register */
-    asm("mrs %0, MIDR_EL1 \n\t" : "=r"(midr));
-
-    /* Extract the CPU Implementer ID */
-    impl_id = (midr >> MIDR_IMPL_ID_SHIFT) & (MIDR_IMPL_ID_MASK);
-
-    /* Check for Qualcomm implementer ID */
-    if (impl_id == QCOM_IMPL_ID) {
-      cpu_variant = (midr >> CPU_VARIANT_SHIFT) & CPU_VARIANT_MASK;
-
-      /* Check for Qualcomm Oryon CPU variants: 0x1, 0x2, 0x3, 0x4, 0x5 */
-      if (cpu_variant <= QCOM_ORYON_CPU_VARIANTS) {
+    if (__bionic_is_oryon(arg->_hwcap)) {
         RETURN_FUNC(memcpy_func, __memcpy_aarch64_nt);
-      } else {
+    } else if (arg->_hwcap & HWCAP_ASIMD) {
+        RETURN_FUNC(memcpy_func, __memcpy_aarch64_simd);
+    } else {
         RETURN_FUNC(memcpy_func, __memcpy_aarch64);
-      }
     }
-  }
-  /* If CPU implementer is not Qualcomm, choose the custom
-   * implementation based on CPU architecture feature
-   * */
-  if (arg->_hwcap & HWCAP_ASIMD) {
-    RETURN_FUNC(memcpy_func, __memcpy_aarch64_simd);
-  } else {
-    RETURN_FUNC(memcpy_func, __memcpy_aarch64);
-  }
 }
 
 typedef void* memmove_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memmove) {
-  unsigned long midr;
-  unsigned int impl_id, cpu_variant;
-
-  /* Check if hardware capability CPUID is available */
-  if (arg->_hwcap & HWCAP_CPUID) {
-    /* Read the MIDR register */
-    asm("mrs %0, MIDR_EL1 \n\t" : "=r"(midr));
-
-    /* Extract the CPU Implementer ID */
-    impl_id = (midr >> MIDR_IMPL_ID_SHIFT) & (MIDR_IMPL_ID_MASK);
-
-    /* Check for Qualcomm implementer ID */
-    if (impl_id == QCOM_IMPL_ID) {
-      cpu_variant = (midr >> CPU_VARIANT_SHIFT) & CPU_VARIANT_MASK;
-
-      /* Check for Qualcomm Oryon CPU variants: 0x1, 0x2, 0x3, 0x4, 0x5 */
-      if (cpu_variant <= QCOM_ORYON_CPU_VARIANTS) {
-        RETURN_FUNC(memcpy_func, __memmove_aarch64_nt);
-      } else {
-        RETURN_FUNC(memcpy_func, __memmove_aarch64);
-      }
-    }
-  }
-  /* If CPU implementer is not Qualcomm, choose the custom
-   * implementation based on CPU architecture feature
-   * */
-  if (arg->_hwcap & HWCAP_ASIMD) {
+  if (__bionic_is_oryon(arg->_hwcap)) {
+    RETURN_FUNC(memcpy_func, __memmove_aarch64_nt);
+  } else if (arg->_hwcap & HWCAP_ASIMD) {
     RETURN_FUNC(memmove_func, __memmove_aarch64_simd);
   } else {
     RETURN_FUNC(memmove_func, __memmove_aarch64);
@@ -137,32 +93,11 @@
 
 typedef int memset_func(void*, int, size_t);
 DEFINE_IFUNC_FOR(memset) {
-  unsigned long midr;
-  unsigned int impl_id, cpu_variant;
-
-  if (arg->_hwcap & HWCAP_CPUID) {
-    /* Read the MIDR register */
-    asm("mrs %0, MIDR_EL1 \n\t" : "=r"(midr));
-
-    /* Extract the CPU Implementer ID */
-    impl_id = (midr >> MIDR_IMPL_ID_SHIFT) & (MIDR_IMPL_ID_MASK);
-
-    /* Check for Qualcomm implementer ID */
-    if (impl_id == QCOM_IMPL_ID) {
-      cpu_variant = (midr >> CPU_VARIANT_SHIFT) & CPU_VARIANT_MASK;
-
-      /* Check for Qualcomm Oryon CPU variants: 0x1, 0x2, 0x3, 0x4, 0x5 */
-      if (cpu_variant <= QCOM_ORYON_CPU_VARIANTS) {
+    if (__bionic_is_oryon(arg->_hwcap)) {
         RETURN_FUNC(memset_func, __memset_aarch64_nt);
-      } else {
-        RETURN_FUNC(memset_func, __memset_aarch64);
-      }
     } else {
-      RETURN_FUNC(memset_func, __memset_aarch64);
+        RETURN_FUNC(memset_func, __memset_aarch64);
     }
-  } else {
-    RETURN_FUNC(memset_func, __memset_aarch64);
-  }
 }
 
 typedef char* stpcpy_func(char*, const char*, size_t);
diff --git a/libc/arch-arm64/string/__memcpy_chk.S b/libc/arch-arm64/string/__memcpy_chk.S
index a8e9e83..c9fc2f7 100644
--- a/libc/arch-arm64/string/__memcpy_chk.S
+++ b/libc/arch-arm64/string/__memcpy_chk.S
@@ -31,10 +31,10 @@
 ENTRY(__memcpy_chk)
   cmp x2, x3
   // Direct b.ls memcpy may not have enough range
-  b.hi .L_memcpy_chk_fail
+  b.hi L(__memcpy_chk_fail_trampoline)
   b memcpy
 
-.L_memcpy_chk_fail:
+L(__memcpy_chk_fail_trampoline):
   // Preserve for accurate backtrace.
   stp x29, x30, [sp, -16]!
   .cfi_def_cfa_offset 16
diff --git a/libc/arch-arm64/string/__memset_chk.S b/libc/arch-arm64/string/__memset_chk.S
index e1e29d0..7a105ce 100644
--- a/libc/arch-arm64/string/__memset_chk.S
+++ b/libc/arch-arm64/string/__memset_chk.S
@@ -31,10 +31,10 @@
 ENTRY(__memset_chk)
   cmp x2, x3
   // Direct b.ls memcpy may not have enough range
-  b.hi .L_memset_chk_fail
+  b.hi L(__memset_chk_fail_trampoline)
   b memset
 
-.L_memset_chk_fail:
+L(__memset_chk_fail_trampoline):
   // Preserve for accurate backtrace.
   stp x29, x30, [sp, -16]!
   .cfi_def_cfa_offset 16
diff --git a/libc/arch-riscv64/bionic/__bionic_clone.S b/libc/arch-riscv64/bionic/__bionic_clone.S
index 2827857..be386b1 100644
--- a/libc/arch-riscv64/bionic/__bionic_clone.S
+++ b/libc/arch-riscv64/bionic/__bionic_clone.S
@@ -41,19 +41,19 @@
   ecall
 
   # Are we the child?
-  beqz a0, .L_bc_child
+  beqz a0, L(child)
 
   # Did the clone(2) fail?
-  bltz a0, .L_bc_failure
+  bltz a0, L(failure)
   # Nope, we're the parent, and our work here is done.
   ret
 
-.L_bc_failure:
+L(failure):
   # Set errno if something went wrong.
   neg a0, a0
   tail __set_errno_internal
 
-.L_bc_child:
+L(child):
   # We're in the child now. Set the end of the frame record chain.
   li fp, 0
   # Setting ra to 0 will make the unwinder stop at __start_thread.
diff --git a/libc/arch-riscv64/bionic/setjmp.S b/libc/arch-riscv64/bionic/setjmp.S
index 81b1e35..5de1099 100644
--- a/libc/arch-riscv64/bionic/setjmp.S
+++ b/libc/arch-riscv64/bionic/setjmp.S
@@ -205,7 +205,7 @@
   // Check the checksum before doing anything.
   m_calculate_checksum t0, a0, t1
   ld t1, _JB_CHECKSUM(a0)
-  bne t0, t1, 3f
+  bne t0, t1, L(checksum_failure)
 
   // Do we need to restore the signal mask?
   ld a2, _JB_SIGFLAG(a0)
@@ -290,7 +290,7 @@
   mv a0, a1
   ret
 
-3:
+L(checksum_failure):
   call __bionic_setjmp_checksum_mismatch
 END(siglongjmp)
 
diff --git a/libc/arch-riscv64/bionic/syscall.S b/libc/arch-riscv64/bionic/syscall.S
index 1a6e60a..ca735c7 100644
--- a/libc/arch-riscv64/bionic/syscall.S
+++ b/libc/arch-riscv64/bionic/syscall.S
@@ -44,10 +44,10 @@
 
   // Did it fail?
   li a7, -MAX_ERRNO
-  bgtu a0, a7, 1f
-
+  bgtu a0, a7, L(failure)
   ret
-1:
+
+L(failure):
   neg a0, a0
   tail __set_errno_internal
 END(syscall)
diff --git a/libc/arch-riscv64/bionic/vfork.S b/libc/arch-riscv64/bionic/vfork.S
index 29ab405..06ebc3e 100644
--- a/libc/arch-riscv64/bionic/vfork.S
+++ b/libc/arch-riscv64/bionic/vfork.S
@@ -51,16 +51,16 @@
   ecall
 
   // if (rc == 0) we're the child, and finished...
-  beqz    a0, .L_success
+  beqz    a0, L(success)
 
   // else if (rc != 0): reset cached_pid_ and vforked_...
   sw      t2, 20(t0)
   // ...and work out whether we succeeded or failed.
-  bltz    a0, .L_failure
-.L_success:
+  bltz    a0, L(failure)
+L(success):
   ret
 
-.L_failure:
+L(failure):
   neg     a0, a0
   tail    __set_errno_internal
 END(vfork)
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 251633d..11f7ced 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -258,14 +258,14 @@
   options->Backtrace = android_unsafe_frame_pointer_chase;
   options->SampleRate = kDefaultSampleRate;
   options->MaxSimultaneousAllocations = kDefaultMaxAllocs;
+  options->Recoverable = true;
+  GwpAsanRecoverable = true;
 
-  *process_sample_rate = 1;
-  if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING) {
+  if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING ||
+      mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
     *process_sample_rate = kDefaultProcessSampling;
-  } else if (mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
-    *process_sample_rate = kDefaultProcessSampling;
-    options->Recoverable = true;
-    GwpAsanRecoverable = true;
+  } else {
+    *process_sample_rate = 1;
   }
 }
 
@@ -403,7 +403,7 @@
         /* default */ kDefaultMaxAllocs / frequency_multiplier;
   }
 
-  bool recoverable = false;
+  bool recoverable = true;
   if (GetGwpAsanBoolOption(&recoverable, mallopt_options, kRecoverableSystemSysprop,
                            kRecoverableAppSysprop, kRecoverableTargetedSyspropPrefix,
                            kRecoverableEnvVar, "recoverable")) {
diff --git a/libc/include/bits/page_size.h b/libc/include/bits/page_size.h
index df0cb7f..594ffe5 100644
--- a/libc/include/bits/page_size.h
+++ b/libc/include/bits/page_size.h
@@ -32,7 +32,16 @@
 
 __BEGIN_DECLS
 
-#if !defined(__BIONIC_NO_PAGE_SIZE_MACRO) || defined(__BIONIC_DEPRECATED_PAGE_SIZE_MACRO)
+// PAGE_SIZE is going away in Android. Prefer getpagesize() instead.
+//
+// For more info, see https://developer.android.com/16kb-page-size.
+//
+// To restore the original behavior, use __BIONIC_DEPRECATED_PAGE_SIZE_MACRO.
+
+#if (defined(__NDK_MAJOR__) && __NDK_MAJOR__ <= 27 && !defined(__BIONIC_NO_PAGE_SIZE_MACRO)) \
+    || defined(__BIONIC_DEPRECATED_PAGE_SIZE_MACRO) \
+    || defined(__arm__) \
+    || defined(__i386__)
 #define PAGE_SIZE 4096
 #define PAGE_MASK (~(PAGE_SIZE - 1))
 #endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 48e7ea9..80fc45d 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -136,6 +136,9 @@
 #define IOV_MAX 1024
 #define SEM_VALUE_MAX 0x3fffffff
 
+/** Do not use: prefer getline() or asprintf() rather than hard-coding an arbitrary size. */
+#define LINE_MAX _POSIX2_LINE_MAX
+
 /* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
 #include <bits/posix_limits.h>
 
diff --git a/libc/include/sys/param.h b/libc/include/sys/param.h
index 79ae067..1c991ae 100644
--- a/libc/include/sys/param.h
+++ b/libc/include/sys/param.h
@@ -41,8 +41,11 @@
 /** The unit of `st_blocks` in `struct stat`. */
 #define DEV_BSIZE 512
 
-/** A historical name for PATH_MAX. */
-#define MAXPATHLEN  PATH_MAX
+/** A historical name for PATH_MAX. Use PATH_MAX in new code. */
+#define MAXPATHLEN PATH_MAX
+
+/** A historical name for NGROUPS_MAX. Use NGROUPS_MAX in new code. */
+#define NGROUPS NGROUPS_MAX
 
 #define MAXSYMLINKS 8
 
diff --git a/libc/include/sys/shm.h b/libc/include/sys/shm.h
index fb6f20c..8ab3d9a 100644
--- a/libc/include/sys/shm.h
+++ b/libc/include/sys/shm.h
@@ -36,11 +36,12 @@
 #include <sys/cdefs.h>
 #include <sys/ipc.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <linux/shm.h>
 
 #define shmid_ds shmid64_ds
-#define SHMLBA 4096
+#define SHMLBA getpagesize()
 
 __BEGIN_DECLS
 
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index a06b8ee..ffc6d4a 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -152,6 +152,10 @@
     // mode, and bug reports will be created by debuggerd, however the process
     // will recover and continue to function as if the memory safety bug wasn't
     // detected.
+    //
+    // In Android 15, this is the same as TURN_ON_WITH_SAMPLING, as GWP-ASan is
+    // only ever used in non-crashing mode (even for platform executables and
+    // system apps).
     TURN_ON_FOR_APP_SAMPLED_NON_CRASHING,
   };
 
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 4deed33..61242eb 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -43,8 +43,8 @@
  public:
   ElfReader();
 
-  bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
-  bool Load(address_space_params* address_space);
+  [[nodiscard]] bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
+  [[nodiscard]] bool Load(address_space_params* address_space);
 
   const char* name() const { return name_.c_str(); }
   size_t phdr_count() const { return phdr_num_; }
@@ -61,18 +61,18 @@
   bool should_pad_segments() const { return should_pad_segments_; }
 
  private:
-  bool ReadElfHeader();
-  bool VerifyElfHeader();
-  bool ReadProgramHeaders();
-  bool ReadSectionHeaders();
-  bool ReadDynamicSection();
-  bool ReadPadSegmentNote();
-  bool ReserveAddressSpace(address_space_params* address_space);
-  bool LoadSegments();
-  bool FindPhdr();
-  bool FindGnuPropertySection();
-  bool CheckPhdr(ElfW(Addr));
-  bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
+  [[nodiscard]] bool ReadElfHeader();
+  [[nodiscard]] bool VerifyElfHeader();
+  [[nodiscard]] bool ReadProgramHeaders();
+  [[nodiscard]] bool ReadSectionHeaders();
+  [[nodiscard]] bool ReadDynamicSection();
+  [[nodiscard]] bool ReadPadSegmentNote();
+  [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space);
+  [[nodiscard]] bool LoadSegments();
+  [[nodiscard]] bool FindPhdr();
+  [[nodiscard]] bool FindGnuPropertySection();
+  [[nodiscard]] bool CheckPhdr(ElfW(Addr));
+  [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
 
   bool did_read_;
   bool did_load_;
diff --git a/tests/headers/posix/limits_h.c b/tests/headers/posix/limits_h.c
index 7e92d81..0ca80a5 100644
--- a/tests/headers/posix/limits_h.c
+++ b/tests/headers/posix/limits_h.c
@@ -130,10 +130,10 @@
   MACRO(CHARCLASS_NAME_MAX);
   MACRO(COLL_WEIGHTS_MAX);
   MACRO(EXPR_NEST_MAX);
-  MACRO(LINE_MAX);
   MACRO(NGROUPS_MAX);
   MACRO(RE_DUP_MAX);
 #endif
+  MACRO(LINE_MAX);
 
   MACRO_VALUE(_POSIX_CLOCKRES_MIN, 20000000);
 
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index e5902ad..bc13a3f 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -21,6 +21,7 @@
 TEST(limits, macros) {
   ASSERT_EQ(8, CHAR_BIT);
   ASSERT_EQ(8 * static_cast<int>(sizeof(int)), WORD_BIT);
+  ASSERT_EQ(2048, LINE_MAX);
   ASSERT_EQ(20, NZERO);
 #if !defined(MB_LEN_MAX)
 #error MB_LEN_MAX