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