1 #!/usr/bin/env python2 2 # 3 # Copyright (C) 2015 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the 'License'); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an 'AS IS' BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 # pylint: disable=bad-indentation,bad-continuation 18 import glob 19 import os 20 import re 21 import sys 22 23 import symbols 24 25 only_unwanted = False 26 if len(sys.argv) > 1: 27 if sys.argv[1] in ('-u', '--unwanted'): 28 only_unwanted = True 29 30 toolchain = os.environ['ANDROID_TOOLCHAIN'] 31 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) 32 if arch == 'aarch64': 33 arch = 'arm64' 34 35 def MangleGlibcNameToBionic(name): 36 if name in glibc_to_bionic_names: 37 return glibc_to_bionic_names[name] 38 return name 39 40 def GetNdkIgnored(arch): # pylint: disable=redefined-outer-name 41 ignored_symbols = set() 42 files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' % 43 (os.getenv('ANDROID_BUILD_TOP'), arch)) 44 for f in files: 45 ignored_symbols |= set(open(f, 'r').read().splitlines()) 46 return ignored_symbols 47 48 glibc_to_bionic_names = { 49 '__res_init': 'res_init', 50 '__res_mkquery': 'res_mkquery', 51 '__res_query': 'res_query', 52 '__res_search': 'res_search', 53 '__xpg_basename': '__gnu_basename', 54 } 55 56 glibc = symbols.GetFromSystemSo([ 57 'libc.so.*', 58 'librt.so.*', 59 'libpthread.so.*', 60 'libresolv.so.*', 61 'libm.so.*', 62 'libutil.so.*', 63 ]) 64 65 bionic = symbols.GetFromAndroidSo(['libc.so', 'libm.so']) 66 this_dir = os.path.dirname(os.path.realpath(__file__)) 67 posix = symbols.GetFromTxt(os.path.join(this_dir, 'posix-2013.txt')) 68 ndk_ignored = GetNdkIgnored(arch) 69 70 glibc = set(map(MangleGlibcNameToBionic, glibc)) 71 72 # bionic includes various BSD symbols to ease porting other BSD-licensed code. 73 bsd_stuff = set([ 74 'arc4random', 75 'arc4random_buf', 76 'arc4random_uniform', 77 'basename_r', 78 'dirname_r', 79 'fgetln', 80 'fpurge', 81 'funopen', 82 'funopen64', 83 'gamma_r', 84 'gammaf_r', 85 'getprogname', 86 'setprogname', 87 'strlcat', 88 'strlcpy', 89 'sys_signame', 90 'wcslcat', 91 'wcslcpy', 92 ]) 93 # Some symbols are part of the FORTIFY implementation. 94 FORTIFY_stuff = set([ 95 '__FD_CLR_chk', 96 '__FD_ISSET_chk', 97 '__FD_SET_chk', 98 '__fwrite_chk', 99 '__memchr_chk', 100 '__memrchr_chk', 101 '__pwrite64_chk', 102 '__pwrite_chk', 103 '__stack_chk_guard', 104 '__stpncpy_chk2', 105 '__strchr_chk', 106 '__strlcat_chk', 107 '__strlcpy_chk', 108 '__strlen_chk', 109 '__strncpy_chk2', 110 '__strrchr_chk', 111 '__umask_chk', 112 '__write_chk', 113 ]) 114 # Some symbols are used to implement public functions/macros. 115 macro_stuff = set([ 116 '__assert2', 117 '__errno', 118 '__fe_dfl_env', 119 '__get_h_errno', 120 '__gnu_strerror_r', 121 '__fpclassifyd', 122 '__isfinite', 123 '__isfinitef', 124 '__isfinitel', 125 '__isnormal', 126 '__isnormalf', 127 '__isnormall', 128 '__sF', 129 '__pthread_cleanup_pop', 130 '__pthread_cleanup_push', 131 ]) 132 # bionic exposes various Linux features that glibc doesn't. 133 linux_stuff = set([ 134 'getauxval', 135 'gettid', 136 'pthread_gettid_np', 137 'tgkill', 138 ]) 139 # Some standard stuff isn't yet in the versions of glibc we're using. 140 std_stuff = set([ 141 'at_quick_exit', 142 'c16rtomb', 143 'c32rtomb', 144 'mbrtoc16', 145 'mbrtoc32', 146 ]) 147 # These have mangled names in glibc, with a macro taking the "obvious" name. 148 weird_stuff = set([ 149 'fstat', 150 'fstat64', 151 'fstatat', 152 'fstatat64', 153 'isfinite', 154 'isfinitef', 155 'isfinitel', 156 'isnormal', 157 'isnormalf', 158 'isnormall', 159 'lstat', 160 'lstat64', 161 'mknod', 162 'mknodat', 163 'stat', 164 'stat64', 165 'optreset', 166 'sigsetjmp', 167 ]) 168 # These exist in glibc, but under slightly different names (generally one extra 169 # or one fewer _). TODO: check against glibc names. 170 libresolv_stuff = set([ 171 '__res_send_setqhook', 172 '__res_send_setrhook', 173 '_resolv_delete_cache_for_net', 174 '_resolv_flush_cache_for_net', 175 '_resolv_set_nameservers_for_net', 176 'dn_expand', 177 'nsdispatch', 178 ]) 179 # Implementation details we know we export (and can't get away from). 180 known = set([ 181 '_ctype_', 182 '__libc_init', 183 ]) 184 # POSIX has some stuff that's too stupid for words (a64l) or not actually 185 # implemented in glibc unless you count always failing with ENOSYS as 186 # being implemented (fattach). 187 in_posix_and_glibc_but_actually_dead = set([ 188 'a64l', 189 'fattach', 190 'fdetach', 191 'getmsg', 192 'getpmsg', 193 'isastream', 194 'l64a', 195 'putmsg', 196 'putpmsg', 197 ]) 198 199 posix = posix - in_posix_and_glibc_but_actually_dead 200 glibc = glibc - in_posix_and_glibc_but_actually_dead 201 202 if not only_unwanted: 203 #print 'glibc:' 204 #for symbol in sorted(glibc): 205 # print symbol 206 #print 207 208 #print 'bionic:' 209 #for symbol in sorted(bionic): 210 # print symbol 211 #print 212 213 print 'in glibc (but not posix) but not bionic:' 214 for symbol in sorted((glibc - posix).difference(bionic)): 215 print symbol 216 print 217 218 print 'in posix (and implemented in glibc) but not bionic:' 219 for symbol in sorted((posix.intersection(glibc)).difference(bionic)): 220 print symbol 221 print 222 223 print 'in bionic but not glibc:' 224 225 allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | 226 std_stuff | weird_stuff | libresolv_stuff | known) 227 for symbol in sorted((bionic - allowed_stuff).difference(glibc)): 228 if symbol in ndk_ignored: 229 symbol += '*' 230 print symbol 231 232 sys.exit(0) 233