• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
10import ast
11import distutils.spawn
12import sys
13import re
14import libcxx.util
15
16
17def 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
25def 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
34def 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
42def 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
63def 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
73def is_elf(filename):
74    with open(filename, 'rb') as f:
75        magic_bytes = f.read(4)
76    return magic_bytes == b'\x7fELF'
77
78
79def 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
92def is_library_file(filename):
93    if sys.platform == 'darwin':
94        return is_mach_o(filename)
95    else:
96        return is_elf(filename)
97
98
99def 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
105def adjust_mangled_name(name):
106    if not name.startswith('__Z'):
107        return name
108    return name[1:]
109
110new_delete_std_symbols = [
111    '_Znam',
112    '_Znwm',
113    '_ZdaPv',
114    '_ZdaPvm',
115    '_ZdlPv',
116    '_ZdlPvm'
117]
118
119cxxabi_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
244def 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
258def 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
269