xref: /llvm-project/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/patch-crashlog.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
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