]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | #===------------------------------------------------------------------------===# | |
92a42be0 | 17 | import argparse |
1a4d82fc JJ |
18 | import os |
19 | import re | |
20 | import subprocess | |
21 | import sys | |
7cac9316 | 22 | import platform |
1a4d82fc | 23 | |
92a42be0 SL |
24 | new_delete = set([ |
25 | '_Znam', '_ZnamRKSt9nothrow_t', # operator new[](unsigned long) | |
26 | '_Znwm', '_ZnwmRKSt9nothrow_t', # operator new(unsigned long) | |
27 | '_Znaj', '_ZnajRKSt9nothrow_t', # operator new[](unsigned int) | |
28 | '_Znwj', '_ZnwjRKSt9nothrow_t', # operator new(unsigned int) | |
29 | '_ZdaPv', '_ZdaPvRKSt9nothrow_t', # operator delete[](void *) | |
30 | '_ZdlPv', '_ZdlPvRKSt9nothrow_t', # operator delete(void *) | |
31 | '_ZdaPvm', # operator delete[](void*, unsigned long) | |
32 | '_ZdlPvm', # operator delete(void*, unsigned long) | |
33 | '_ZdaPvj', # operator delete[](void*, unsigned int) | |
34 | '_ZdlPvj', # operator delete(void*, unsigned int) | |
35 | ]) | |
1a4d82fc JJ |
36 | |
37 | versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np', | |
38 | 'pthread_cond_broadcast', | |
39 | 'pthread_cond_destroy', 'pthread_cond_init', | |
40 | 'pthread_cond_signal', 'pthread_cond_timedwait', | |
41 | 'pthread_cond_wait', 'realpath', | |
42 | 'sched_getaffinity']) | |
43 | ||
44 | def get_global_functions(library): | |
45 | functions = [] | |
7cac9316 XL |
46 | nm = os.environ.get('NM', 'nm') |
47 | nm_proc = subprocess.Popen([nm, library], stdout=subprocess.PIPE, | |
1a4d82fc JJ |
48 | stderr=subprocess.PIPE) |
49 | nm_out = nm_proc.communicate()[0].decode().split('\n') | |
50 | if nm_proc.returncode != 0: | |
7cac9316 | 51 | raise subprocess.CalledProcessError(nm_proc.returncode, nm) |
92a42be0 SL |
52 | func_symbols = ['T', 'W'] |
53 | # On PowerPC, nm prints function descriptors from .data section. | |
7cac9316 | 54 | if platform.uname()[4] in ["powerpc", "ppc64"]: |
92a42be0 | 55 | func_symbols += ['D'] |
1a4d82fc JJ |
56 | for line in nm_out: |
57 | cols = line.split(' ') | |
92a42be0 | 58 | if len(cols) == 3 and cols[1] in func_symbols : |
1a4d82fc JJ |
59 | functions.append(cols[2]) |
60 | return functions | |
61 | ||
62 | def main(argv): | |
92a42be0 SL |
63 | parser = argparse.ArgumentParser() |
64 | parser.add_argument('--version-list', action='store_true') | |
65 | parser.add_argument('--extra', default=[], action='append') | |
66 | parser.add_argument('libraries', default=[], nargs='+') | |
67 | args = parser.parse_args() | |
68 | ||
1a4d82fc JJ |
69 | result = [] |
70 | ||
92a42be0 SL |
71 | all_functions = [] |
72 | for library in args.libraries: | |
73 | all_functions.extend(get_global_functions(library)) | |
1a4d82fc JJ |
74 | function_set = set(all_functions) |
75 | for func in all_functions: | |
76 | # Export new/delete operators. | |
77 | if func in new_delete: | |
78 | result.append(func) | |
79 | continue | |
80 | # Export interceptors. | |
81 | match = re.match('__interceptor_(.*)', func) | |
82 | if match: | |
83 | result.append(func) | |
84 | # We have to avoid exporting the interceptors for versioned library | |
85 | # functions due to gold internal error. | |
86 | orig_name = match.group(1) | |
92a42be0 | 87 | if orig_name in function_set and (args.version_list or orig_name not in versioned_functions): |
1a4d82fc JJ |
88 | result.append(orig_name) |
89 | continue | |
90 | # Export sanitizer interface functions. | |
91 | if re.match('__sanitizer_(.*)', func): | |
92 | result.append(func) | |
93 | ||
94 | # Additional exported functions from files. | |
92a42be0 | 95 | for fname in args.extra: |
1a4d82fc JJ |
96 | f = open(fname, 'r') |
97 | for line in f: | |
98 | result.append(line.rstrip()) | |
99 | # Print the resulting list in the format recognized by ld. | |
100 | print('{') | |
92a42be0 SL |
101 | if args.version_list: |
102 | print('global:') | |
1a4d82fc JJ |
103 | result.sort() |
104 | for f in result: | |
92a42be0 SL |
105 | print(u' %s;' % f) |
106 | if args.version_list: | |
107 | print('local:') | |
108 | print(' *;') | |
1a4d82fc JJ |
109 | print('};') |
110 | ||
111 | if __name__ == '__main__': | |
112 | main(sys.argv) |