1#!/usr/bin/python 2 3import glob 4import os 5import re 6import string 7import subprocess 8import sys 9 10toolchain = os.environ['ANDROID_TOOLCHAIN'] 11arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) 12 13def GetSymbolsFromSo(so_file): 14 # Example readelf output: 15 # 264: 0001623c 4 FUNC GLOBAL DEFAULT 8 cabsf 16 # 266: 00016244 4 FUNC GLOBAL DEFAULT 8 dremf 17 # 267: 00019018 4 OBJECT GLOBAL DEFAULT 11 __fe_dfl_env 18 # 268: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_dcmplt 19 20 r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)') 21 22 symbols = set() 23 24 for line in subprocess.check_output(['readelf', '--dyn-syms', '-W', so_file]).split('\n'): 25 if ' HIDDEN ' in line or ' UND ' in line: 26 continue 27 m = r.match(line) 28 if m: 29 symbol = m.group(2) 30 symbol = re.sub('@.*', '', symbol) 31 symbols.add(symbol) 32 33 return symbols 34 35def GetSymbolsFromAndroidSo(*files): 36 symbols = set() 37 for f in files: 38 symbols = symbols | GetSymbolsFromSo('%s/system/lib64/%s' % (os.environ['ANDROID_PRODUCT_OUT'], f)) 39 return symbols 40 41def GetSymbolsFromSystemSo(*files): 42 symbols = set() 43 for f in files: 44 f = glob.glob('/lib/x86_64-linux-gnu/%s' % f)[-1] 45 symbols = symbols | GetSymbolsFromSo(f) 46 return symbols 47 48def MangleGlibcNameToBionic(name): 49 if name in glibc_to_bionic_names: 50 return glibc_to_bionic_names[name] 51 return name 52 53glibc_to_bionic_names = { 54 '__res_init': 'res_init', 55 '__res_mkquery': 'res_mkquery', 56 '__res_query': 'res_query', 57 '__res_search': 'res_search', 58} 59 60glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*') 61bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so') 62 63glibc = map(MangleGlibcNameToBionic, glibc) 64 65# bionic includes various BSD symbols to ease porting other BSD-licensed code. 66bsd_stuff = set([ 67 'basename_r', 68 'dirname_r', 69 'fgetln', 70 'fpurge', 71 'funopen', 72 'gamma_r', 73 'gammaf_r', 74 'getprogname', 75 'setprogname', 76 'strlcat', 77 'strlcpy', 78 'sys_signame', 79 'wcslcat', 80 'wcslcpy' 81]) 82# Some symbols are part of the FORTIFY implementation. 83FORTIFY_stuff = set([ 84 '__FD_CLR_chk', 85 '__FD_ISSET_chk', 86 '__FD_SET_chk', 87 '__stack_chk_guard', 88 '__stpncpy_chk2', 89 '__strchr_chk', 90 '__strlcat_chk', 91 '__strlcpy_chk', 92 '__strlen_chk', 93 '__strncpy_chk2', 94 '__strrchr_chk', 95 '__umask_chk' 96]) 97# Some symbols are used to implement public macros. 98macro_stuff = set([ 99 '__assert2', 100 '__errno', 101 '__fe_dfl_env', 102 '__get_h_errno', 103]) 104# bionic exposes various Linux features that glibc doesn't. 105linux_stuff = set([ 106 'getauxval', 107 'gettid', 108 'tgkill' 109]) 110# Some standard stuff isn't yet in the versions of glibc we're using. 111std_stuff = set([ 112 'at_quick_exit', 113 'c16rtomb', 114 'c32rtomb', 115 'mbrtoc16', 116 'mbrtoc32', 117]) 118# These have mangled names in glibc, with a macro taking the "obvious" name. 119weird_stuff = set([ 120 'fstat', 121 'fstat64', 122 'fstatat', 123 'fstatat64', 124 'isfinite', 125 'isfinitef', 126 'isfinitel', 127 'isnormal', 128 'isnormalf', 129 'isnormall', 130 'lstat', 131 'lstat64', 132 'mknod', 133 'mknodat', 134 'stat', 135 'stat64', 136]) 137 138print 'glibc:' 139for symbol in sorted(glibc): 140 print symbol 141 142print 143print 'bionic:' 144for symbol in sorted(bionic): 145 print symbol 146 147print 148print 'in bionic but not glibc:' 149allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff) 150for symbol in sorted((bionic - allowed_stuff).difference(glibc)): 151 print symbol 152 153sys.exit(0) 154