1#!/usr/bin/env python 2 3import json 4import os 5import re 6import subprocess 7import sys 8import argparse 9 10 11class CrashLogPatcher: 12 13 SYMBOL_REGEX = re.compile(r'^([0-9a-fA-F]+) T _(.*)$') 14 UUID_REGEX = re.compile(r'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') 15 16 def __init__(self, data, binary, offsets, json): 17 self.data = data 18 self.binary = binary 19 self.offsets = offsets 20 self.json = json 21 22 def patch_executable(self): 23 self.data = self.data.replace("@EXEC@", self.binary) 24 self.data = self.data.replace("@NAME@", os.path.basename(self.binary)) 25 26 def patch_uuid(self): 27 output = subprocess.check_output(['dwarfdump', '--uuid', self.binary]).decode("utf-8") 28 m = self.UUID_REGEX.match(output) 29 if m: 30 self.data = self.data.replace("@UUID@", m.group(1)) 31 32 def patch_addresses(self): 33 if not self.offsets: 34 return 35 output = subprocess.check_output(['nm', self.binary]).decode("utf-8") 36 for line in output.splitlines(): 37 m = self.SYMBOL_REGEX.match(line) 38 if m: 39 address = m.group(1) 40 symbol = m.group(2) 41 if symbol in self.offsets: 42 patch_addr = int(m.group(1), 16) + int( 43 self.offsets[symbol]) 44 if self.json: 45 patch_addr = patch_addr - 0x100000000 46 representation = int 47 else: 48 representation = hex 49 self.data = self.data.replace( 50 "@{}@".format(symbol), str(representation(patch_addr))) 51 52 def remove_metadata(self): 53 self.data= self.data[self.data.index('\n') + 1:] 54 55 56if __name__ == '__main__': 57 parser = argparse.ArgumentParser(description='Crashlog Patcher') 58 parser.add_argument('--binary', required=True) 59 parser.add_argument('--crashlog', required=True) 60 parser.add_argument('--offsets', required=True) 61 parser.add_argument('--json', default=False, action='store_true') 62 parser.add_argument('--no-metadata', default=False, action='store_true') 63 args = parser.parse_args() 64 65 offsets = json.loads(args.offsets) 66 67 with open(args.crashlog, 'r') as file: 68 data = file.read() 69 70 p = CrashLogPatcher(data, args.binary, offsets, args.json) 71 p.patch_executable() 72 p.patch_uuid() 73 p.patch_addresses() 74 75 if args.no_metadata: 76 p.remove_metadata() 77 78 with open(args.crashlog, 'w') as file: 79 file.write(p.data) 80