xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/sanitizer_common/scripts/gen_dynamic_list.py (revision a7c257b03e4462df2b1020128fb82716512d7856)
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 argparse
18import os
19import re
20import subprocess
21import sys
22import platform
23
24new_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',
55                  ])
56
57versioned_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'])
63
64def get_global_functions(library):
65  functions = []
66  nm = os.environ.get('NM', 'nm')
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
81
82def 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  args = parser.parse_args()
88
89  result = []
90
91  all_functions = []
92  for library in args.libraries:
93    all_functions.extend(get_global_functions(library))
94  function_set = set(all_functions)
95  for func in all_functions:
96    # Export new/delete operators.
97    if func in new_delete:
98      result.append(func)
99      continue
100    # Export interceptors.
101    match = re.match('__interceptor_(.*)', func)
102    if match:
103      result.append(func)
104      # We have to avoid exporting the interceptors for versioned library
105      # functions due to gold internal error.
106      orig_name = match.group(1)
107      if orig_name in function_set and (args.version_list or orig_name not in versioned_functions):
108        result.append(orig_name)
109      continue
110    # Export sanitizer interface functions.
111    if re.match('__sanitizer_(.*)', func):
112      result.append(func)
113
114  # Additional exported functions from files.
115  for fname in args.extra:
116    f = open(fname, 'r')
117    for line in f:
118      result.append(line.rstrip())
119  # Print the resulting list in the format recognized by ld.
120  print('{')
121  if args.version_list:
122    print('global:')
123  result.sort()
124  for f in result:
125    print(u'  %s;' % f)
126  if args.version_list:
127    print('local:')
128    print('  *;')
129  print('};')
130
131if __name__ == '__main__':
132  main(sys.argv)
133