]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - utils/libcxx/sym_check/util.py
Vendor import of libc++ 4.0.0 release r297347:
[FreeBSD/FreeBSD.git] / utils / libcxx / sym_check / util.py
1 #===----------------------------------------------------------------------===##
2 #
3 #                     The LLVM Compiler Infrastructure
4 #
5 # This file is dual licensed under the MIT and the University of Illinois Open
6 # Source Licenses. See LICENSE.TXT for details.
7 #
8 #===----------------------------------------------------------------------===##
9
10 import ast
11 import distutils.spawn
12 import sys
13 import re
14 import libcxx.util
15
16
17 def read_syms_from_list(slist):
18     """
19     Read a list of symbols from a list of strings.
20     Each string is one symbol.
21     """
22     return [ast.literal_eval(l) for l in slist]
23
24
25 def read_syms_from_file(filename):
26     """
27     Read a list of symbols in from a file.
28     """
29     with open(filename, 'r') as f:
30         data = f.read()
31     return read_syms_from_list(data.splitlines())
32
33
34 def read_blacklist(filename):
35     with open(filename, 'r') as f:
36         data = f.read()
37     lines = [l.strip() for l in data.splitlines() if l.strip()]
38     lines = [l for l in lines if not l.startswith('#')]
39     return lines
40
41
42 def write_syms(sym_list, out=None, names_only=False):
43     """
44     Write a list of symbols to the file named by out.
45     """
46     out_str = ''
47     out_list = sym_list
48     out_list.sort(key=lambda x: x['name'])
49     if names_only:
50         out_list = [sym['name'] for sym in sym_list]
51     for sym in out_list:
52         out_str += '%s\n' % sym
53     if out is None:
54         sys.stdout.write(out_str)
55     else:
56         with open(out, 'w') as f:
57             f.write(out_str)
58
59
60 _cppfilt_exe = distutils.spawn.find_executable('c++filt')
61
62
63 def demangle_symbol(symbol):
64     if _cppfilt_exe is None:
65         return symbol
66     out, _, exit_code = libcxx.util.executeCommandVerbose(
67         [_cppfilt_exe], input=symbol)
68     if exit_code != 0:
69         return symbol
70     return out
71
72
73 def is_elf(filename):
74     with open(filename, 'rb') as f:
75         magic_bytes = f.read(4)
76     return magic_bytes == b'\x7fELF'
77
78
79 def is_mach_o(filename):
80     with open(filename, 'rb') as f:
81         magic_bytes = f.read(4)
82     return magic_bytes in [
83         '\xfe\xed\xfa\xce',  # MH_MAGIC
84         '\xce\xfa\xed\xfe',  # MH_CIGAM
85         '\xfe\xed\xfa\xcf',  # MH_MAGIC_64
86         '\xcf\xfa\xed\xfe',  # MH_CIGAM_64
87         '\xca\xfe\xba\xbe',  # FAT_MAGIC
88         '\xbe\xba\xfe\xca'   # FAT_CIGAM
89     ]
90
91
92 def is_library_file(filename):
93     if sys.platform == 'darwin':
94         return is_mach_o(filename)
95     else:
96         return is_elf(filename)
97
98
99 def extract_or_load(filename):
100     import libcxx.sym_check.extract
101     if is_library_file(filename):
102         return libcxx.sym_check.extract.extract_symbols(filename)
103     return read_syms_from_file(filename)
104
105 def adjust_mangled_name(name):
106     if not name.startswith('__Z'):
107         return name
108     return name[1:]
109
110 new_delete_std_symbols = [
111     '_Znam',
112     '_Znwm',
113     '_ZdaPv',
114     '_ZdaPvm',
115     '_ZdlPv',
116     '_ZdlPvm'
117 ]
118
119 cxxabi_symbols = [
120     '___dynamic_cast',
121     '___gxx_personality_v0',
122     '_ZTIDi',
123     '_ZTIDn',
124     '_ZTIDs',
125     '_ZTIPDi',
126     '_ZTIPDn',
127     '_ZTIPDs',
128     '_ZTIPKDi',
129     '_ZTIPKDn',
130     '_ZTIPKDs',
131     '_ZTIPKa',
132     '_ZTIPKb',
133     '_ZTIPKc',
134     '_ZTIPKd',
135     '_ZTIPKe',
136     '_ZTIPKf',
137     '_ZTIPKh',
138     '_ZTIPKi',
139     '_ZTIPKj',
140     '_ZTIPKl',
141     '_ZTIPKm',
142     '_ZTIPKs',
143     '_ZTIPKt',
144     '_ZTIPKv',
145     '_ZTIPKw',
146     '_ZTIPKx',
147     '_ZTIPKy',
148     '_ZTIPa',
149     '_ZTIPb',
150     '_ZTIPc',
151     '_ZTIPd',
152     '_ZTIPe',
153     '_ZTIPf',
154     '_ZTIPh',
155     '_ZTIPi',
156     '_ZTIPj',
157     '_ZTIPl',
158     '_ZTIPm',
159     '_ZTIPs',
160     '_ZTIPt',
161     '_ZTIPv',
162     '_ZTIPw',
163     '_ZTIPx',
164     '_ZTIPy',
165     '_ZTIa',
166     '_ZTIb',
167     '_ZTIc',
168     '_ZTId',
169     '_ZTIe',
170     '_ZTIf',
171     '_ZTIh',
172     '_ZTIi',
173     '_ZTIj',
174     '_ZTIl',
175     '_ZTIm',
176     '_ZTIs',
177     '_ZTIt',
178     '_ZTIv',
179     '_ZTIw',
180     '_ZTIx',
181     '_ZTIy',
182     '_ZTSDi',
183     '_ZTSDn',
184     '_ZTSDs',
185     '_ZTSPDi',
186     '_ZTSPDn',
187     '_ZTSPDs',
188     '_ZTSPKDi',
189     '_ZTSPKDn',
190     '_ZTSPKDs',
191     '_ZTSPKa',
192     '_ZTSPKb',
193     '_ZTSPKc',
194     '_ZTSPKd',
195     '_ZTSPKe',
196     '_ZTSPKf',
197     '_ZTSPKh',
198     '_ZTSPKi',
199     '_ZTSPKj',
200     '_ZTSPKl',
201     '_ZTSPKm',
202     '_ZTSPKs',
203     '_ZTSPKt',
204     '_ZTSPKv',
205     '_ZTSPKw',
206     '_ZTSPKx',
207     '_ZTSPKy',
208     '_ZTSPa',
209     '_ZTSPb',
210     '_ZTSPc',
211     '_ZTSPd',
212     '_ZTSPe',
213     '_ZTSPf',
214     '_ZTSPh',
215     '_ZTSPi',
216     '_ZTSPj',
217     '_ZTSPl',
218     '_ZTSPm',
219     '_ZTSPs',
220     '_ZTSPt',
221     '_ZTSPv',
222     '_ZTSPw',
223     '_ZTSPx',
224     '_ZTSPy',
225     '_ZTSa',
226     '_ZTSb',
227     '_ZTSc',
228     '_ZTSd',
229     '_ZTSe',
230     '_ZTSf',
231     '_ZTSh',
232     '_ZTSi',
233     '_ZTSj',
234     '_ZTSl',
235     '_ZTSm',
236     '_ZTSs',
237     '_ZTSt',
238     '_ZTSv',
239     '_ZTSw',
240     '_ZTSx',
241     '_ZTSy'
242 ]
243
244 def is_stdlib_symbol_name(name):
245     name = adjust_mangled_name(name)
246     if re.search("@GLIBC|@GCC", name):
247         return False
248     if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name):
249         return True
250     if name in new_delete_std_symbols:
251         return True
252     if name in cxxabi_symbols:
253         return True
254     if name.startswith('_Z'):
255         return True
256     return False
257
258 def filter_stdlib_symbols(syms):
259     stdlib_symbols = []
260     other_symbols = []
261     for s in syms:
262         canon_name = adjust_mangled_name(s['name'])
263         if not is_stdlib_symbol_name(canon_name):
264             assert not s['is_defined'] and "found defined non-std symbol"
265             other_symbols += [s]
266         else:
267             stdlib_symbols += [s]
268     return stdlib_symbols, other_symbols