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