• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  # 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
19
20  r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
21
22  symbols = set()
23
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)
32
33  return symbols
34
35def 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
40
41def 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
47
48def MangleGlibcNameToBionic(name):
49  if name in glibc_to_bionic_names:
50    return glibc_to_bionic_names[name]
51  return name
52
53glibc_to_bionic_names = {
54  '__res_init': 'res_init',
55  '__res_mkquery': 'res_mkquery',
56  '__res_query': 'res_query',
57  '__res_search': 'res_search',
58}
59
60glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
61bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
62
63glibc = map(MangleGlibcNameToBionic, glibc)
64
65# bionic includes various BSD symbols to ease porting other BSD-licensed code.
66bsd_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.
83FORTIFY_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.
98macro_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.
105linux_stuff = set([
106  'getauxval',
107  'gettid',
108  'tgkill'
109])
110# Some standard stuff isn't yet in the versions of glibc we're using.
111std_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.
119weird_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])
137
138print 'glibc:'
139for symbol in sorted(glibc):
140  print symbol
141
142print
143print 'bionic:'
144for symbol in sorted(bionic):
145  print symbol
146
147print
148print 'in bionic but not glibc:'
149allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff)
150for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
151  print symbol
152
153sys.exit(0)
154