[clang] Handle __declspec() attributes in using
[llvm-project.git] / compiler-rt / lib / sanitizer_common / scripts / gen_dynamic_list.py
blob6585a42dc81b867db69465a96b4f0aa705fd98f7
1 #!/usr/bin/env python
2 #===- lib/sanitizer_common/scripts/gen_dynamic_list.py ---------------------===#
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-exception
8 #===------------------------------------------------------------------------===#
10 # Generates the list of functions that should be exported from sanitizer
11 # runtimes. The output format is recognized by --dynamic-list linker option.
12 # Usage:
13 # gen_dynamic_list.py libclang_rt.*san*.a [ files ... ]
15 #===------------------------------------------------------------------------===#
16 from __future__ import print_function
17 import argparse
18 import os
19 import re
20 import subprocess
21 import sys
22 import platform
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 # operator new(unsigned long, std::align_val_t)
30 '_ZnwmSt11align_val_t', '_ZnwmSt11align_val_tRKSt9nothrow_t',
31 # operator new(unsigned int, std::align_val_t)
32 '_ZnwjSt11align_val_t', '_ZnwjSt11align_val_tRKSt9nothrow_t',
33 # operator new[](unsigned long, std::align_val_t)
34 '_ZnamSt11align_val_t', '_ZnamSt11align_val_tRKSt9nothrow_t',
35 # operator new[](unsigned int, std::align_val_t)
36 '_ZnajSt11align_val_t', '_ZnajSt11align_val_tRKSt9nothrow_t',
37 '_ZdaPv', '_ZdaPvRKSt9nothrow_t', # operator delete[](void *)
38 '_ZdlPv', '_ZdlPvRKSt9nothrow_t', # operator delete(void *)
39 '_ZdaPvm', # operator delete[](void*, unsigned long)
40 '_ZdlPvm', # operator delete(void*, unsigned long)
41 '_ZdaPvj', # operator delete[](void*, unsigned int)
42 '_ZdlPvj', # operator delete(void*, unsigned int)
43 # operator delete(void*, std::align_val_t)
44 '_ZdlPvSt11align_val_t', '_ZdlPvSt11align_val_tRKSt9nothrow_t',
45 # operator delete[](void*, std::align_val_t)
46 '_ZdaPvSt11align_val_t', '_ZdaPvSt11align_val_tRKSt9nothrow_t',
47 # operator delete(void*, unsigned long, std::align_val_t)
48 '_ZdlPvmSt11align_val_t',
49 # operator delete[](void*, unsigned long, std::align_val_t)
50 '_ZdaPvmSt11align_val_t',
51 # operator delete(void*, unsigned int, std::align_val_t)
52 '_ZdlPvjSt11align_val_t',
53 # operator delete[](void*, unsigned int, std::align_val_t)
54 '_ZdaPvjSt11align_val_t',
57 versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np',
58 'pthread_cond_broadcast',
59 'pthread_cond_destroy', 'pthread_cond_init',
60 'pthread_cond_signal', 'pthread_cond_timedwait',
61 'pthread_cond_wait', 'realpath',
62 'sched_getaffinity'])
64 def get_global_functions(nm_executable, library):
65 functions = []
66 nm = os.environ.get('NM', nm_executable)
67 nm_proc = subprocess.Popen([nm, library], stdout=subprocess.PIPE,
68 stderr=subprocess.PIPE)
69 nm_out = nm_proc.communicate()[0].decode().split('\n')
70 if nm_proc.returncode != 0:
71 raise subprocess.CalledProcessError(nm_proc.returncode, nm)
72 func_symbols = ['T', 'W']
73 # On PowerPC, nm prints function descriptors from .data section.
74 if platform.uname()[4] in ["powerpc", "ppc64"]:
75 func_symbols += ['D']
76 for line in nm_out:
77 cols = line.split(' ')
78 if len(cols) == 3 and cols[1] in func_symbols :
79 functions.append(cols[2])
80 return functions
82 def main(argv):
83 parser = argparse.ArgumentParser()
84 parser.add_argument('--version-list', action='store_true')
85 parser.add_argument('--extra', default=[], action='append')
86 parser.add_argument('libraries', default=[], nargs='+')
87 parser.add_argument('--nm-executable', required=True)
88 parser.add_argument('-o', '--output', required=True)
89 args = parser.parse_args()
91 result = []
93 all_functions = []
94 for library in args.libraries:
95 all_functions.extend(get_global_functions(args.nm_executable, library))
96 function_set = set(all_functions)
97 for func in all_functions:
98 # Export new/delete operators.
99 if func in new_delete:
100 result.append(func)
101 continue
102 # Export interceptors.
103 match = re.match('__interceptor_(.*)', func)
104 if match:
105 result.append(func)
106 # We have to avoid exporting the interceptors for versioned library
107 # functions due to gold internal error.
108 orig_name = match.group(1)
109 if orig_name in function_set and (args.version_list or orig_name not in versioned_functions):
110 result.append(orig_name)
111 continue
112 # Export sanitizer interface functions.
113 if re.match('__sanitizer_(.*)', func):
114 result.append(func)
116 # Additional exported functions from files.
117 for fname in args.extra:
118 f = open(fname, 'r')
119 for line in f:
120 result.append(line.rstrip())
121 # Print the resulting list in the format recognized by ld.
122 with open(args.output, 'w') as f:
123 print('{', file=f)
124 if args.version_list:
125 print('global:', file=f)
126 result.sort()
127 for sym in result:
128 print(u' %s;' % sym, file=f)
129 if args.version_list:
130 print('local:', file=f)
131 print(' *;', file=f)
132 print('};', file=f)
134 if __name__ == '__main__':
135 main(sys.argv)