1import ast 2import distutils.spawn 3import signal 4import subprocess 5import sys 6 7 8def execute_command(cmd, input_str=None): 9 """ 10 Execute a command, capture and return its output. 11 """ 12 kwargs = { 13 'stdin': subprocess.PIPE, 14 'stdout': subprocess.PIPE, 15 'stderr': subprocess.PIPE, 16 } 17 p = subprocess.Popen(cmd, **kwargs) 18 out, err = p.communicate(input=input_str) 19 exitCode = p.wait() 20 if exitCode == -signal.SIGINT: 21 raise KeyboardInterrupt 22 return out, err, exitCode 23 24 25def execute_command_verbose(cmd, input_str=None): 26 """ 27 Execute a command and print its output on failure. 28 """ 29 out, err, exitCode = execute_command(cmd, input_str=input_str) 30 if exitCode != 0: 31 report = "Command: %s\n" % ' '.join(["'%s'" % a for a in cmd]) 32 report += "Exit Code: %d\n" % exitCode 33 if out: 34 report += "Standard Output:\n--\n%s--" % out 35 if err: 36 report += "Standard Error:\n--\n%s--" % err 37 report += "\n\nFailed!" 38 sys.stderr.write('%s\n' % report) 39 return out, err, exitCode 40 41 42def read_syms_from_list(slist): 43 """ 44 Read a list of symbols from a list of strings. 45 Each string is one symbol. 46 """ 47 return [ast.literal_eval(l) for l in slist] 48 49 50def read_syms_from_file(filename): 51 """ 52 Read a list of symbols in from a file. 53 """ 54 with open(filename, 'r') as f: 55 data = f.read() 56 return read_syms_from_list(data.splitlines()) 57 58 59def read_blacklist(filename): 60 with open(filename, 'r') as f: 61 data = f.read() 62 lines = [l.strip() for l in data.splitlines() if l.strip()] 63 lines = [l for l in lines if not l.startswith('#')] 64 return lines 65 66 67def write_syms(sym_list, out=None, names_only=False): 68 """ 69 Write a list of symbols to the file named by out. 70 """ 71 out_str = '' 72 out_list = sym_list 73 if names_only: 74 out_list = [sym['name'] for sym in sym_list] 75 out_list.sort() 76 for sym in out_list: 77 out_str += '%s\n' % sym 78 if out is None: 79 sys.stdout.write(out_str) 80 else: 81 with open(out, 'w') as f: 82 f.write(out_str) 83 84 85_cppfilt_exe = distutils.spawn.find_executable('c++filt') 86 87 88def demangle_symbol(symbol): 89 if _cppfilt_exe is None: 90 return symbol 91 out, _, exit_code = execute_command_verbose( 92 [_cppfilt_exe], input_str=symbol) 93 if exit_code != 0: 94 return symbol 95 return out 96 97 98def is_elf(filename): 99 with open(filename, 'r') as f: 100 magic_bytes = f.read(4) 101 return magic_bytes == '\x7fELF' 102 103 104def is_mach_o(filename): 105 with open(filename, 'r') as f: 106 magic_bytes = f.read(4) 107 return magic_bytes in [ 108 '\xfe\xed\xfa\xce', # MH_MAGIC 109 '\xce\xfa\xed\xfe', # MH_CIGAM 110 '\xfe\xed\xfa\xcf', # MH_MAGIC_64 111 '\xcf\xfa\xed\xfe', # MH_CIGAM_64 112 '\xca\xfe\xba\xbe', # FAT_MAGIC 113 '\xbe\xba\xfe\xca' # FAT_CIGAM 114 ] 115 116 117def is_library_file(filename): 118 if sys.platform == 'darwin': 119 return is_mach_o(filename) 120 else: 121 return is_elf(filename) 122 123 124def extract_or_load(filename): 125 import sym_check.extract 126 if is_library_file(filename): 127 return sym_check.extract.extract_symbols(filename) 128 return read_syms_from_file(filename) 129