File: stack_trace_call_fault.py

package info (click to toggle)
drgn 0.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,852 kB
  • sloc: python: 74,992; ansic: 54,589; awk: 423; makefile: 351; sh: 99
file content (75 lines) | stat: -rw-r--r-- 2,364 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env drgn
# Copyright (c) Meta Platforms, Inc. and affiliates.
# SPDX-License-Identifier: LGPL-2.1-or-later

"""
Get a stack trace from a call to an invalid address on x86-64 or AArch64. drgn
should do this automatically eventually.
"""

import drgn
from drgn import Object
from drgn.helpers.common.prog import takes_program_or_default


def pt_regs_members_from_stack_frame(prog, frame):
    regs = frame.registers()
    if prog.platform.arch == drgn.Architecture.X86_64:
        return {
            "r15": regs.get("r15", 0),
            "r14": regs.get("r14", 0),
            "r13": regs.get("r13", 0),
            "r12": regs.get("r12", 0),
            "bp": regs.get("rbp", 0),
            "bx": regs.get("rbx", 0),
            "r11": regs.get("r11", 0),
            "r10": regs.get("r10", 0),
            "r9": regs.get("r9", 0),
            "r8": regs.get("r8", 0),
            "ax": regs.get("rax", 0),
            "cx": regs.get("rcx", 0),
            "dx": regs.get("rdx", 0),
            "si": regs.get("rsi", 0),
            "di": regs.get("rdi", 0),
            "orig_ax": -1,
            "ip": regs.get("rip", 0),
            "cs": regs.get("cs", 0),
            "flags": regs.get("rflags", 0),
            "sp": regs.get("rsp", 0),
            "ss": regs.get("ss", 0),
        }
    elif prog.platform.arch == drgn.Architecture.AARCH64:
        try:
            pc = frame.pc
        except LookupError:
            pc = 0
        return {
            "regs": [regs.get(f"x{i}", 0) for i in range(31)],
            "sp": regs.get("sp", 0),
            "pc": pc,
            "pstate": regs.get("pstate", 0),
        }
    else:
        raise NotImplementedError()


@takes_program_or_default
def call_fault_stack_trace(prog):
    pt_regs_members = pt_regs_members_from_stack_frame(
        prog, prog.crashed_thread().stack_trace()[0]
    )

    if prog.platform.arch == drgn.Architecture.X86_64:
        pt_regs_members["ip"] = prog.read_word(pt_regs_members["sp"]) - 1
        pt_regs_members["sp"] += 8
    elif prog.platform.arch == drgn.Architecture.AARCH64:
        pt_regs_members["pc"] = pt_regs_members["regs"][30] - 4
    else:
        raise NotImplementedError()

    return prog.stack_trace(Object(prog, "struct pt_regs", pt_regs_members))


if __name__ == "__main__":
    trace = call_fault_stack_trace(prog)
    print(trace)