xref: /openbsd-src/gnu/llvm/compiler-rt/lib/dfsan/scripts/build-libc-list.py (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick#!/usr/bin/env python
23cab2bb3Spatrick#===- lib/dfsan/scripts/build-libc-list.py ---------------------------------===#
33cab2bb3Spatrick#
43cab2bb3Spatrick# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
53cab2bb3Spatrick# See https://llvm.org/LICENSE.txt for license information.
63cab2bb3Spatrick# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73cab2bb3Spatrick#
83cab2bb3Spatrick#===------------------------------------------------------------------------===#
93cab2bb3Spatrick# The purpose of this script is to identify every function symbol in a set of
103cab2bb3Spatrick# libraries (in this case, libc and libgcc) so that they can be marked as
113cab2bb3Spatrick# uninstrumented, thus allowing the instrumentation pass to treat calls to those
123cab2bb3Spatrick# functions correctly.
133cab2bb3Spatrick
14*810390e3Srobert# Typical usage will list runtime libraries which are not instrumented by dfsan.
15*810390e3Srobert# This would include libc, and compiler builtins.
16*810390e3Srobert#
17*810390e3Srobert# ./build-libc-list.py \
18*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \
19*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libanl.so.1 \
20*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libBrokenLocale.so.1 \
21*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libcidn.so.1 \
22*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libcrypt.so.1 \
23*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libc.so.6 \
24*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libdl.so.2 \
25*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libm.so.6 \
26*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libnsl.so.1 \
27*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libpthread.so.0 \
28*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libresolv.so.2 \
29*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/librt.so.1 \
30*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libthread_db.so.1 \
31*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libutil.so.1 \
32*810390e3Srobert#    --lib-file=/usr/lib/x86_64-linux-gnu/libc_nonshared.a \
33*810390e3Srobert#    --lib-file=/usr/lib/x86_64-linux-gnu/libpthread_nonshared.a \
34*810390e3Srobert#    --lib-file=/lib/x86_64-linux-gnu/libgcc_s.so.1 \
35*810390e3Srobert#    --lib-file=/usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc.a \
36*810390e3Srobert#    --error-missing-lib
37*810390e3Srobert
383cab2bb3Spatrickimport os
393cab2bb3Spatrickimport subprocess
403cab2bb3Spatrickimport sys
413cab2bb3Spatrickfrom optparse import OptionParser
423cab2bb3Spatrick
433cab2bb3Spatrickdef defined_function_list(object):
443cab2bb3Spatrick  functions = []
453cab2bb3Spatrick  readelf_proc = subprocess.Popen(['readelf', '-s', '-W', object],
463cab2bb3Spatrick                                  stdout=subprocess.PIPE)
473cab2bb3Spatrick  readelf = readelf_proc.communicate()[0].split('\n')
483cab2bb3Spatrick  if readelf_proc.returncode != 0:
493cab2bb3Spatrick    raise subprocess.CalledProcessError(readelf_proc.returncode, 'readelf')
503cab2bb3Spatrick  for line in readelf:
513cab2bb3Spatrick    if (line[31:35] == 'FUNC' or line[31:36] == 'IFUNC') and \
523cab2bb3Spatrick       line[39:44] != 'LOCAL' and \
533cab2bb3Spatrick       line[55:58] != 'UND':
543cab2bb3Spatrick      function_name = line[59:].split('@')[0]
553cab2bb3Spatrick      functions.append(function_name)
563cab2bb3Spatrick  return functions
573cab2bb3Spatrick
583cab2bb3Spatrickp = OptionParser()
593cab2bb3Spatrick
60*810390e3Srobertp.add_option('--lib-file', action='append', metavar='PATH',
61*810390e3Srobert             help='Specific library files to add.',
62*810390e3Srobert             default=[])
633cab2bb3Spatrick
64*810390e3Srobertp.add_option('--error-missing-lib', action='store_true',
65*810390e3Srobert             help='Make this script exit with an error code if any library is missing.',
66*810390e3Srobert             dest='error_missing_lib', default=False)
673cab2bb3Spatrick
683cab2bb3Spatrick(options, args) = p.parse_args()
693cab2bb3Spatrick
70*810390e3Srobertlibs = options.lib_file
71*810390e3Srobertif not libs:
72*810390e3Srobert    print >> sys.stderr, 'No libraries provided.'
73*810390e3Srobert    exit(1)
743cab2bb3Spatrick
75*810390e3Srobertmissing_lib = False
763cab2bb3Spatrickfunctions = []
773cab2bb3Spatrickfor l in libs:
783cab2bb3Spatrick  if os.path.exists(l):
793cab2bb3Spatrick    functions += defined_function_list(l)
803cab2bb3Spatrick  else:
81*810390e3Srobert    missing_lib = True
823cab2bb3Spatrick    print >> sys.stderr, 'warning: library %s not found' % l
833cab2bb3Spatrick
84*810390e3Srobertif options.error_missing_lib and missing_lib:
85*810390e3Srobert    print >> sys.stderr, 'Exiting with failure code due to missing library.'
86*810390e3Srobert    exit(1)
87*810390e3Srobert
883cab2bb3Spatrickfunctions = list(set(functions))
893cab2bb3Spatrickfunctions.sort()
903cab2bb3Spatrick
913cab2bb3Spatrickfor f in functions:
923cab2bb3Spatrick  print 'fun:%s=uninstrumented' % f
93