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 \
296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines       line[39:44] != 'LOCAL' and \
306e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne       line[55:58] != 'UND':
316e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne      function_name = line[59:].split('@')[0]
326e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne      functions.append(function_name)
336e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  return functions
346e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
356e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournep = OptionParser()
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libc-dso-path', metavar='PATH',
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libc DSO directory',
396e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/lib/x86_64-linux-gnu')
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libc-archive-path', metavar='PATH',
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libc archive directory',
426e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/usr/lib/x86_64-linux-gnu')
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libgcc-dso-path', metavar='PATH',
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libgcc DSO directory',
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             default='/lib/x86_64-linux-gnu')
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libgcc-archive-path', metavar='PATH',
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libgcc archive directory',
496e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             default='/usr/lib/gcc/x86_64-linux-gnu/4.6')
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
516e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournep.add_option('--with-libstdcxx', action='store_true',
526e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             dest='with_libstdcxx',
536e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne             help='include libstdc++ in the list (inadvisable)')
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesp.add_option('--libstdcxx-dso-path', metavar='PATH',
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             help='path to libstdc++ DSO directory',
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             default='/usr/lib/x86_64-linux-gnu')
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
586e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne(options, args) = p.parse_args()
596e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs = [os.path.join(options.libc_dso_path, name) for name in
616e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne        ['ld-linux-x86-64.so.2',
626e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libanl.so.1',
636e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libBrokenLocale.so.1',
646e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libcidn.so.1',
656e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libcrypt.so.1',
666e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libc.so.6',
676e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libdl.so.2',
686e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libm.so.6',
696e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libnsl.so.1',
706e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libpthread.so.0',
716e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libresolv.so.2',
726e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'librt.so.1',
736e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libthread_db.so.1',
746e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         'libutil.so.1']]
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs += [os.path.join(options.libc_archive_path, name) for name in
766e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne         ['libc_nonshared.a',
776e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne          'libpthread_nonshared.a']]
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs.append(os.path.join(options.libgcc_dso_path, 'libgcc_s.so.1'))
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslibs.append(os.path.join(options.libgcc_archive_path, 'libgcc.a'))
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
826e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourneif options.with_libstdcxx:
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  libs.append(os.path.join(options.libstdcxx_dso_path, 'libstdc++.so.6'))
846e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
856e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions = []
866e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefor l in libs:
876e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  if os.path.exists(l):
886e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    functions += defined_function_list(l)
896e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  else:
906e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne    print >> sys.stderr, 'warning: library %s not found' % l
916e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
926e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions = list(set(functions))
936e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefunctions.sort()
946e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne
956e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbournefor f in functions:
966e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne  print 'fun:%s=uninstrumented' % f
97