]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blob - libc/tools/check-symbols-glibc.py
Merge "Implement malloc_info(3)."
[android-sdk/platform-bionic.git] / libc / tools / check-symbols-glibc.py
1 #!/usr/bin/python
3 import glob
4 import os
5 import re
6 import subprocess
7 import sys
9 only_unwanted = False
10 if len(sys.argv) > 1:
11   if sys.argv[1] in ('-u', '--unwanted'):
12     only_unwanted = True
14 toolchain = os.environ['ANDROID_TOOLCHAIN']
15 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
16 if arch == 'aarch64':
17   arch = 'arm64'
19 def GetSymbolsFromSo(so_file):
20   # Example readelf output:
21   #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf
22   #   266: 00016244     4 FUNC    GLOBAL DEFAULT    8 dremf
23   #   267: 00019018     4 OBJECT  GLOBAL DEFAULT   11 __fe_dfl_env
24   #   268: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_dcmplt
26   r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
28   symbols = set()
30   for line in subprocess.check_output(['readelf', '--dyn-syms', '-W', so_file]).split('\n'):
31     if ' HIDDEN ' in line or ' UND ' in line:
32       continue
33     m = r.match(line)
34     if m:
35       symbol = m.group(2)
36       symbol = re.sub('@.*', '', symbol)
37       symbols.add(symbol)
39   return symbols
41 def GetSymbolsFromAndroidSo(*files):
42   symbols = set()
43   for f in files:
44     symbols = symbols | GetSymbolsFromSo('%s/system/lib64/%s' % (os.environ['ANDROID_PRODUCT_OUT'], f))
45   return symbols
47 def GetSymbolsFromSystemSo(*files):
48   symbols = set()
49   for f in files:
50     f = glob.glob('/lib/x86_64-linux-gnu/%s' % f)[-1]
51     symbols = symbols | GetSymbolsFromSo(f)
52   return symbols
54 def MangleGlibcNameToBionic(name):
55   if name in glibc_to_bionic_names:
56     return glibc_to_bionic_names[name]
57   return name
59 def GetNdkIgnored():
60   global arch
61   symbols = set()
62   files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' %
63                     (os.getenv('ANDROID_BUILD_TOP'), arch))
64   for f in files:
65     symbols |= set(open(f, 'r').read().splitlines())
66   return symbols
68 glibc_to_bionic_names = {
69   '__res_init': 'res_init',
70   '__res_mkquery': 'res_mkquery',
71   '__res_query': 'res_query',
72   '__res_search': 'res_search',
73   '__xpg_basename': '__gnu_basename',
74 }
76 glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
77 bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
78 ndk_ignored = GetNdkIgnored()
80 glibc = map(MangleGlibcNameToBionic, glibc)
82 # bionic includes various BSD symbols to ease porting other BSD-licensed code.
83 bsd_stuff = set([
84   'basename_r',
85   'dirname_r',
86   'fgetln',
87   'fpurge',
88   'funopen',
89   'gamma_r',
90   'gammaf_r',
91   'getprogname',
92   'setprogname',
93   'strlcat',
94   'strlcpy',
95   'sys_signame',
96   'wcslcat',
97   'wcslcpy'
98 ])
99 # Some symbols are part of the FORTIFY implementation.
100 FORTIFY_stuff = set([
101   '__FD_CLR_chk',
102   '__FD_ISSET_chk',
103   '__FD_SET_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 ])
114 # Some symbols are used to implement public macros.
115 macro_stuff = set([
116   '__assert2',
117   '__errno',
118   '__fe_dfl_env',
119   '__get_h_errno',
120   '__fpclassifyd',
121   '__isfinite',
122   '__isfinitef',
123   '__isfinitel',
124   '__isnormal',
125   '__isnormalf',
126   '__isnormall',
127   '__sF',
128   '__pthread_cleanup_pop',
129   '__pthread_cleanup_push',
130 ])
131 # bionic exposes various Linux features that glibc doesn't.
132 linux_stuff = set([
133   'getauxval',
134   'gettid',
135   'tgkill'
136 ])
137 # Some standard stuff isn't yet in the versions of glibc we're using.
138 std_stuff = set([
139   'at_quick_exit',
140   'c16rtomb',
141   'c32rtomb',
142   'mbrtoc16',
143   'mbrtoc32',
144 ])
145 # These have mangled names in glibc, with a macro taking the "obvious" name.
146 weird_stuff = set([
147   'fstat',
148   'fstat64',
149   'fstatat',
150   'fstatat64',
151   'isfinite',
152   'isfinitef',
153   'isfinitel',
154   'isnormal',
155   'isnormalf',
156   'isnormall',
157   'lstat',
158   'lstat64',
159   'mknod',
160   'mknodat',
161   'stat',
162   'stat64',
163   'optreset',
164   'sigsetjmp',
165 ])
166 # These exist in glibc, but under slightly different names (generally one extra
167 # or one fewer _). TODO: check against glibc names.
168 libresolv_stuff = set([
169   '__res_send_setqhook',
170   '__res_send_setrhook',
171   '_resolv_flush_cache_for_net',
172   '_resolv_set_nameservers_for_net',
173   'dn_expand',
174   'nsdispatch',
175 ])
176 # Implementation details we know we export (and can't get away from).
177 known = set([
178   '_ctype_',
179   '__libc_init',
180 ])
182 if not only_unwanted:
183   print 'glibc:'
184   for symbol in sorted(glibc):
185     print symbol
187   print
188   print 'bionic:'
189   for symbol in sorted(bionic):
190     print symbol
192   print
193   print 'in bionic but not glibc:'
195 allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
196                  std_stuff | weird_stuff | libresolv_stuff | known)
197 for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
198   if symbol in ndk_ignored:
199     symbol += '*'
200   print symbol
202 sys.exit(0)