1 #!/usr/bin/env python 2 #===- lib/sanitizer_common/scripts/gen_dynamic_list.py ---------------------===# 3 # 4 # The LLVM Compiler Infrastructure 5 # 6 # This file is distributed under the University of Illinois Open Source 7 # License. See LICENSE.TXT for details. 8 # 9 #===------------------------------------------------------------------------===# 10 # 11 # Generates the list of functions that should be exported from sanitizer 12 # runtimes. The output format is recognized by --dynamic-list linker option. 13 # Usage: 14 # gen_dynamic_list.py libclang_rt.*san*.a [ files ... ] 15 # 16 #===------------------------------------------------------------------------===# 17 import os 18 import re 19 import subprocess 20 import sys 21 22 new_delete = set(['_ZdaPv', '_ZdaPvRKSt9nothrow_t', 23 '_ZdlPv', '_ZdlPvRKSt9nothrow_t', 24 '_Znam', '_ZnamRKSt9nothrow_t', 25 '_Znwm', '_ZnwmRKSt9nothrow_t']) 26 27 versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np', 28 'pthread_cond_broadcast', 29 'pthread_cond_destroy', 'pthread_cond_init', 30 'pthread_cond_signal', 'pthread_cond_timedwait', 31 'pthread_cond_wait', 'realpath', 32 'sched_getaffinity']) 33 34 def get_global_functions(library): 35 functions = [] 36 nm_proc = subprocess.Popen(['nm', library], stdout=subprocess.PIPE, 37 stderr=subprocess.PIPE) 38 nm_out = nm_proc.communicate()[0].decode().split('\n') 39 if nm_proc.returncode != 0: 40 raise subprocess.CalledProcessError(nm_proc.returncode, 'nm') 41 for line in nm_out: 42 cols = line.split(' ') 43 if (len(cols) == 3 and cols[1] in ('T', 'W')) : 44 functions.append(cols[2]) 45 return functions 46 47 def main(argv): 48 result = [] 49 50 library = argv[1] 51 all_functions = get_global_functions(library) 52 function_set = set(all_functions) 53 for func in all_functions: 54 # Export new/delete operators. 55 if func in new_delete: 56 result.append(func) 57 continue 58 # Export interceptors. 59 match = re.match('__interceptor_(.*)', func) 60 if match: 61 result.append(func) 62 # We have to avoid exporting the interceptors for versioned library 63 # functions due to gold internal error. 64 orig_name = match.group(1) 65 if orig_name in function_set and orig_name not in versioned_functions: 66 result.append(orig_name) 67 continue 68 # Export sanitizer interface functions. 69 if re.match('__sanitizer_(.*)', func): 70 result.append(func) 71 72 # Additional exported functions from files. 73 for fname in argv[2:]: 74 f = open(fname, 'r') 75 for line in f: 76 result.append(line.rstrip()) 77 # Print the resulting list in the format recognized by ld. 78 print('{') 79 result.sort() 80 for f in result: 81 print(' ' + f + ';') 82 print('};') 83 84 if __name__ == '__main__': 85 main(sys.argv) 86