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