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