1#===----------------------------------------------------------------------===## 2# 3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4# See https://llvm.org/LICENSE.txt for license information. 5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6# 7#===----------------------------------------------------------------------===## 8 9import ast 10import distutils.spawn 11import sys 12import re 13import libcxx.util 14from pprint import pformat 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_exclusions(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, filter=None): 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 filter is not None: 50 out_list = filter(out_list) 51 if names_only: 52 out_list = [sym['name'] for sym in out_list] 53 for sym in out_list: 54 # Use pformat for consistent ordering of keys. 55 out_str += pformat(sym, width=100000) + '\n' 56 if out is None: 57 sys.stdout.write(out_str) 58 else: 59 with open(out, 'w') as f: 60 f.write(out_str) 61 62 63_cppfilt_exe = distutils.spawn.find_executable('c++filt') 64 65 66def demangle_symbol(symbol): 67 if _cppfilt_exe is None: 68 return symbol 69 out, _, exit_code = libcxx.util.executeCommandVerbose( 70 [_cppfilt_exe], input=symbol) 71 if exit_code != 0: 72 return symbol 73 return out 74 75 76def is_elf(filename): 77 with open(filename, 'rb') as f: 78 magic_bytes = f.read(4) 79 return magic_bytes == b'\x7fELF' 80 81 82def is_mach_o(filename): 83 with open(filename, 'rb') as f: 84 magic_bytes = f.read(4) 85 return magic_bytes in [ 86 b'\xfe\xed\xfa\xce', # MH_MAGIC 87 b'\xce\xfa\xed\xfe', # MH_CIGAM 88 b'\xfe\xed\xfa\xcf', # MH_MAGIC_64 89 b'\xcf\xfa\xed\xfe', # MH_CIGAM_64 90 b'\xca\xfe\xba\xbe', # FAT_MAGIC 91 b'\xbe\xba\xfe\xca' # FAT_CIGAM 92 ] 93 94 95def is_library_file(filename): 96 if sys.platform == 'darwin': 97 return is_mach_o(filename) 98 else: 99 return is_elf(filename) 100 101 102def extract_or_load(filename): 103 import libcxx.sym_check.extract 104 if is_library_file(filename): 105 return libcxx.sym_check.extract.extract_symbols(filename) 106 return read_syms_from_file(filename) 107 108def adjust_mangled_name(name): 109 if not name.startswith('__Z'): 110 return name 111 return name[1:] 112 113new_delete_std_symbols = [ 114 '_Znam', 115 '_Znwm', 116 '_ZdaPv', 117 '_ZdaPvm', 118 '_ZdlPv', 119 '_ZdlPvm' 120] 121 122cxxabi_symbols = [ 123 '___dynamic_cast', 124 '___gxx_personality_v0', 125 '_ZTIDi', 126 '_ZTIDn', 127 '_ZTIDs', 128 '_ZTIPDi', 129 '_ZTIPDn', 130 '_ZTIPDs', 131 '_ZTIPKDi', 132 '_ZTIPKDn', 133 '_ZTIPKDs', 134 '_ZTIPKa', 135 '_ZTIPKb', 136 '_ZTIPKc', 137 '_ZTIPKd', 138 '_ZTIPKe', 139 '_ZTIPKf', 140 '_ZTIPKh', 141 '_ZTIPKi', 142 '_ZTIPKj', 143 '_ZTIPKl', 144 '_ZTIPKm', 145 '_ZTIPKs', 146 '_ZTIPKt', 147 '_ZTIPKv', 148 '_ZTIPKw', 149 '_ZTIPKx', 150 '_ZTIPKy', 151 '_ZTIPa', 152 '_ZTIPb', 153 '_ZTIPc', 154 '_ZTIPd', 155 '_ZTIPe', 156 '_ZTIPf', 157 '_ZTIPh', 158 '_ZTIPi', 159 '_ZTIPj', 160 '_ZTIPl', 161 '_ZTIPm', 162 '_ZTIPs', 163 '_ZTIPt', 164 '_ZTIPv', 165 '_ZTIPw', 166 '_ZTIPx', 167 '_ZTIPy', 168 '_ZTIa', 169 '_ZTIb', 170 '_ZTIc', 171 '_ZTId', 172 '_ZTIe', 173 '_ZTIf', 174 '_ZTIh', 175 '_ZTIi', 176 '_ZTIj', 177 '_ZTIl', 178 '_ZTIm', 179 '_ZTIs', 180 '_ZTIt', 181 '_ZTIv', 182 '_ZTIw', 183 '_ZTIx', 184 '_ZTIy', 185 '_ZTSDi', 186 '_ZTSDn', 187 '_ZTSDs', 188 '_ZTSPDi', 189 '_ZTSPDn', 190 '_ZTSPDs', 191 '_ZTSPKDi', 192 '_ZTSPKDn', 193 '_ZTSPKDs', 194 '_ZTSPKa', 195 '_ZTSPKb', 196 '_ZTSPKc', 197 '_ZTSPKd', 198 '_ZTSPKe', 199 '_ZTSPKf', 200 '_ZTSPKh', 201 '_ZTSPKi', 202 '_ZTSPKj', 203 '_ZTSPKl', 204 '_ZTSPKm', 205 '_ZTSPKs', 206 '_ZTSPKt', 207 '_ZTSPKv', 208 '_ZTSPKw', 209 '_ZTSPKx', 210 '_ZTSPKy', 211 '_ZTSPa', 212 '_ZTSPb', 213 '_ZTSPc', 214 '_ZTSPd', 215 '_ZTSPe', 216 '_ZTSPf', 217 '_ZTSPh', 218 '_ZTSPi', 219 '_ZTSPj', 220 '_ZTSPl', 221 '_ZTSPm', 222 '_ZTSPs', 223 '_ZTSPt', 224 '_ZTSPv', 225 '_ZTSPw', 226 '_ZTSPx', 227 '_ZTSPy', 228 '_ZTSa', 229 '_ZTSb', 230 '_ZTSc', 231 '_ZTSd', 232 '_ZTSe', 233 '_ZTSf', 234 '_ZTSh', 235 '_ZTSi', 236 '_ZTSj', 237 '_ZTSl', 238 '_ZTSm', 239 '_ZTSs', 240 '_ZTSt', 241 '_ZTSv', 242 '_ZTSw', 243 '_ZTSx', 244 '_ZTSy' 245] 246 247def is_stdlib_symbol_name(name, sym): 248 name = adjust_mangled_name(name) 249 if re.search("@GLIBC|@GCC", name): 250 # Only when symbol is defined do we consider it ours 251 return sym['is_defined'] 252 if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name): 253 return True 254 if name in new_delete_std_symbols: 255 return True 256 if name in cxxabi_symbols: 257 return True 258 if name.startswith('_Z'): 259 return True 260 return False 261 262def filter_stdlib_symbols(syms): 263 stdlib_symbols = [] 264 other_symbols = [] 265 for s in syms: 266 canon_name = adjust_mangled_name(s['name']) 267 if not is_stdlib_symbol_name(canon_name, s): 268 other_symbols += [s] 269 else: 270 stdlib_symbols += [s] 271 return stdlib_symbols, other_symbols 272