xref: /llvm-project/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/patch-crashlog.py (revision c7cbf32f5770c5eec2a2dd6eb7cf3153e654ed08)
1#!/usr/bin/env python
2
3import json
4import os
5import re
6import subprocess
7import sys
8
9
10class CrashLogPatcher:
11
12    SYMBOL_REGEX = re.compile(r'^([0-9a-fA-F]+) T _(.*)$')
13    UUID_REGEX = re.compile(r'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
14
15    def __init__(self, data, binary, offsets):
16        self.data = data
17        self.binary = binary
18        self.offsets = offsets
19
20    def patch_executable(self):
21        self.data = self.data.replace("@EXEC@", self.binary)
22        self.data = self.data.replace("@NAME@", os.path.basename(self.binary))
23
24    def patch_uuid(self):
25        output = subprocess.check_output(['dwarfdump', '--uuid', self.binary])
26        m = self.UUID_REGEX.match(output)
27        if m:
28            self.data = self.data.replace("@UUID@", m.group(1))
29
30    def patch_addresses(self):
31        if not self.offsets:
32            return
33        output = subprocess.check_output(['nm', self.binary])
34        for line in output.splitlines():
35            m = self.SYMBOL_REGEX.match(line)
36            if m:
37                address = m.group(1)
38                symbol = m.group(2)
39                if symbol in self.offsets:
40                    patch_addr = int(m.group(1), 16) + int(
41                        self.offsets[symbol])
42                    self.data = self.data.replace("@{}@".format(symbol),
43                                                  str(hex(patch_addr)))
44
45
46if __name__ == '__main__':
47    binary = sys.argv[1]
48    crashlog = sys.argv[2]
49    offsets = json.loads(sys.argv[3]) if len(sys.argv) > 3 else None
50
51    with open(crashlog, 'r') as file:
52        data = file.read()
53
54    p = CrashLogPatcher(data, binary, offsets)
55    p.patch_executable()
56    p.patch_uuid()
57    p.patch_addresses()
58
59    with open(crashlog, 'w') as file:
60        file.write(p.data)
61