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