Files
jsix/assets/debugging/jsix.elf-gdb.py
Justin C. Miller 5c82e5ba1b [tools] Fix gdb j6bt & j6stack commands
These commands had a number of issues. They weren't evaluating their
arguments (eg, you couldn't use a symbol name instead of a number), and
they weren't explicitly using hex when evaluating numbers, so they were
getting incorrect values when the default radix was not 10.
2022-01-15 09:07:00 -08:00

138 lines
3.8 KiB
Python

import gdb
class PrintStackCommand(gdb.Command):
def __init__(self):
super().__init__("j6stack", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
base = "$rsp"
if len(args) > 0:
base = args[0]
base = int(gdb.parse_and_eval(base))
depth = 22
if len(args) > 1:
depth = int(args[1])
for i in range(depth-1, -1, -1):
try:
offset = i * 8
value = gdb.parse_and_eval(f"*(uint64_t*)({base:#x} + {offset:#x})")
print("{:016x} (+{:04x}): {:016x}".format(base + offset, offset, int(value)))
except Exception as e:
print(e)
continue
class PrintBacktraceCommand(gdb.Command):
def __init__(self):
super().__init__("j6bt", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
frame = "$rbp"
if len(args) > 0:
frame = args[0]
frame = int(gdb.parse_and_eval(f"{frame}"))
depth = 30
if len(args) > 1:
depth = int(gdb.parse_and_eval(args[1]))
for i in range(depth-1, -1, -1):
ret = gdb.parse_and_eval(f"*(uint64_t*)({frame:#x} + 0x8)")
name = ""
try:
block = gdb.block_for_pc(int(ret))
if block:
name = block.function or ""
except RuntimeError:
pass
print("{:016x}: {:016x} {}".format(int(frame), int(ret), name))
frame = int(gdb.parse_and_eval(f"*(uint64_t*)({frame:#x})"))
if frame == 0 or ret == 0:
return
class TableWalkCommand(gdb.Command):
def __init__(self):
super().__init__("j6tw", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
if len(args) < 2:
raise Exception("Must be: j6tw <pml4> <addr>")
pml4 = int(gdb.parse_and_eval(args[0]))
addr = int(gdb.parse_and_eval(args[1]))
indices = [
(addr >> 39) & 0x1ff,
(addr >> 30) & 0x1ff,
(addr >> 21) & 0x1ff,
(addr >> 12) & 0x1ff,
]
names = ["PML4", "PDP", "PD", "PT"]
table_flags = [
(0x0001, "present"),
(0x0002, "write"),
(0x0004, "user"),
(0x0008, "pwt"),
(0x0010, "pcd"),
(0x0020, "accessed"),
(0x0040, "dirty"),
(0x0080, "largepage"),
(0x0100, "global"),
(0x1080, "pat"),
((1<<63), "xd"),
]
page_flags = [
(0x0001, "present"),
(0x0002, "write"),
(0x0004, "user"),
(0x0008, "pwt"),
(0x0010, "pcd"),
(0x0020, "accessed"),
(0x0040, "dirty"),
(0x0080, "pat"),
(0x0100, "global"),
((1<<63), "xd"),
]
flagsets = [table_flags, table_flags, table_flags, page_flags]
table = pml4
entry = 0
for i in range(len(indices)):
entry = int(gdb.parse_and_eval(f'((uint64_t*)0x{table:x})[0x{indices[i]:x}]'))
flagset = flagsets[i]
flag_names = " | ".join([f[1] for f in flagset if (entry & f[0]) == f[0]])
print(f"{names[i]:>4}: {table:016x}")
print(f" index: {indices[i]:3} {entry:016x}")
print(f" flags: {flag_names}")
if (entry & 1) == 0 or (i < 3 and (entry & 0x80)):
break
table = (entry & 0x7ffffffffffffe00) | 0xffffc00000000000
PrintStackCommand()
PrintBacktraceCommand()
TableWalkCommand()
gdb.execute("target remote :1234")
gdb.execute("display/i $rip")