Merge "Fix clang header dependency for versioner"
diff --git a/libc/Android.bp b/libc/Android.bp
index 52a7aca..71d4d4a 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1675,7 +1675,9 @@
         versions: ["10000"],
     },
 
-    symbol_ordering_file: "symbol_ordering",
+    // Sorting bss symbols by size usually results in less dirty pages at run
+    // time, because small symbols are grouped together.
+    sort_bss_symbols_by_size: true,
 }
 
 genrule {
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 4984e38..6e1b0de 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -135,8 +135,11 @@
 
   main_thread.mmap_base = mapping.mmap_base;
   main_thread.mmap_size = mapping.mmap_size;
+  main_thread.mmap_base_unguarded = mapping.mmap_base_unguarded;
+  main_thread.mmap_size_unguarded = mapping.mmap_size_unguarded;
 
   __set_tls(&new_tcb->tls_slot(0));
 
+  __set_stack_and_tls_vma_name(true);
   __free_temp_bionic_tls(temp_tls);
 }
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index fc00207..cda5e85 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -55,6 +55,10 @@
     // fork, close all of their fds blindly, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
 
+    // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
+    // parent process.
+    __set_stack_and_tls_vma_name(true);
+
     __bionic_atfork_run_child();
   } else {
     __bionic_atfork_run_parent();
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index b9a4e99..ef77c9c 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -30,7 +30,7 @@
 
 void* je_aligned_alloc_wrapper(size_t, size_t);
 int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
-int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) __attribute__((nothrow));
 struct mallinfo je_mallinfo();
 void je_malloc_disable();
 void je_malloc_enable();
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 4cf14ad..0dbf539 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -254,6 +254,8 @@
   ThreadMapping result = {};
   result.mmap_base = space;
   result.mmap_size = mmap_size;
+  result.mmap_base_unguarded = space + stack_guard_size;
+  result.mmap_size_unguarded = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
   result.static_tls = space + mmap_size - PTHREAD_GUARD_SIZE - layout.size();
   result.stack_base = space;
   result.stack_top = result.static_tls;
@@ -315,12 +317,33 @@
   thread->attr = *attr;
   thread->mmap_base = mapping.mmap_base;
   thread->mmap_size = mapping.mmap_size;
+  thread->mmap_base_unguarded = mapping.mmap_base_unguarded;
+  thread->mmap_size_unguarded = mapping.mmap_size_unguarded;
 
   *tcbp = tcb;
   *child_stack = stack_top;
   return 0;
 }
 
+void __set_stack_and_tls_vma_name(bool is_main_thread) {
+  // Name the thread's stack-and-tls area to help with debugging. This mapped area also includes
+  // static TLS data, which is typically a few pages (e.g. bionic_tls).
+  pthread_internal_t* thread = __get_thread();
+  const char* name;
+  if (is_main_thread) {
+    name = "stack_and_tls:main";
+  } else {
+    // The kernel doesn't copy the name string, but this variable will last at least as long as the
+    // mapped area. The mapped area's VMAs are unmapped with a single call to munmap.
+    auto& name_buffer = thread->vma_name_buffer;
+    static_assert(arraysize(name_buffer) >= arraysize("stack_and_tls:") + 11 + 1);
+    async_safe_format_buffer(name_buffer, arraysize(name_buffer), "stack_and_tls:%d", thread->tid);
+    name = name_buffer;
+  }
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->mmap_base_unguarded, thread->mmap_size_unguarded,
+        name);
+}
+
 __attribute__((no_sanitize("hwaddress")))
 static int __pthread_start(void* arg) {
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
@@ -333,6 +356,7 @@
   // accesses previously made by the creating thread are visible to us.
   thread->startup_handshake_lock.lock();
 
+  __set_stack_and_tls_vma_name(false);
   __init_additional_stacks(thread);
 
   void* result = thread->start_routine(thread->start_routine_arg);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a1e0c45..22cc400 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -129,6 +129,11 @@
   void* mmap_base;
   size_t mmap_size;
 
+  // The location of the VMA to label as the thread's stack_and_tls.
+  void* mmap_base_unguarded;
+  size_t mmap_size_unguarded;
+  char vma_name_buffer[32];
+
   thread_local_dtor* thread_local_dtors;
 
   /*
@@ -147,6 +152,8 @@
 struct ThreadMapping {
   char* mmap_base;
   size_t mmap_size;
+  char* mmap_base_unguarded;
+  size_t mmap_size_unguarded;
 
   char* static_tls;
   char* stack_base;
@@ -162,6 +169,7 @@
 __LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
 __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
 __LIBC_HIDDEN__ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size);
+__LIBC_HIDDEN__ void __set_stack_and_tls_vma_name(bool is_main_thread);
 
 __LIBC_HIDDEN__ pthread_t __pthread_internal_add(pthread_internal_t* thread);
 __LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id, const char* caller);
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 5ca9813..d2c7677 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -52,7 +52,7 @@
 
 static __inline int __ndk_legacy___libc_current_sigrtmin() {
   if (__libc_current_sigrtmin) return __libc_current_sigrtmin();
-  return __SIGRTMIN + 6; /* Should match __libc_current_sigrtmin. */
+  return __SIGRTMIN + 7; /* Should match __libc_current_sigrtmin. */
 }
 
 #undef SIGRTMAX
diff --git a/libc/private/sigrtmin.h b/libc/private/sigrtmin.h
index d78d980..5de1a32 100644
--- a/libc/private/sigrtmin.h
+++ b/libc/private/sigrtmin.h
@@ -39,13 +39,14 @@
 //   33 (__SIGRTMIN + 1)        libbacktrace
 //   34 (__SIGRTMIN + 2)        libcore
 //   35 (__SIGRTMIN + 3)        debuggerd -b
-//   36 (__SIGRTMIN + 4)        heapprofd
+//   36 (__SIGRTMIN + 4)        heapprofd native dumps
 //   37 (__SIGRTMIN + 5)        coverage (libprofile-extras)
+//   38 (__SIGRTMIN + 6)        heapprofd ART managed heap dumps
 //
 // If you change this, also change __ndk_legacy___libc_current_sigrtmin
 // in <android/legacy_signal_inlines.h> to match.
 
-#define __SIGRT_RESERVED 6
+#define __SIGRT_RESERVED 7
 static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
   int (*block)(sigset64_t*, int);
   int (*unblock)(sigset64_t*, int);
@@ -72,5 +73,6 @@
   unblock(&sigset, __SIGRTMIN + 3);
   unblock(&sigset, __SIGRTMIN + 4);
   unblock(&sigset, __SIGRTMIN + 5);
+  unblock(&sigset, __SIGRTMIN + 6);
   return sigset;
 }
diff --git a/libc/symbol_ordering b/libc/symbol_ordering
deleted file mode 100644
index 679d461..0000000
--- a/libc/symbol_ordering
+++ /dev/null
@@ -1,208 +0,0 @@
-# This file is generated by sorting symbols in the .bss section in libc.so by
-# their sizes and taking out symbols that are unique to a target.  By sorting
-# symbols by size, we usually have less dirty pages at runtime, because small
-# symbols are grouped together.
-
-ctl_initialized
-gGlobalsMutating
-global_hashtable_initialized
-gmtcheck.gmt_is_set
-had_conf_error
-je_background_thread_enabled_state
-je_log_init_done
-je_opt_abort
-je_opt_abort_conf
-je_opt_background_thread
-je_opt_junk_alloc
-je_opt_junk_free
-je_opt_stats_print
-je_opt_utrace
-je_opt_xmalloc
-je_opt_zero
-je_tsd_booted
-malloc_disabled_tcache
-malloc_slow_flags
-mmap_flags
-os_overcommits
-restartloop
-_ZL24gHeapprofdInitInProgress
-_ZL27gHeapprofdInitHookInstalled
-_ZL23gZygoteChildProfileable
-_ZZ17__find_icu_symbolPKcE9found_icu
-ru_a
-ru_b
-ru_counter
-ru_g
-ru_msb
-ru_seed
-ru_seed2
-ru_x
-_ZZ12bindresvportE4port
-a0
-__atexit
-atexit_mutex
-b0
-ctl_arenas
-ctl_stats
-__cxa_finalize.call_depth
-daylight
-dirty_decay_ms_default.0
-environ
-error_message_count
-error_one_per_line
-error_print_progname
-__free_hook
-g_atexit_lock
-gGlobalsMutateLock
-global_hashtable
-gmtptr
-handlers
-je_background_thread_info
-je_hooks_arena_new_hook
-je_init_system_thp_mode
-je_malloc_conf
-je_malloc_disable.once_control
-je_malloc_message
-je_narenas_auto
-je_ncpus
-je_nhbins
-je_opt_dirty_decay_ms
-je_opt_metadata_thp
-je_opt_muzzy_decay_ms
-je_opt_narenas
-je_opt_thp
-je_tcache_bin_info
-je_tcache_maxclass
-je_tcaches
-je_tsd_tsd
-lastenv
-lcl_is_set
-lclptr
-locallock
-malloc_disabled_lock
-__malloc_hook
-malloc_initializer
-mbrlen.mbs
-mbtowc.mbs
-__memalign_hook
-muzzy_decay_ms_default.0
-narenas_total
-ncleanups
-optarg
-optreset
-os_page
-p5s
-__progname
-random_mutex
-__realloc_hook
-_res_cache_list_lock
-_res_cache_once
-_res_key
-__res_randomid.__libc_mutex_random
-rs
-_rs_forkdetect._rs_pid
-_rs_forked
-rsx
-ru_pid
-ru_prf
-ru_reseed
-__stack_chk_guard
-stack_nelms
-strtok.last
-suboptarg
-__system_property_area__
-tcaches_avail
-tcaches_past
-timezone
-tmpnam.tmpcount
-ut
-wctomb.mbs
-_ZL11g_arc4_lock
-_ZL13g_locale_once
-_ZL13g_thread_list
-_ZL14syslog_log_tag
-_ZL16gHeapprofdHandle
-_ZL17g_libicuuc_handle
-_ZL18netdClientInitOnce
-_ZL30g_propservice_protocol_version
-_ZN9prop_area13pa_data_size_E
-_ZN9prop_area8pa_size_E
-_ZZ10mbsnrtowcsE15__private_state
-_ZZ10wcsnrtombsE15__private_state
-_ZZ13error_at_lineE9last_file
-_ZZ13error_at_lineE9last_line
-_ZZ14__icu_charTypejE10u_charType
-_ZZ23__bionic_get_shell_pathE7sh_path
-_ZZ23__icu_hasBinaryPropertyj9UPropertyPFiiEE19u_hasBinaryProperty
-_ZZ25__icu_getIntPropertyValuej9UPropertyE21u_getIntPropertyValue
-_ZZ7mbrtowcE15__private_state
-_ZZ7wcrtombE15__private_state
-_ZZ8c16rtombE15__private_state
-_ZZ8c32rtombE15__private_state
-_ZZ8iswcntrlE10u_charType
-_ZZ8iswdigitE9u_isdigit
-_ZZ8iswpunctE9u_ispunct
-_ZZ8mbrtoc16E15__private_state
-_ZZ8mbrtoc32E15__private_state
-_ZZ8towlowerE9u_tolower
-_ZZ8towupperE9u_toupper
-ether_aton.addr
-seed48.sseed
-__dtoa_locks
-_ZGVZ14__icu_charTypejE10u_charType
-_ZGVZ14tzset_unlockedE20persist_sys_timezone
-_ZGVZ17__find_icu_symbolPKcE9found_icu
-_ZGVZ23__bionic_get_shell_pathE7sh_path
-_ZGVZ23__icu_hasBinaryPropertyj9UPropertyPFiiEE19u_hasBinaryProperty
-_ZGVZ25__icu_getIntPropertyValuej9UPropertyE21u_getIntPropertyValue
-_ZGVZ8iswcntrlE10u_charType
-_ZGVZ8iswdigitE9u_isdigit
-_ZGVZ8iswpunctE9u_ispunct
-_ZGVZ8towlowerE9u_tolower
-_ZGVZ8towupperE9u_toupper
-_ZL10gAllocated
-_ZL11gAllocLimit
-_ZL13g_atfork_list
-_ZL6g_lock
-_ZL6g_tags
-je_opt_stats_print_opts
-nuls
-precsize_ntoa.retbuf
-__p_secstodate.output
-ether_ntoa.buf
-inet_ntoa.b
-__p_class.classbuf
-__p_type.typebuf
-__sym_ntop.unname
-__sym_ntos.unname
-_ZL10gFunctions
-freelist
-__p_option.nbuf
-__p_time.nbuf
-_ZL18g_thread_list_lock
-tm
-_ZL8g_locale
-ctl_mtx
-init_lock
-je_arenas_lock
-je_background_thread_lock
-tcaches_mtx
-je_tsd_init_head
-buf_asctime
-__loc_ntoa.tmpbuf
-utmp
-_ZZ14tzset_unlockedE20persist_sys_timezone
-arena_binind_div_info
-__hexdig_D2A
-lcl_TZname
-inet_nsap_ntoa_tmpbuf
-_ZL7key_map
-_ZL17system_properties
-private_mem
-_res_cache_list
-__libc_globals
-tmpnam.buf
-je_extents_rtree
-_nres
-je_arenas
-je_extent_mutex_pool
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 55d684f..e39da81 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -282,6 +282,16 @@
 void count_relocation(RelocationKind kind) {
   ++linker_stats.count[kind];
 }
+
+void print_linker_stats() {
+  PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol (%d cached)",
+         g_argv[0],
+         linker_stats.count[kRelocAbsolute],
+         linker_stats.count[kRelocRelative],
+         linker_stats.count[kRelocCopy],
+         linker_stats.count[kRelocSymbol],
+         linker_stats.count[kRelocSymbolCached]);
+}
 #else
 void count_relocation(RelocationKind) {
 }
@@ -2883,6 +2893,17 @@
   const size_t tls_tp_base = __libc_shared_globals()->static_tls_layout.offset_thread_pointer();
   std::vector<std::pair<TlsDescriptor*, size_t>> deferred_tlsdesc_relocs;
 
+  struct {
+    // Cache key
+    ElfW(Word) sym;
+
+    // Cache value
+    const ElfW(Sym)* s;
+    soinfo* lsi;
+  } symbol_lookup_cache;
+
+  symbol_lookup_cache.sym = 0;
+
   for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
     const auto rel = rel_iterator.next();
     if (rel == nullptr) {
@@ -2926,14 +2947,25 @@
       return false;
     } else {
       sym_name = get_string(symtab_[sym].st_name);
-      const version_info* vi = nullptr;
 
-      if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
-        return false;
-      }
+      if (sym == symbol_lookup_cache.sym) {
+        s = symbol_lookup_cache.s;
+        lsi = symbol_lookup_cache.lsi;
+        count_relocation(kRelocSymbolCached);
+      } else {
+        const version_info* vi = nullptr;
 
-      if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
-        return false;
+        if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+          return false;
+        }
+
+        if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+          return false;
+        }
+
+        symbol_lookup_cache.sym = sym;
+        symbol_lookup_cache.s = s;
+        symbol_lookup_cache.lsi = lsi;
       }
 
       if (s == nullptr) {
diff --git a/linker/linker.h b/linker/linker.h
index 0f30946..782da1c 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -94,11 +94,14 @@
   kRelocRelative,
   kRelocCopy,
   kRelocSymbol,
+  kRelocSymbolCached,
   kRelocMax
 };
 
 void count_relocation(RelocationKind kind);
 
+void print_linker_stats();
+
 soinfo* get_libdl_info(const soinfo& linker_si);
 
 soinfo* find_containing_library(const void* p);
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 612f52f..11d3d29 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -490,11 +490,7 @@
                           static_cast<long long>(t0.tv_usec))));
 #endif
 #if STATS
-  PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol", g_argv[0],
-         linker_stats.count[kRelocAbsolute],
-         linker_stats.count[kRelocRelative],
-         linker_stats.count[kRelocCopy],
-         linker_stats.count[kRelocSymbol]);
+  print_linker_stats();
 #endif
 #if COUNT_PAGES
   {