From 2239d459f0fbd665126543ea49834597acbab2e5 Mon Sep 17 00:00:00 2001 From: Danny Tsai Date: Mon, 20 Nov 2023 07:21:16 +0800 Subject: [PATCH] Add Luma3DSDumpConvert (#1211) * add cog luma3dsdumpconvert * reduce one line to save a little bit of space * Use snake case --------- Co-authored-by: FrozenChen --- cogs/luma3dsdumpconvert.py | 115 +++++++++++++++++++++++++++++++++++++ kurisu.py | 1 + 2 files changed, 116 insertions(+) create mode 100644 cogs/luma3dsdumpconvert.py diff --git a/cogs/luma3dsdumpconvert.py b/cogs/luma3dsdumpconvert.py new file mode 100644 index 000000000..a5adee0c4 --- /dev/null +++ b/cogs/luma3dsdumpconvert.py @@ -0,0 +1,115 @@ +import discord +import concurrent.futures +import functools + +from discord.ext import commands +from struct import unpack_from +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from kurisu import Kurisu + +# adapted from luma3ds_exception_dump_parser +handled_exception_names = ("FIQ", "undefined instruction", "prefetch abort", "data abort") +register_names = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr") + ("dfsr", "ifsr", "far") + ("fpexc", "fpinst", "fpinst2") +svc_break_reasons = ("(svcBreak: panic)", "(svcBreak: assertion failed)", "(svcBreak: user-related)") +fault_status_sources = { + 0b1: 'Alignment', 0b100: 'Instruction cache maintenance operation fault', + 0b1100: 'External Abort on translation - First-level', 0b1110: 'External Abort on translation - Second-level', + 0b101: 'Translation - Section', 0b111: 'Translation - Page', 0b11: 'Access bit - Section', 0b110: 'Access bit - Page', + 0b1001: 'Domain - Section', 0b1011: 'Domain - Page', 0b1101: 'Permission - Section', 0b1111: 'Permission - Page', + 0b1000: 'Precise External Abort', 0b10110: 'Imprecise External Abort', 0b10: 'Debug event' +} + + +class Luma3DSDumpConvert(commands.Cog): + """ + Convert luma3ds exception dump files automatically. + """ + + def __init__(self, bot: 'Kurisu'): + self.bot = bot + + @staticmethod + def dump_convert(data: bytes): + out_message = "" + if unpack_from("<2I", data) != (0xdeadc0de, 0xdeadcafe): + return "Invalid file format" + + version, processor, exception_type, _, nb_registers, code_dump_size, stack_dump_size, additional_data_size = unpack_from("<8I", data, 8) + nb_registers //= 4 + + processor, core_id = processor & 0xffff, processor >> 16 + + if version < (1 << 16) | 2: + return "Incompatible format version" + + registers = unpack_from("<{0}I".format(nb_registers), data, 40) + code_offset = 40 + 4 * nb_registers + code_dump = data[code_offset:code_offset + code_dump_size] + stack_offset = code_offset + code_dump_size + # stackDump = data[stackOffset:stackOffset + stackDumpSize] + addtional_data_offset = stack_offset + stack_dump_size + additional_data = data[addtional_data_offset:addtional_data_offset + additional_data_size] + + if processor == 9: + out_message += "Processor: Arm9\n" + else: + out_message += "Processor: Arm11 (core {0})\n".format(core_id) + + type_details_str = "" + if exception_type == 2: + if (registers[16] & 0x20) == 0 and code_dump_size >= 4: + instr = unpack_from("= 2: + instr = unpack_from("= len(handled_exception_names) else handled_exception_names[exception_type], type_details_str) + + if processor == 11 and exception_type >= 2: + xfsr = registers[18] if exception_type == 2 else registers[17] + out_message += "Fault status: " + fault_status_sources[xfsr & 0xf] + "\n" + + if additional_data_size != 0: + if processor == 11: + out_message += "Current process: {0} ({1:016x})\n".format(additional_data[:8].decode("ascii"), unpack_from("