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.
13 # gen_dynamic_list.py libclang_rt.*san*.a [ files ... ]
15 #===------------------------------------------------------------------------===#
16 from __future__
import print_function
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',
64 def get_global_functions(nm_executable
, library
):
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"]:
77 cols
= line
.split(' ')
78 if len(cols
) == 3 and cols
[1] in func_symbols
:
79 functions
.append(cols
[2])
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()
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
:
102 # Export interceptors.
103 match
= re
.match('__interceptor_(.*)', 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
)
112 # Export sanitizer interface functions.
113 if re
.match('__sanitizer_(.*)', func
):
116 # Additional exported functions from files.
117 for fname
in args
.extra
:
120 result
.append(line
.rstrip())
121 # Print the resulting list in the format recognized by ld.
122 with
open(args
.output
, 'w') as f
:
124 if args
.version_list
:
125 print('global:', file=f
)
128 print(u
' %s;' % sym
, file=f
)
129 if args
.version_list
:
130 print('local:', file=f
)
134 if __name__
== '__main__':