Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python2
      2 #
      3 # Copyright (C) 2015 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the 'License');
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an 'AS IS' BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 # pylint: disable=bad-indentation,bad-continuation
     18 import glob
     19 import os
     20 import re
     21 import sys
     22 
     23 import symbols
     24 
     25 only_unwanted = False
     26 if len(sys.argv) > 1:
     27   if sys.argv[1] in ('-u', '--unwanted'):
     28     only_unwanted = True
     29 
     30 toolchain = os.environ['ANDROID_TOOLCHAIN']
     31 arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
     32 if arch == 'aarch64':
     33   arch = 'arm64'
     34 
     35 def MangleGlibcNameToBionic(name):
     36   if name in glibc_to_bionic_names:
     37     return glibc_to_bionic_names[name]
     38   return name
     39 
     40 def GetNdkIgnored(arch):  # pylint: disable=redefined-outer-name
     41   ignored_symbols = set()
     42   files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' %
     43                     (os.getenv('ANDROID_BUILD_TOP'), arch))
     44   for f in files:
     45     ignored_symbols |= set(open(f, 'r').read().splitlines())
     46   return ignored_symbols
     47 
     48 glibc_to_bionic_names = {
     49   '__res_init': 'res_init',
     50   '__res_mkquery': 'res_mkquery',
     51   '__res_query': 'res_query',
     52   '__res_search': 'res_search',
     53   '__xpg_basename': '__gnu_basename',
     54 }
     55 
     56 glibc = symbols.GetFromSystemSo([
     57     'libc.so.*',
     58     'librt.so.*',
     59     'libpthread.so.*',
     60     'libresolv.so.*',
     61     'libm.so.*',
     62     'libutil.so.*',
     63 ])
     64 
     65 bionic = symbols.GetFromAndroidSo(['libc.so', 'libm.so'])
     66 this_dir = os.path.dirname(os.path.realpath(__file__))
     67 posix = symbols.GetFromTxt(os.path.join(this_dir, 'posix-2013.txt'))
     68 ndk_ignored = GetNdkIgnored(arch)
     69 
     70 glibc = set(map(MangleGlibcNameToBionic, glibc))
     71 
     72 # bionic includes various BSD symbols to ease porting other BSD-licensed code.
     73 bsd_stuff = set([
     74   'arc4random',
     75   'arc4random_buf',
     76   'arc4random_uniform',
     77   'basename_r',
     78   'dirname_r',
     79   'fgetln',
     80   'fpurge',
     81   'funopen',
     82   'funopen64',
     83   'gamma_r',
     84   'gammaf_r',
     85   'getprogname',
     86   'setprogname',
     87   'strlcat',
     88   'strlcpy',
     89   'sys_signame',
     90   'wcslcat',
     91   'wcslcpy'
     92 ])
     93 # Some symbols are part of the FORTIFY implementation.
     94 FORTIFY_stuff = set([
     95   '__FD_CLR_chk',
     96   '__FD_ISSET_chk',
     97   '__FD_SET_chk',
     98   '__fwrite_chk',
     99   '__memchr_chk',
    100   '__memrchr_chk',
    101   '__pwrite64_chk',
    102   '__pwrite_chk',
    103   '__stack_chk_guard',
    104   '__stpncpy_chk2',
    105   '__strchr_chk',
    106   '__strlcat_chk',
    107   '__strlcpy_chk',
    108   '__strlen_chk',
    109   '__strncpy_chk2',
    110   '__strrchr_chk',
    111   '__umask_chk'
    112   '__write_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 ])
    181 
    182 if not only_unwanted:
    183   #print 'glibc:'
    184   #for symbol in sorted(glibc):
    185   #  print symbol
    186   #print
    187 
    188   #print 'bionic:'
    189   #for symbol in sorted(bionic):
    190   #  print symbol
    191   #print
    192 
    193   print 'in glibc (but not posix) but not bionic:'
    194   for symbol in sorted((glibc - posix).difference(bionic)):
    195     print symbol
    196   print
    197 
    198   print 'in posix (and implemented in glibc) but not bionic:'
    199   for symbol in sorted((posix.intersection(glibc)).difference(bionic)):
    200     print symbol
    201   print
    202 
    203   print 'in bionic but not glibc:'
    204 
    205 allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
    206                  std_stuff | weird_stuff | libresolv_stuff | known)
    207 for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
    208   if symbol in ndk_ignored:
    209     symbol += '*'
    210   print symbol
    211 
    212 sys.exit(0)
    213