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