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