Merge "Have stdatomic.h punt to C++ atomic when possible"
diff --git a/libc/Android.mk b/libc/Android.mk
index 3b6e3cb..72ea6ed 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -279,7 +279,6 @@
     upstream-netbsd/lib/libc/regex/regerror.c \
     upstream-netbsd/lib/libc/regex/regexec.c \
     upstream-netbsd/lib/libc/regex/regfree.c \
-    upstream-netbsd/lib/libc/resolv/mtctxres.c \
     upstream-netbsd/lib/libc/stdlib/bsearch.c \
     upstream-netbsd/lib/libc/stdlib/div.c \
     upstream-netbsd/lib/libc/stdlib/drand48.c \
@@ -635,6 +634,7 @@
     $(call all-c-files-under,dns) \
     upstream-netbsd/lib/libc/isc/ev_streams.c \
     upstream-netbsd/lib/libc/isc/ev_timers.c \
+    upstream-netbsd/lib/libc/resolv/mtctxres.c \
 
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 4c3fd7f..ddb49ce 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -92,7 +92,7 @@
   g_locale.int_n_sign_posn = CHAR_MAX;
 }
 
-size_t __mb_cur_max() {
+size_t __ctype_get_mb_cur_max() {
   locale_t l = reinterpret_cast<locale_t>(pthread_getspecific(g_uselocale_key));
   if (l == nullptr || l == LC_GLOBAL_LOCALE) {
     return __bionic_current_locale_is_utf8 ? 4 : 1;
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index a5eb3d1..52f71dd 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -161,8 +161,8 @@
 extern int	wctomb(char *, wchar_t);
 extern size_t	wcstombs(char *, const wchar_t *, size_t);
 
-extern size_t __mb_cur_max(void);
-#define MB_CUR_MAX __mb_cur_max()
+extern size_t __ctype_get_mb_cur_max(void);
+#define MB_CUR_MAX __ctype_get_mb_cur_max()
 
 __END_DECLS
 
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 58a10e0..ffff964 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -3,12 +3,18 @@
 import glob
 import os
 import re
-import string
 import subprocess
 import sys
 
+only_unwanted = False
+if len(sys.argv) > 1:
+  if sys.argv[1] in ('-u', '--unwanted'):
+    only_unwanted = True
+
 toolchain = os.environ['ANDROID_TOOLCHAIN']
 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
+if arch == 'aarch64':
+  arch = 'arm64'
 
 def GetSymbolsFromSo(so_file):
   # Example readelf output:
@@ -50,6 +56,15 @@
     return glibc_to_bionic_names[name]
   return name
 
+def GetNdkIgnored():
+  global arch
+  symbols = set()
+  files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' %
+                    (os.getenv('ANDROID_BUILD_TOP'), arch))
+  for f in files:
+    symbols |= set(open(f, 'r').read().splitlines())
+  return symbols
+
 glibc_to_bionic_names = {
   '__res_init': 'res_init',
   '__res_mkquery': 'res_mkquery',
@@ -59,6 +74,7 @@
 
 glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
 bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
+ndk_ignored = GetNdkIgnored()
 
 glibc = map(MangleGlibcNameToBionic, glibc)
 
@@ -100,6 +116,16 @@
   '__errno',
   '__fe_dfl_env',
   '__get_h_errno',
+  '__fpclassifyd',
+  '__isfinite',
+  '__isfinitef',
+  '__isfinitel',
+  '__isnormal',
+  '__isnormalf',
+  '__isnormall',
+  '__sF',
+  '__pthread_cleanup_pop',
+  '__pthread_cleanup_push',
 ])
 # bionic exposes various Linux features that glibc doesn't.
 linux_stuff = set([
@@ -133,21 +159,62 @@
   'mknodat',
   'stat',
   'stat64',
+  'optreset',
+  'sigsetjmp',
+])
+# These exist in glibc, but under slightly different names (generally one extra
+# or one fewer _). TODO: check against glibc names.
+libresolv_stuff = set([
+  '__res_send_setqhook',
+  '__res_send_setrhook',
+  '_resolv_flush_cache_for_net',
+  '_resolv_set_nameservers_for_net',
+  'dn_expand',
+  'nsdispatch',
+])
+# libstdc++ stuff we took over.
+libstdcxx_stuff = set([
+  # new, delete, nothrow
+  '_ZSt7nothrow',
+  '_ZdaPv',
+  '_ZdaPvRKSt9nothrow_t',
+  '_ZdlPv',
+  '_ZdlPvRKSt9nothrow_t',
+  '_Znam',
+  '_ZnamRKSt9nothrow_t',
+  '_Znwm',
+  '_ZnwmRKSt9nothrow_t',
+
+  '__cxa_guard_abort',
+  '__cxa_guard_acquire',
+  '__cxa_guard_release',
+  '__cxa_pure_virtual',
+])
+# Implementation details we know we export (and can't get away from).
+known = set([
+  '_ctype_',
+  '__libc_init',
 ])
 
-print 'glibc:'
-for symbol in sorted(glibc):
-  print symbol
+if not only_unwanted:
+  print 'glibc:'
+  for symbol in sorted(glibc):
+    print symbol
 
-print
-print 'bionic:'
-for symbol in sorted(bionic):
-  print symbol
+  print
+  print 'bionic:'
+  for symbol in sorted(bionic):
+    print symbol
 
-print
-print 'in bionic but not glibc:'
-allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff)
+  print
+  print 'in bionic but not glibc:'
+
+allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
+                 std_stuff | weird_stuff | libresolv_stuff | libstdcxx_stuff |
+                 known)
 for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
+  if symbol in ndk_ignored:
+    symbol += '*'
   print symbol
 
 sys.exit(0)
diff --git a/linker/Android.mk b/linker/Android.mk
index 68e801d..5853c90 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -57,6 +57,10 @@
 LOCAL_MODULE_STEM_64 := linker64
 LOCAL_MULTILIB := both
 
+# Leave the symbols in the shared library so that stack unwinders can produce
+# meaningful name resolution.
+LOCAL_STRIP_MODULE := keep_symbols
+
 include $(LOCAL_PATH)/linker_executable.mk
 ifdef TARGET_2ND_ARCH
 LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX)