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