1#!/usr/bin/env python3 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 18import glob 19import os 20import re 21import sys 22 23import symbols 24 25only_unwanted = False 26if len(sys.argv) > 1: 27 if sys.argv[1] in ('-u', '--unwanted'): 28 only_unwanted = True 29 30toolchain = os.environ['ANDROID_TOOLCHAIN'] 31arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) 32if arch == 'aarch64': 33 arch = 'arm64' 34 35def MangleGlibcNameToBionic(name): 36 if name in glibc_to_bionic_names: 37 return glibc_to_bionic_names[name] 38 return name 39 40def 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 48glibc_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 56glibc = symbols.GetFromSystemSo([ 57 'libc.so.*', 58 'librt.so.*', 59 'libpthread.so.*', 60 'libresolv.so.*', 61 'libm.so.*', 62 'libutil.so.*', 63]) 64 65bionic = symbols.GetFromAndroidSo(['libc.so', 'libm.so']) 66this_dir = os.path.dirname(os.path.realpath(__file__)) 67posix = symbols.GetFromTxt(os.path.join(this_dir, 'posix-2013.txt')) 68ndk_ignored = GetNdkIgnored(arch) 69 70glibc = set(map(MangleGlibcNameToBionic, glibc)) 71 72# bionic includes various BSD symbols to ease porting other BSD-licensed code. 73bsd_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. 94FORTIFY_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 '__sendto_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 '__write_chk', 114]) 115# Some symbols are used to implement public functions/macros. 116macro_stuff = set([ 117 '__assert2', 118 '__errno', 119 '__fe_dfl_env', 120 '__get_h_errno', 121 '__gnu_strerror_r', 122 '__fpclassifyd', 123 '__isfinite', 124 '__isfinitef', 125 '__isfinitel', 126 '__isnormal', 127 '__isnormalf', 128 '__isnormall', 129 '__sF', 130 '__pthread_cleanup_pop', 131 '__pthread_cleanup_push', 132]) 133# bionic exposes various Linux features that glibc doesn't. 134linux_stuff = set([ 135 'getauxval', 136 'gettid', 137 'pthread_gettid_np', 138 'tgkill', 139]) 140# Some standard stuff isn't yet in the versions of glibc we're using. 141std_stuff = set([ 142 'at_quick_exit', 143 'c16rtomb', 144 'c32rtomb', 145 'mbrtoc16', 146 'mbrtoc32', 147]) 148# These have mangled names in glibc, with a macro taking the "obvious" name. 149weird_stuff = set([ 150 'fstat', 151 'fstat64', 152 'fstatat', 153 'fstatat64', 154 'isfinite', 155 'isfinitef', 156 'isfinitel', 157 'isnormal', 158 'isnormalf', 159 'isnormall', 160 'lstat', 161 'lstat64', 162 'mknod', 163 'mknodat', 164 'stat', 165 'stat64', 166 'optreset', 167 'sigsetjmp', 168]) 169# These exist in glibc, but under slightly different names (generally one extra 170# or one fewer _). TODO: check against glibc names. 171libresolv_stuff = set([ 172 '__res_send_setqhook', 173 '__res_send_setrhook', 174 '_resolv_delete_cache_for_net', 175 '_resolv_flush_cache_for_net', 176 '_resolv_set_nameservers_for_net', 177 'dn_expand', 178 'nsdispatch', 179]) 180# Implementation details we know we export (and can't get away from). 181known = set([ 182 '_ctype_', 183 '__libc_init', 184]) 185# POSIX has some stuff that's unusable in the modern world (a64l) or not 186# actually implemented in glibc unless you count always failing with ENOSYS 187# as being implemented (fattach). Other stuff (fmtmsg) isn't used in any 188# codebase I have access to, internal or external. 189in_posix_and_glibc_but_dead_or_useless = set([ 190 'a64l', # obsolete 191 'confstr', # obsolete 192 'endutxent', # no utmp on Android 193 'fattach', # <stropts.h> marked obsolescent 194 'fdetach', # <stropts.h> marked obsolescent 195 'fmtmsg', # unused 196 'getdate', # unused 197 'getdate_err', # unused 198 'gethostid', # obsolete 199 'getmsg', # <stropts.h> marked obsolescent 200 'getpmsg', # <stropts.h> marked obsolescent 201 'getutxent', # no utmp on Android 202 'getutxid', # no utmp on Android 203 'getutxline', # no utmp on Android 204 'isastream', # <stropts.h> marked obsolescent 205 'l64a', # obsolete 206 'mq_close', # disallowed by SELinux 207 'mq_getattr', # disallowed by SELinux 208 'mq_notify', # disallowed by SELinux 209 'mq_open', # disallowed by SELinux 210 'mq_receive', # disallowed by SELinux 211 'mq_send', # disallowed by SELinux 212 'mq_setattr', # disallowed by SELinux 213 'mq_timedreceive', # disallowed by SELinux 214 'mq_timedsend', # disallowed by SELinux 215 'mq_unlink', # disallowed by SELinux 216 'pthread_getconcurrency', # marked obsolescent 217 'pthread_setconcurrency', # marked obsolescent 218 'putmsg', # <stropts.h> marked obsolescent 219 'putpmsg', # <stropts.h> marked obsolescent 220 'pututxline', # no utmp on Android 221 'shm_open', # disallowed by SELinux 222 'shm_unlink', # disallowed by SELinux 223 'setutxent', # no utmp on Android 224 'sockatmark', # obsolete (https://tools.ietf.org/html/rfc6093) 225 'strfmon', # icu4c 226 'strfmon_l', # icu4c 227 'ulimit', # <ulimit.h> marked obsolescent 228]) 229 230posix = posix - in_posix_and_glibc_but_dead_or_useless 231glibc = glibc - in_posix_and_glibc_but_dead_or_useless 232 233if not only_unwanted: 234 #print('glibc:') 235 #for symbol in sorted(glibc): 236 # print(symbol) 237 #print() 238 239 #print('bionic:') 240 #for symbol in sorted(bionic): 241 # print(symbol) 242 #print() 243 244 print('in glibc (but not posix) but not bionic:') 245 for symbol in sorted((glibc - posix).difference(bionic)): 246 print(symbol) 247 print() 248 249 print('in posix (and implemented in glibc) but not bionic:') 250 for symbol in sorted((posix.intersection(glibc)).difference(bionic)): 251 print(symbol) 252 print() 253 254 print('in bionic but not glibc:') 255 256allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | 257 std_stuff | weird_stuff | libresolv_stuff | known) 258for symbol in sorted((bionic - allowed_stuff).difference(glibc)): 259 if symbol in ndk_ignored: 260 symbol += '*' 261 print(symbol) 262 263sys.exit(0) 264