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