16e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#!/usr/bin/env python
26e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#===- lib/dfsan/scripts/build-libc-list.py ---------------------------------===#
36e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#
46e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#                     The LLVM Compiler Infrastructure
56e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#
66e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# This file is distributed under the University of Illinois Open Source
76e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# License. See LICENSE.TXT for details.
86e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#
96e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne#===------------------------------------------------------------------------===#
106e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# The purpose of this script is to identify every function symbol in a set of
116e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# libraries (in this case, libc and libgcc) so that they can be marked as
126e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# uninstrumented, thus allowing the instrumentation pass to treat calls to those
136e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne# functions correctly.
146e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
156e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourneimport os
166e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourneimport subprocess
176e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourneimport sys
186e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefrom optparse import OptionParser
196e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
206e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournedef defined_function_list(object):
216e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  functions = []
226e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  readelf_proc = subprocess.Popen(['readelf', '-s', '-W', object],
236e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne                                  stdout=subprocess.PIPE)
246e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  readelf = readelf_proc.communicate()[0].split('\n')
256e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  if readelf_proc.returncode != 0:
266e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    raise subprocess.CalledProcessError(readelf_proc.returncode, 'readelf')
276e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  for line in readelf:
286e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    if (line[31:35] == 'FUNC' or line[31:36] == 'IFUNC') and \
296e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne       line[55:58] != 'UND':
306e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne      function_name = line[59:].split('@')[0]
316e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne      functions.append(function_name)
326e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  return functions
336e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
346e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournep = OptionParser()
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libc-dso-path', metavar='PATH',
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libc DSO directory',
386e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/lib/x86_64-linux-gnu')
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libc-archive-path', metavar='PATH',
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libc archive directory',
416e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/usr/lib/x86_64-linux-gnu')
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libgcc-dso-path', metavar='PATH',
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libgcc DSO directory',
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             default='/lib/x86_64-linux-gnu')
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libgcc-archive-path', metavar='PATH',
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libgcc archive directory',
486e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/usr/lib/gcc/x86_64-linux-gnu/4.6')
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
506e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournep.add_option('--with-libstdcxx', action='store_true',
516e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             dest='with_libstdcxx',
526e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             help='include libstdc++ in the list (inadvisable)')
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libstdcxx-dso-path', metavar='PATH',
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libstdc++ DSO directory',
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             default='/usr/lib/x86_64-linux-gnu')
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
576e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne(options, args) = p.parse_args()
586e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs = [os.path.join(options.libc_dso_path, name) for name in
606e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne        ['ld-linux-x86-64.so.2',
616e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libanl.so.1',
626e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libBrokenLocale.so.1',
636e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libcidn.so.1',
646e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libcrypt.so.1',
656e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libc.so.6',
666e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libdl.so.2',
676e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libm.so.6',
686e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libnsl.so.1',
696e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libpthread.so.0',
706e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libresolv.so.2',
716e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'librt.so.1',
726e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libthread_db.so.1',
736e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libutil.so.1']]
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs += [os.path.join(options.libc_archive_path, name) for name in
756e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         ['libc_nonshared.a',
766e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne          'libpthread_nonshared.a']]
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs.append(os.path.join(options.libgcc_dso_path, 'libgcc_s.so.1'))
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs.append(os.path.join(options.libgcc_archive_path, 'libgcc.a'))
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
816e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourneif options.with_libstdcxx:
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  libs.append(os.path.join(options.libstdcxx_dso_path, 'libstdc++.so.6'))
836e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
846e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions = []
856e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefor l in libs:
866e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  if os.path.exists(l):
876e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    functions += defined_function_list(l)
886e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  else:
896e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    print >> sys.stderr, 'warning: library %s not found' % l
906e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
916e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions = list(set(functions))
926e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions.sort()
936e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
946e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefor f in functions:
956e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  print 'fun:%s=uninstrumented' % f
96