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#===------------------------------------------------------------------------===# 17import os 18import re 19import subprocess 20import sys 21 22new_delete = set(['_ZdaPv', '_ZdaPvRKSt9nothrow_t', 23 '_ZdlPv', '_ZdlPvRKSt9nothrow_t', 24 '_Znam', '_ZnamRKSt9nothrow_t', 25 '_Znwm', '_ZnwmRKSt9nothrow_t']) 26 27versioned_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 34def 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 func_symbols = ['T', 'W'] 42 # On PowerPC, nm prints function descriptors from .data section. 43 if os.uname()[4] in ["powerpc", "ppc64"]: 44 func_symbols += ['D'] 45 for line in nm_out: 46 cols = line.split(' ') 47 if len(cols) == 3 and cols[1] in func_symbols : 48 functions.append(cols[2]) 49 return functions 50 51def main(argv): 52 result = [] 53 54 library = argv[1] 55 all_functions = get_global_functions(library) 56 function_set = set(all_functions) 57 for func in all_functions: 58 # Export new/delete operators. 59 if func in new_delete: 60 result.append(func) 61 continue 62 # Export interceptors. 63 match = re.match('__interceptor_(.*)', func) 64 if match: 65 result.append(func) 66 # We have to avoid exporting the interceptors for versioned library 67 # functions due to gold internal error. 68 orig_name = match.group(1) 69 if orig_name in function_set and orig_name not in versioned_functions: 70 result.append(orig_name) 71 continue 72 # Export sanitizer interface functions. 73 if re.match('__sanitizer_(.*)', func): 74 result.append(func) 75 76 # Additional exported functions from files. 77 for fname in argv[2:]: 78 f = open(fname, 'r') 79 for line in f: 80 result.append(line.rstrip()) 81 # Print the resulting list in the format recognized by ld. 82 print('{') 83 result.sort() 84 for f in result: 85 print(' ' + f + ';') 86 print('};') 87 88if __name__ == '__main__': 89 main(sys.argv) 90