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   '__sendto_chk',
    104   '__stack_chk_guard',
    105   '__stpncpy_chk2',
    106   '__strchr_chk',
    107   '__strlcat_chk',
    108   '__strlcpy_chk',
    109   '__strlen_chk',
    110   '__strncpy_chk2',
    111   '__strrchr_chk',
    112   '__umask_chk',
    113   '__write_chk',
    114 ])
    115 # Some symbols are used to implement public functions/macros.
    116 macro_stuff = set([
    117   '__assert2',
    118   '__errno',
    119   '__fe_dfl_env',
    120   '__get_h_errno',
    121   '__gnu_strerror_r',
    122   '__fpclassifyd',
    123   '__isfinite',
    124   '__isfinitef',
    125   '__isfinitel',
    126   '__isnormal',
    127   '__isnormalf',
    128   '__isnormall',
    129   '__sF',
    130   '__pthread_cleanup_pop',
    131   '__pthread_cleanup_push',
    132 ])
    133 # bionic exposes various Linux features that glibc doesn't.
    134 linux_stuff = set([
    135   'getauxval',
    136   'gettid',
    137   'pthread_gettid_np',
    138   'tgkill',
    139 ])
    140 # Some standard stuff isn't yet in the versions of glibc we're using.
    141 std_stuff = set([
    142   'at_quick_exit',
    143   'c16rtomb',
    144   'c32rtomb',
    145   'mbrtoc16',
    146   'mbrtoc32',
    147 ])
    148 # These have mangled names in glibc, with a macro taking the "obvious" name.
    149 weird_stuff = set([
    150   'fstat',
    151   'fstat64',
    152   'fstatat',
    153   'fstatat64',
    154   'isfinite',
    155   'isfinitef',
    156   'isfinitel',
    157   'isnormal',
    158   'isnormalf',
    159   'isnormall',
    160   'lstat',
    161   'lstat64',
    162   'mknod',
    163   'mknodat',
    164   'stat',
    165   'stat64',
    166   'optreset',
    167   'sigsetjmp',
    168 ])
    169 # These exist in glibc, but under slightly different names (generally one extra
    170 # or one fewer _). TODO: check against glibc names.
    171 libresolv_stuff = set([
    172   '__res_send_setqhook',
    173   '__res_send_setrhook',
    174   '_resolv_delete_cache_for_net',
    175   '_resolv_flush_cache_for_net',
    176   '_resolv_set_nameservers_for_net',
    177   'dn_expand',
    178   'nsdispatch',
    179 ])
    180 # Implementation details we know we export (and can't get away from).
    181 known = set([
    182   '_ctype_',
    183   '__libc_init',
    184 ])
    185 # POSIX has some stuff that's too stupid for words (a64l) or not actually
    186 # implemented in glibc unless you count always failing with ENOSYS as
    187 # being implemented (fattach). Other stuff (fmtmsg) isn't used in any
    188 # codebase I have access to, internal or external.
    189 in_posix_and_glibc_but_dead_or_useless = set([
    190   'a64l', # obsolete
    191   'confstr', # obsolete
    192   'endutxent', # no utmp on Android
    193   'fattach', # <stropts.h> marked obsolescent
    194   'fdetach', # <stropts.h> marked obsolescent
    195   'fmtmsg', # unused
    196   'getdate', # unused
    197   'getdate_err', # unused
    198   'gethostid', # obsolete
    199   'getmsg', # <stropts.h> marked obsolescent
    200   'getpmsg', # <stropts.h> marked obsolescent
    201   'getutxent', # no utmp on Android
    202   'getutxid', # no utmp on Android
    203   'getutxline', # no utmp on Android
    204   'isastream', # <stropts.h> marked obsolescent
    205   'l64a', # obsolete
    206   'mq_close', # disallowed by SELinux
    207   'mq_getattr', # disallowed by SELinux
    208   'mq_notify', # disallowed by SELinux
    209   'mq_open', # disallowed by SELinux
    210   'mq_receive', # disallowed by SELinux
    211   'mq_send', # disallowed by SELinux
    212   'mq_setattr', # disallowed by SELinux
    213   'mq_timedreceive', # disallowed by SELinux
    214   'mq_timedsend', # disallowed by SELinux
    215   'mq_unlink', # disallowed by SELinux
    216   'pthread_getconcurrency', # marked obsolescent
    217   'pthread_setconcurrency', # marked obsolescent
    218   'putmsg', # <stropts.h> marked obsolescent
    219   'putpmsg', # <stropts.h> marked obsolescent
    220   'pututxline', # no utmp on Android
    221   'shm_open', # disallowed by SELinux
    222   'shm_unlink', # disallowed by SELinux
    223   'setutxent', # no utmp on Android
    224   'sockatmark', # obsolete (https://tools.ietf.org/html/rfc6093)
    225   'strfmon', # icu4c
    226   'strfmon_l', # icu4c
    227   'ulimit', # <ulimit.h> marked obsolescent
    228 ])
    229 
    230 posix = posix - in_posix_and_glibc_but_dead_or_useless
    231 glibc = glibc - in_posix_and_glibc_but_dead_or_useless
    232 
    233 if not only_unwanted:
    234   #print 'glibc:'
    235   #for symbol in sorted(glibc):
    236   #  print symbol
    237   #print
    238 
    239   #print 'bionic:'
    240   #for symbol in sorted(bionic):
    241   #  print symbol
    242   #print
    243 
    244   print 'in glibc (but not posix) but not bionic:'
    245   for symbol in sorted((glibc - posix).difference(bionic)):
    246     print symbol
    247   print
    248 
    249   print 'in posix (and implemented in glibc) but not bionic:'
    250   for symbol in sorted((posix.intersection(glibc)).difference(bionic)):
    251     print symbol
    252   print
    253 
    254   print 'in bionic but not glibc:'
    255 
    256 allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
    257                  std_stuff | weird_stuff | libresolv_stuff | known)
    258 for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
    259   if symbol in ndk_ignored:
    260     symbol += '*'
    261   print symbol
    262 
    263 sys.exit(0)
    264