| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 1 | #!/usr/bin/python | 
|  | 2 |  | 
|  | 3 | import glob | 
|  | 4 | import os | 
|  | 5 | import re | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 6 | import subprocess | 
|  | 7 | import sys | 
|  | 8 |  | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 9 | only_unwanted = False | 
|  | 10 | if len(sys.argv) > 1: | 
|  | 11 | if sys.argv[1] in ('-u', '--unwanted'): | 
|  | 12 | only_unwanted = True | 
|  | 13 |  | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 14 | toolchain = os.environ['ANDROID_TOOLCHAIN'] | 
|  | 15 | arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 16 | if arch == 'aarch64': | 
|  | 17 | arch = 'arm64' | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 18 |  | 
|  | 19 | def GetSymbolsFromSo(so_file): | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 20 | # Example readelf output: | 
|  | 21 | #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf | 
|  | 22 | #   266: 00016244     4 FUNC    GLOBAL DEFAULT    8 dremf | 
|  | 23 | #   267: 00019018     4 OBJECT  GLOBAL DEFAULT   11 __fe_dfl_env | 
|  | 24 | #   268: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_dcmplt | 
|  | 25 |  | 
|  | 26 | r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)') | 
|  | 27 |  | 
|  | 28 | symbols = set() | 
|  | 29 |  | 
|  | 30 | for line in subprocess.check_output(['readelf', '--dyn-syms', '-W', so_file]).split('\n'): | 
| Elliott Hughes | e8e4534 | 2014-06-13 11:50:07 -0700 | [diff] [blame] | 31 | if ' HIDDEN ' in line or ' UND ' in line: | 
|  | 32 | continue | 
|  | 33 | m = r.match(line) | 
|  | 34 | if m: | 
|  | 35 | symbol = m.group(2) | 
|  | 36 | symbol = re.sub('@.*', '', symbol) | 
|  | 37 | symbols.add(symbol) | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 38 |  | 
|  | 39 | return symbols | 
|  | 40 |  | 
|  | 41 | def GetSymbolsFromAndroidSo(*files): | 
|  | 42 | symbols = set() | 
|  | 43 | for f in files: | 
|  | 44 | symbols = symbols | GetSymbolsFromSo('%s/system/lib64/%s' % (os.environ['ANDROID_PRODUCT_OUT'], f)) | 
|  | 45 | return symbols | 
|  | 46 |  | 
|  | 47 | def GetSymbolsFromSystemSo(*files): | 
|  | 48 | symbols = set() | 
|  | 49 | for f in files: | 
|  | 50 | f = glob.glob('/lib/x86_64-linux-gnu/%s' % f)[-1] | 
|  | 51 | symbols = symbols | GetSymbolsFromSo(f) | 
|  | 52 | return symbols | 
|  | 53 |  | 
| Elliott Hughes | e8e4534 | 2014-06-13 11:50:07 -0700 | [diff] [blame] | 54 | def MangleGlibcNameToBionic(name): | 
|  | 55 | if name in glibc_to_bionic_names: | 
|  | 56 | return glibc_to_bionic_names[name] | 
|  | 57 | return name | 
|  | 58 |  | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 59 | def GetNdkIgnored(): | 
|  | 60 | global arch | 
|  | 61 | symbols = set() | 
|  | 62 | files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' % | 
|  | 63 | (os.getenv('ANDROID_BUILD_TOP'), arch)) | 
|  | 64 | for f in files: | 
|  | 65 | symbols |= set(open(f, 'r').read().splitlines()) | 
|  | 66 | return symbols | 
|  | 67 |  | 
| Elliott Hughes | e8e4534 | 2014-06-13 11:50:07 -0700 | [diff] [blame] | 68 | glibc_to_bionic_names = { | 
|  | 69 | '__res_init': 'res_init', | 
|  | 70 | '__res_mkquery': 'res_mkquery', | 
|  | 71 | '__res_query': 'res_query', | 
|  | 72 | '__res_search': 'res_search', | 
| Dan Albert | 2320b02 | 2014-08-21 11:36:07 -0700 | [diff] [blame] | 73 | '__xpg_basename': '__gnu_basename', | 
| Elliott Hughes | e8e4534 | 2014-06-13 11:50:07 -0700 | [diff] [blame] | 74 | } | 
|  | 75 |  | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 76 | glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*') | 
|  | 77 | bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so') | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 78 | ndk_ignored = GetNdkIgnored() | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 79 |  | 
| Elliott Hughes | e8e4534 | 2014-06-13 11:50:07 -0700 | [diff] [blame] | 80 | glibc = map(MangleGlibcNameToBionic, glibc) | 
|  | 81 |  | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 82 | # bionic includes various BSD symbols to ease porting other BSD-licensed code. | 
|  | 83 | bsd_stuff = set([ | 
| Elliott Hughes | 45bf4c3 | 2014-05-22 18:53:21 -0700 | [diff] [blame] | 84 | 'basename_r', | 
|  | 85 | 'dirname_r', | 
|  | 86 | 'fgetln', | 
|  | 87 | 'fpurge', | 
|  | 88 | 'funopen', | 
|  | 89 | 'gamma_r', | 
|  | 90 | 'gammaf_r', | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 91 | 'getprogname', | 
|  | 92 | 'setprogname', | 
|  | 93 | 'strlcat', | 
|  | 94 | 'strlcpy', | 
| Elliott Hughes | 45bf4c3 | 2014-05-22 18:53:21 -0700 | [diff] [blame] | 95 | 'sys_signame', | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 96 | 'wcslcat', | 
|  | 97 | 'wcslcpy' | 
|  | 98 | ]) | 
|  | 99 | # Some symbols are part of the FORTIFY implementation. | 
|  | 100 | FORTIFY_stuff = set([ | 
|  | 101 | '__FD_CLR_chk', | 
|  | 102 | '__FD_ISSET_chk', | 
|  | 103 | '__FD_SET_chk', | 
|  | 104 | '__stack_chk_guard', | 
|  | 105 | '__stpncpy_chk2', | 
|  | 106 | '__strchr_chk', | 
|  | 107 | '__strlcat_chk', | 
|  | 108 | '__strlcpy_chk', | 
|  | 109 | '__strlen_chk', | 
|  | 110 | '__strncpy_chk2', | 
|  | 111 | '__strrchr_chk', | 
|  | 112 | '__umask_chk' | 
|  | 113 | ]) | 
| Elliott Hughes | b497c43 | 2014-05-20 20:37:56 -0700 | [diff] [blame] | 114 | # Some symbols are used to implement public macros. | 
|  | 115 | macro_stuff = set([ | 
|  | 116 | '__assert2', | 
|  | 117 | '__errno', | 
|  | 118 | '__fe_dfl_env', | 
|  | 119 | '__get_h_errno', | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 120 | '__fpclassifyd', | 
|  | 121 | '__isfinite', | 
|  | 122 | '__isfinitef', | 
|  | 123 | '__isfinitel', | 
|  | 124 | '__isnormal', | 
|  | 125 | '__isnormalf', | 
|  | 126 | '__isnormall', | 
|  | 127 | '__sF', | 
|  | 128 | '__pthread_cleanup_pop', | 
|  | 129 | '__pthread_cleanup_push', | 
| Elliott Hughes | b497c43 | 2014-05-20 20:37:56 -0700 | [diff] [blame] | 130 | ]) | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 131 | # bionic exposes various Linux features that glibc doesn't. | 
|  | 132 | linux_stuff = set([ | 
|  | 133 | 'getauxval', | 
|  | 134 | 'gettid', | 
|  | 135 | 'tgkill' | 
|  | 136 | ]) | 
|  | 137 | # Some standard stuff isn't yet in the versions of glibc we're using. | 
|  | 138 | std_stuff = set([ | 
| Elliott Hughes | f6b1d43 | 2014-06-06 15:20:50 -0700 | [diff] [blame] | 139 | 'at_quick_exit', | 
|  | 140 | 'c16rtomb', | 
|  | 141 | 'c32rtomb', | 
|  | 142 | 'mbrtoc16', | 
|  | 143 | 'mbrtoc32', | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 144 | ]) | 
|  | 145 | # These have mangled names in glibc, with a macro taking the "obvious" name. | 
|  | 146 | weird_stuff = set([ | 
|  | 147 | 'fstat', | 
|  | 148 | 'fstat64', | 
|  | 149 | 'fstatat', | 
|  | 150 | 'fstatat64', | 
|  | 151 | 'isfinite', | 
|  | 152 | 'isfinitef', | 
|  | 153 | 'isfinitel', | 
|  | 154 | 'isnormal', | 
|  | 155 | 'isnormalf', | 
|  | 156 | 'isnormall', | 
|  | 157 | 'lstat', | 
|  | 158 | 'lstat64', | 
|  | 159 | 'mknod', | 
|  | 160 | 'mknodat', | 
|  | 161 | 'stat', | 
|  | 162 | 'stat64', | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 163 | 'optreset', | 
|  | 164 | 'sigsetjmp', | 
|  | 165 | ]) | 
|  | 166 | # These exist in glibc, but under slightly different names (generally one extra | 
|  | 167 | # or one fewer _). TODO: check against glibc names. | 
|  | 168 | libresolv_stuff = set([ | 
|  | 169 | '__res_send_setqhook', | 
|  | 170 | '__res_send_setrhook', | 
|  | 171 | '_resolv_flush_cache_for_net', | 
|  | 172 | '_resolv_set_nameservers_for_net', | 
|  | 173 | 'dn_expand', | 
|  | 174 | 'nsdispatch', | 
|  | 175 | ]) | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 176 | # Implementation details we know we export (and can't get away from). | 
|  | 177 | known = set([ | 
|  | 178 | '_ctype_', | 
|  | 179 | '__libc_init', | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 180 | ]) | 
|  | 181 |  | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 182 | if not only_unwanted: | 
|  | 183 | print 'glibc:' | 
|  | 184 | for symbol in sorted(glibc): | 
|  | 185 | print symbol | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 186 |  | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 187 | print | 
|  | 188 | print 'bionic:' | 
|  | 189 | for symbol in sorted(bionic): | 
|  | 190 | print symbol | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 191 |  | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 192 | print | 
|  | 193 | print 'in bionic but not glibc:' | 
|  | 194 |  | 
|  | 195 | allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | | 
| Dan Albert | fd5ee9a | 2014-08-15 14:20:04 -0700 | [diff] [blame] | 196 | std_stuff | weird_stuff | libresolv_stuff | known) | 
| Elliott Hughes | b497c43 | 2014-05-20 20:37:56 -0700 | [diff] [blame] | 197 | for symbol in sorted((bionic - allowed_stuff).difference(glibc)): | 
| Dan Albert | 76212ee | 2014-08-13 13:04:28 -0700 | [diff] [blame] | 198 | if symbol in ndk_ignored: | 
|  | 199 | symbol += '*' | 
| Elliott Hughes | 5a93e88 | 2014-05-16 14:44:38 -0700 | [diff] [blame] | 200 | print symbol | 
|  | 201 |  | 
|  | 202 | sys.exit(0) |