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