Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python
      2 
      3 import glob
      4 import os
      5 import re
      6 import string
      7 import subprocess
      8 import sys
      9 
     10 toolchain = os.environ['ANDROID_TOOLCHAIN']
     11 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
     12 
     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
     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 
     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
     40 
     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
     47 
     48 def MangleGlibcNameToBionic(name):
     49   if name in glibc_to_bionic_names:
     50     return glibc_to_bionic_names[name]
     51   return name
     52 
     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 }
     59 
     60 glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
     61 bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
     62 
     63 glibc = map(MangleGlibcNameToBionic, glibc)
     64 
     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 ])
    137 
    138 print 'glibc:'
    139 for symbol in sorted(glibc):
    140   print symbol
    141 
    142 print
    143 print 'bionic:'
    144 for symbol in sorted(bionic):
    145   print symbol
    146 
    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
    152 
    153 sys.exit(0)
    154