summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/xnutools.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/proxyclient/m1n1/xnutools.py')
-rw-r--r--tools/proxyclient/m1n1/xnutools.py117
1 files changed, 117 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/xnutools.py b/tools/proxyclient/m1n1/xnutools.py
new file mode 100644
index 0000000..88c1a49
--- /dev/null
+++ b/tools/proxyclient/m1n1/xnutools.py
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: MIT
+import re
+from construct import *
+
+__all__ = []
+
+DebuggerState = Struct(
+ "panic_options" / Hex(Int64ul),
+ "current_op" / Hex(Int32ul),
+ "proceed_on_sync_failre" / Int32ul,
+ "message" / Hex(Int64ul),
+ "panic_str" / Hex(Int64ul),
+ "panic_args" / Hex(Int64ul),
+ "panic_data_ptr" / Hex(Int64ul),
+ "panic_caller" / Hex(Int64ul),
+ "entry_count" / Hex(Int32ul),
+ "kern_return" / Hex(Int32sl)
+)
+
+# Darwin va_list is just a stack pointer...
+VaList = Struct(
+ "stack" / Hex(Int64ul),
+)
+
+def decode_debugger_state(u, ctx):
+ p = u.proxy
+ iface = u.iface
+
+ def hv_readmem(addr, size):
+ addr = p.hv_translate(addr, False, False)
+ assert addr != 0
+ return iface.readmem(addr, size)
+
+ p_state = p.hv_translate(ctx.regs[25], False, False)
+ assert p_state != 0
+ di = iface.readstruct(p_state, DebuggerState)
+ print(di)
+
+ message = hv_readmem(di.message, 1024).split(b"\x00")[0].decode("ascii")
+ print()
+ print(f"Message: {message}")
+
+ print("===== Panic string =====")
+ decode_panic(u, di.panic_str, di.panic_args)
+ print("========================")
+
+def decode_panic_call(u, ctx):
+ decode_panic(u, ctx.regs[0], ctx.regs[1])
+
+def decode_panic(u, p_string, p_args):
+ p = u.proxy
+ iface = u.iface
+
+ def hv_readmem(addr, size):
+ addr = p.hv_translate(addr, False, False)
+ assert addr != 0
+ return iface.readmem(addr, size)
+
+ string = hv_readmem(p_string, 1024).split(b"\x00")[0].decode("ascii")
+ p_args = p.hv_translate(p_args, False, False)
+
+ args = iface.readstruct(p_args, VaList)
+
+ stack = hv_readmem(args.stack, 504)
+
+ def va_arg(t):
+ nonlocal stack
+ d, stack = stack[:8], stack[8:]
+ return t.parse(d)
+
+ utypes = {
+ "hh": Int8ul,
+ "h": Int16ul,
+ None: Int32ul,
+ "l": Int64ul,
+ "ll": Int64ul,
+ "q": Int64ul,
+ "s": Int64ul,
+ "t": Int64ul,
+ }
+
+ stypes = {
+ "hh": Int8sl,
+ "h": Int16sl,
+ None: Int32sl,
+ "l": Int64sl,
+ "ll": Int64sl,
+ "q": Int64sl,
+ "s": Int64sl,
+ "t": Int64sl,
+ }
+
+ #print(string)
+
+ def format_arg(match):
+ pat, flags, width, mod, conv = match.group(0, 1, 2, 3, 4)
+ if conv == "%":
+ return "%"
+ elif conv == "s":
+ return hv_readmem(va_arg(Int64ul), 1024).split(b"\x00")[0].decode("ascii")
+ elif conv in "di":
+ v = va_arg(stypes[mod])
+ return f"%{flags or ''}{width or ''}{conv or ''}" % v
+ elif conv in "ouxX":
+ v = va_arg(utypes[mod])
+ return f"%{flags or ''}{width or ''}{conv or ''}" % v
+ elif conv in "p":
+ return f"0x{va_arg(Int64ul):x}"
+ else:
+ return f"[{pat!r}:{va_arg(Int64ul):x}]"
+
+ string = re.sub('%([-#0 +]*)([1-9][0-9]*)?(hh|h|l|ll|q|L|j|z|Z|t)?([diouxXeEfFgGaAcsCSpnm%])',
+ format_arg, string)
+ print(string + "\n", end="")
+
+__all__.extend(k for k, v in globals().items()
+ if (callable(v) or isinstance(v, type)) and v.__module__ == __name__)