| #!/usr/bin/python | 
 |  | 
 | import glob | 
 | import os | 
 | import re | 
 | import string | 
 | import subprocess | 
 | import sys | 
 |  | 
 | toolchain = os.environ['ANDROID_TOOLCHAIN'] | 
 | arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) | 
 |  | 
 | def GetSymbolsFromSo(so_file): | 
 |   # Example readelf output: | 
 |   #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf | 
 |   #   266: 00016244     4 FUNC    GLOBAL DEFAULT    8 dremf | 
 |   #   267: 00019018     4 OBJECT  GLOBAL DEFAULT   11 __fe_dfl_env | 
 |   #   268: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_dcmplt | 
 |  | 
 |   r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)') | 
 |  | 
 |   symbols = set() | 
 |  | 
 |   for line in subprocess.check_output(['readelf', '--dyn-syms', '-W', so_file]).split('\n'): | 
 |     if ' HIDDEN ' in line or ' UND ' in line: | 
 |       continue | 
 |     m = r.match(line) | 
 |     if m: | 
 |       symbol = m.group(2) | 
 |       symbol = re.sub('@.*', '', symbol) | 
 |       symbols.add(symbol) | 
 |  | 
 |   return symbols | 
 |  | 
 | def GetSymbolsFromAndroidSo(*files): | 
 |   symbols = set() | 
 |   for f in files: | 
 |     symbols = symbols | GetSymbolsFromSo('%s/system/lib64/%s' % (os.environ['ANDROID_PRODUCT_OUT'], f)) | 
 |   return symbols | 
 |  | 
 | def GetSymbolsFromSystemSo(*files): | 
 |   symbols = set() | 
 |   for f in files: | 
 |     f = glob.glob('/lib/x86_64-linux-gnu/%s' % f)[-1] | 
 |     symbols = symbols | GetSymbolsFromSo(f) | 
 |   return symbols | 
 |  | 
 | def MangleGlibcNameToBionic(name): | 
 |   if name in glibc_to_bionic_names: | 
 |     return glibc_to_bionic_names[name] | 
 |   return name | 
 |  | 
 | glibc_to_bionic_names = { | 
 |   '__res_init': 'res_init', | 
 |   '__res_mkquery': 'res_mkquery', | 
 |   '__res_query': 'res_query', | 
 |   '__res_search': 'res_search', | 
 | } | 
 |  | 
 | glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*') | 
 | bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so') | 
 |  | 
 | glibc = map(MangleGlibcNameToBionic, glibc) | 
 |  | 
 | # bionic includes various BSD symbols to ease porting other BSD-licensed code. | 
 | bsd_stuff = set([ | 
 |   'basename_r', | 
 |   'dirname_r', | 
 |   'fgetln', | 
 |   'fpurge', | 
 |   'funopen', | 
 |   'gamma_r', | 
 |   'gammaf_r', | 
 |   'getprogname', | 
 |   'setprogname', | 
 |   'strlcat', | 
 |   'strlcpy', | 
 |   'sys_signame', | 
 |   'wcslcat', | 
 |   'wcslcpy' | 
 | ]) | 
 | # Some symbols are part of the FORTIFY implementation. | 
 | FORTIFY_stuff = set([ | 
 |   '__FD_CLR_chk', | 
 |   '__FD_ISSET_chk', | 
 |   '__FD_SET_chk', | 
 |   '__stack_chk_guard', | 
 |   '__stpncpy_chk2', | 
 |   '__strchr_chk', | 
 |   '__strlcat_chk', | 
 |   '__strlcpy_chk', | 
 |   '__strlen_chk', | 
 |   '__strncpy_chk2', | 
 |   '__strrchr_chk', | 
 |   '__umask_chk' | 
 | ]) | 
 | # Some symbols are used to implement public macros. | 
 | macro_stuff = set([ | 
 |   '__assert2', | 
 |   '__errno', | 
 |   '__fe_dfl_env', | 
 |   '__get_h_errno', | 
 | ]) | 
 | # bionic exposes various Linux features that glibc doesn't. | 
 | linux_stuff = set([ | 
 |   'getauxval', | 
 |   'gettid', | 
 |   'tgkill' | 
 | ]) | 
 | # Some standard stuff isn't yet in the versions of glibc we're using. | 
 | std_stuff = set([ | 
 |   'at_quick_exit', | 
 |   'c16rtomb', | 
 |   'c32rtomb', | 
 |   'mbrtoc16', | 
 |   'mbrtoc32', | 
 | ]) | 
 | # These have mangled names in glibc, with a macro taking the "obvious" name. | 
 | weird_stuff = set([ | 
 |   'fstat', | 
 |   'fstat64', | 
 |   'fstatat', | 
 |   'fstatat64', | 
 |   'isfinite', | 
 |   'isfinitef', | 
 |   'isfinitel', | 
 |   'isnormal', | 
 |   'isnormalf', | 
 |   'isnormall', | 
 |   'lstat', | 
 |   'lstat64', | 
 |   'mknod', | 
 |   'mknodat', | 
 |   'stat', | 
 |   'stat64', | 
 | ]) | 
 |  | 
 | print 'glibc:' | 
 | for symbol in sorted(glibc): | 
 |   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) | 
 | for symbol in sorted((bionic - allowed_stuff).difference(glibc)): | 
 |   print symbol | 
 |  | 
 | sys.exit(0) |