text: #!/usr/bin/env python2
  #
  # Copyright (C) 2015 The Android Open Source Project
  #
  # Licensed under the Apache License, Version 2.0 (the 'License');
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #      http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an 'AS IS' BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  # pylint: disable=bad-indentation,bad-continuation
  import glob
  import os
  import re
  import sys
  
  import symbols
  
  only_unwanted = False
  if len(sys.argv) > 1:
    if sys.argv[1] in ('-u', '--unwanted'):
      only_unwanted = True
  
  toolchain = os.environ['ANDROID_TOOLCHAIN']
  arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
  if arch == 'aarch64':
    arch = 'arm64'
  
  def MangleGlibcNameToBionic(name):
    if name in glibc_to_bionic_names:
      return glibc_to_bionic_names[name]
    return name
  
  def GetNdkIgnored(arch):  # pylint: disable=redefined-outer-name
    ignored_symbols = set()
    files = glob.glob('%s/ndk/build/tools/unwanted-symbols/%s/*' %
                      (os.getenv('ANDROID_BUILD_TOP'), arch))
    for f in files:
      ignored_symbols |= set(open(f, 'r').read().splitlines())
    return ignored_symbols
  
  glibc_to_bionic_names = {
    '__res_init': 'res_init',
    '__res_mkquery': 'res_mkquery',
    '__res_query': 'res_query',
    '__res_search': 'res_search',
    '__xpg_basename': '__gnu_basename',
  }
  
  glibc = symbols.GetFromSystemSo([
      'libc.so.*',
      'librt.so.*',
      'libpthread.so.*',
      'libresolv.so.*',
      'libm.so.*',
      'libutil.so.*',
  ])
  
  bionic = symbols.GetFromAndroidSo(['libc.so', 'libm.so'])
  this_dir = os.path.dirname(os.path.realpath(__file__))
  posix = symbols.GetFromTxt(os.path.join(this_dir, 'posix-2013.txt'))
  ndk_ignored = GetNdkIgnored(arch)
  
  glibc = set(map(MangleGlibcNameToBionic, glibc))
  
  # bionic includes various BSD symbols to ease porting other BSD-licensed code.
  bsd_stuff = set([
    'basename_r',
    'dirname_r',
    'fgetln',
    'fpurge',
    'funopen',
    'gamma_r',
    'gammaf_r',
    'getprogname',
    'setprogname',
    'strlcat',
    'strlcpy',
    'sys_signame',
    'wcslcat',
    'wcslcpy'
  ])
  # Some symbols are part of the FORTIFY implementation.
  FORTIFY_stuff = set([
    '__FD_CLR_chk',
    '__FD_ISSET_chk',
    '__FD_SET_chk',
    '__stack_chk_guard',
    '__stpncpy_chk2',
    '__strchr_chk',
    '__strlcat_chk',
    '__strlcpy_chk',
    '__strlen_chk',
    '__strncpy_chk2',
    '__strrchr_chk',
    '__umask_chk'
  ])
  # Some symbols are used to implement public macros.
  macro_stuff = set([
    '__assert2',
    '__errno',
    '__fe_dfl_env',
    '__get_h_errno',
    '__fpclassifyd',
    '__isfinite',
    '__isfinitef',
    '__isfinitel',
    '__isnormal',
    '__isnormalf',
    '__isnormall',
    '__sF',
    '__pthread_cleanup_pop',
    '__pthread_cleanup_push',
  ])
  # bionic exposes various Linux features that glibc doesn't.
  linux_stuff = set([
    'getauxval',
    'gettid',
    'tgkill'
  ])
  # Some standard stuff isn't yet in the versions of glibc we're using.
  std_stuff = set([
    'at_quick_exit',
    'c16rtomb',
    'c32rtomb',
    'mbrtoc16',
    'mbrtoc32',
  ])
  # These have mangled names in glibc, with a macro taking the "obvious" name.
  weird_stuff = set([
    'fstat',
    'fstat64',
    'fstatat',
    'fstatat64',
    'isfinite',
    'isfinitef',
    'isfinitel',
    'isnormal',
    'isnormalf',
    'isnormall',
    'lstat',
    'lstat64',
    'mknod',
    'mknodat',
    'stat',
    'stat64',
    'optreset',
    'sigsetjmp',
  ])
  # These exist in glibc, but under slightly different names (generally one extra
  # or one fewer _). TODO: check against glibc names.
  libresolv_stuff = set([
    '__res_send_setqhook',
    '__res_send_setrhook',
    '_resolv_flush_cache_for_net',
    '_resolv_set_nameservers_for_net',
    'dn_expand',
    'nsdispatch',
  ])
  # Implementation details we know we export (and can't get away from).
  known = set([
    '_ctype_',
    '__libc_init',
  ])
  
  if not only_unwanted:
    #print 'glibc:'
    #for symbol in sorted(glibc):
    #  print symbol
    #print
  
    #print 'bionic:'
    #for symbol in sorted(bionic):
    #  print symbol
    #print
  
    print 'in glibc (but not posix) but not bionic:'
    for symbol in sorted((glibc - posix).difference(bionic)):
      print symbol
    print
  
    print 'in posix (and implemented in glibc) but not bionic:'
    for symbol in sorted((posix.intersection(glibc)).difference(bionic)):
      print symbol
    print
  
    print 'in bionic but not glibc:'
  
  allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff |
                   std_stuff | weird_stuff | libresolv_stuff | known)
  for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
    if symbol in ndk_ignored:
      symbol += '*'
    print symbol
  
  sys.exit(0)
  