check-symbols-glibc.py revision b497c43336475ff5f0248436510a7fbeccfa96a9
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 'getprogname', 55 'setprogname', 56 'strlcat', 57 'strlcpy', 58 'wcslcat', 59 'wcslcpy' 60]) 61# Some symbols are part of the FORTIFY implementation. 62FORTIFY_stuff = set([ 63 '__FD_CLR_chk', 64 '__FD_ISSET_chk', 65 '__FD_SET_chk', 66 '__stack_chk_guard', 67 '__stpncpy_chk2', 68 '__strchr_chk', 69 '__strlcat_chk', 70 '__strlcpy_chk', 71 '__strlen_chk', 72 '__strncpy_chk2', 73 '__strrchr_chk', 74 '__umask_chk' 75]) 76# Some symbols are used to implement public macros. 77macro_stuff = set([ 78 '__assert2', 79 '__errno', 80 '__fe_dfl_env', 81 '__get_h_errno', 82]) 83# bionic exposes various Linux features that glibc doesn't. 84linux_stuff = set([ 85 'getauxval', 86 'gettid', 87 'tgkill' 88]) 89# Some standard stuff isn't yet in the versions of glibc we're using. 90std_stuff = set([ 91 'at_quick_exit' 92]) 93# These have mangled names in glibc, with a macro taking the "obvious" name. 94weird_stuff = set([ 95 'fstat', 96 'fstat64', 97 'fstatat', 98 'fstatat64', 99 'isfinite', 100 'isfinitef', 101 'isfinitel', 102 'isnormal', 103 'isnormalf', 104 'isnormall', 105 'lstat', 106 'lstat64', 107 'mknod', 108 'mknodat', 109 'stat', 110 'stat64', 111]) 112 113print 'glibc:' 114for symbol in sorted(glibc): 115 print symbol 116 117print 118print 'bionic:' 119for symbol in sorted(bionic): 120 print symbol 121 122print 123print 'in bionic but not glibc:' 124allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff) 125for symbol in sorted((bionic - allowed_stuff).difference(glibc)): 126 print symbol 127 128sys.exit(0) 129