Skip to content

Instantly share code, notes, and snippets.

@DavidBuchanan314
Last active July 12, 2021 17:45
Show Gist options
  • Save DavidBuchanan314/d07a621fc565b23d0ba16451f29f098c to your computer and use it in GitHub Desktop.
Save DavidBuchanan314/d07a621fc565b23d0ba16451f29f098c to your computer and use it in GitHub Desktop.
# https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libvapours/include/vapours/ams/ams_fatal_error_context.hpp
from ctypes import *
import subprocess
import string
import sys
MaxStackTrace = 0x20
MaxStackDumpSize = 0x100
ThreadLocalSize = 0x100
NumGprs = 29
StdAbortMagicAddress = 0x8
StdAbortMagicValue = 0xA55AF00DDEADCAFE
StdAbortErrorDesc = 0xFFE
StackOverflowErrorDesc = 0xFFD
KernelPanicDesc = 0xF00
DataAbortErrorDesc = 0x101
class FatalErrorContext(Structure):
_fields_ = [
("magic", c_uint32),
("error_desc", c_uint32),
("program_id", c_uint64),
("gprs", c_uint64 * 32),
("pc", c_uint64),
("module_base", c_uint64),
("pstate", c_uint32),
("afsr0", c_uint32),
("afsr1", c_uint32),
("esr", c_uint32),
("far", c_uint64),
("report_identifier", c_uint64),
("stack_trace_size", c_uint64),
("stack_dump_size", c_uint64),
("stack_trace", c_uint64 * MaxStackTrace),
("stack_dump", c_uint8 * MaxStackDumpSize),
("tls", c_uint8 * ThreadLocalSize)
]
def addr2line(elf, addr):
return subprocess.check_output(["addr2line", "-pfC", "-e", elf, hex(addr)]).decode().strip()
def fmt_rel(addr, base):
delta = addr-base
if delta > 0 and delta < 1<<32:
if have_elf:
line = addr2line(sys.argv[2], delta)
linestr = f" ({line})"
else:
linestr = ""
return f"{hex(addr)} (base+{hex(delta)})" + linestr
else:
return hex(addr)
def hexdump(data):
for i in range(0, len(data), 16):
row = data[i:i+16]
line = f"0x{i:02x}: "
for c in row:
line += f"{c:02x} "
line += " "*(56-len(line))
for c in row:
if chr(c) in string.ascii_letters + string.digits + string.punctuation + " ":
line += chr(c)
else:
line += "."
print(line)
have_elf = len(sys.argv) > 2
report = open(sys.argv[1], "rb").read()
info = FatalErrorContext.from_buffer_copy(report)
assert(info.magic == 0x32454641) # AFE2
print()
print(" ======= INFO =======")
print("Title:", hex(info.program_id))
print("Error:", hex(info.error_desc))
print("Module Base:", hex(info.module_base))
print("Report Identifier:", info.report_identifier)
print()
print(" ======= REGISTER STATE =======")
for gpr in range(32):
rnames = {29: "fp", 30: "lr", 31: "sp"}
name = rnames.get(gpr, "r" + str(gpr))
print(name + ":\t", fmt_rel(info.gprs[gpr], info.module_base))
print("pc:\t", fmt_rel(info.pc, info.module_base))
print()
print("pstate:\t", hex(info.pstate))
print("afsr0:\t", hex(info.afsr0))
print("afsr1:\t", hex(info.afsr1))
print("esr:\t", hex(info.esr))
print("far:\t", hex(info.far))
print()
print(" ======= STACK TRACE =======")
for i in range(info.stack_trace_size):
print(f"0x{i*8:03x}:\t", fmt_rel(info.stack_trace[i], info.module_base))
print()
print(" ======= STACK DUMP =======")
hexdump(info.stack_dump[:info.stack_dump_size])
print()
print(" ======= TLS DUMP =======")
hexdump(info.tls)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment