163 lines · python
1#!/usr/bin/env python2# ===- lib/sanitizer_common/scripts/gen_dynamic_list.py ---------------------===#3#4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5# See https://llvm.org/LICENSE.txt for license information.6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7#8# ===------------------------------------------------------------------------===#9#10# Generates the list of functions that should be exported from sanitizer11# runtimes. The output format is recognized by --dynamic-list linker option.12# Usage:13# gen_dynamic_list.py libclang_rt.*san*.a [ files ... ]14#15# ===------------------------------------------------------------------------===#16from __future__ import print_function17import argparse18import os19import re20import subprocess21import sys22import platform23 24new_delete = set(25 [26 "_Znam",27 "_ZnamRKSt9nothrow_t", # operator new[](unsigned long)28 "_Znwm",29 "_ZnwmRKSt9nothrow_t", # operator new(unsigned long)30 "_Znaj",31 "_ZnajRKSt9nothrow_t", # operator new[](unsigned int)32 "_Znwj",33 "_ZnwjRKSt9nothrow_t", # operator new(unsigned int)34 # operator new(unsigned long, std::align_val_t)35 "_ZnwmSt11align_val_t",36 "_ZnwmSt11align_val_tRKSt9nothrow_t",37 # operator new(unsigned int, std::align_val_t)38 "_ZnwjSt11align_val_t",39 "_ZnwjSt11align_val_tRKSt9nothrow_t",40 # operator new[](unsigned long, std::align_val_t)41 "_ZnamSt11align_val_t",42 "_ZnamSt11align_val_tRKSt9nothrow_t",43 # operator new[](unsigned int, std::align_val_t)44 "_ZnajSt11align_val_t",45 "_ZnajSt11align_val_tRKSt9nothrow_t",46 "_ZdaPv",47 "_ZdaPvRKSt9nothrow_t", # operator delete[](void *)48 "_ZdlPv",49 "_ZdlPvRKSt9nothrow_t", # operator delete(void *)50 "_ZdaPvm", # operator delete[](void*, unsigned long)51 "_ZdlPvm", # operator delete(void*, unsigned long)52 "_ZdaPvj", # operator delete[](void*, unsigned int)53 "_ZdlPvj", # operator delete(void*, unsigned int)54 # operator delete(void*, std::align_val_t)55 "_ZdlPvSt11align_val_t",56 "_ZdlPvSt11align_val_tRKSt9nothrow_t",57 # operator delete[](void*, std::align_val_t)58 "_ZdaPvSt11align_val_t",59 "_ZdaPvSt11align_val_tRKSt9nothrow_t",60 # operator delete(void*, unsigned long, std::align_val_t)61 "_ZdlPvmSt11align_val_t",62 # operator delete[](void*, unsigned long, std::align_val_t)63 "_ZdaPvmSt11align_val_t",64 # operator delete(void*, unsigned int, std::align_val_t)65 "_ZdlPvjSt11align_val_t",66 # operator delete[](void*, unsigned int, std::align_val_t)67 "_ZdaPvjSt11align_val_t",68 ]69)70 71versioned_functions = set(72 [73 "memcpy",74 "pthread_attr_getaffinity_np",75 "pthread_cond_broadcast",76 "pthread_cond_destroy",77 "pthread_cond_init",78 "pthread_cond_signal",79 "pthread_cond_timedwait",80 "pthread_cond_wait",81 "realpath",82 "sched_getaffinity",83 ]84)85 86 87def get_global_functions(nm_executable, library):88 functions = []89 nm = os.environ.get("NM", nm_executable)90 nm_proc = subprocess.Popen(91 [nm, library], stdout=subprocess.PIPE, stderr=subprocess.PIPE92 )93 nm_out = nm_proc.communicate()[0].decode().split("\n")94 if nm_proc.returncode != 0:95 raise subprocess.CalledProcessError(nm_proc.returncode, nm)96 func_symbols = ["T", "W"]97 # On PowerPC, nm prints function descriptors from .data section.98 if platform.uname()[4] in ["powerpc", "ppc64"]:99 func_symbols += ["D"]100 for line in nm_out:101 cols = line.split(" ")102 if len(cols) == 3 and cols[1] in func_symbols:103 functions.append(cols[2])104 return functions105 106 107def main(argv):108 parser = argparse.ArgumentParser()109 parser.add_argument("--version-list", action="store_true")110 parser.add_argument("--extra", default=[], action="append")111 parser.add_argument("libraries", default=[], nargs="+")112 parser.add_argument("--nm-executable", required=True)113 parser.add_argument("-o", "--output", required=True)114 args = parser.parse_args()115 116 result = set()117 118 all_functions = []119 for library in args.libraries:120 all_functions.extend(get_global_functions(args.nm_executable, library))121 function_set = set(all_functions)122 for func in all_functions:123 # Export new/delete operators.124 if func in new_delete:125 result.add(func)126 continue127 # Export interceptors.128 match = re.match("_?__interceptor_(.*)", func)129 if match:130 result.add(func)131 # We have to avoid exporting the interceptors for versioned library132 # functions due to gold internal error.133 orig_name = match.group(1)134 if orig_name in function_set and (135 args.version_list or orig_name not in versioned_functions136 ):137 result.add(orig_name)138 continue139 # Export sanitizer interface functions.140 if re.match("__sanitizer_(.*)", func):141 result.add(func)142 143 # Additional exported functions from files.144 for fname in args.extra:145 f = open(fname, "r")146 for line in f:147 result.add(line.rstrip())148 # Print the resulting list in the format recognized by ld.149 with open(args.output, "w") as f:150 print("{", file=f)151 if args.version_list:152 print("global:", file=f)153 for sym in sorted(result):154 print(" %s;" % sym, file=f)155 if args.version_list:156 print("local:", file=f)157 print(" *;", file=f)158 print("};", file=f)159 160 161if __name__ == "__main__":162 main(sys.argv)163