From 1fd194141a5643e3d274108a4a886ba8173270bd Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 20 Jun 2022 20:39:16 -0400 Subject: dynarmic: Stop ReadCode callbacks to unmapped addresses --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 42 ++++++++++++++++++++++--------- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 28 +++++++++++++++------ 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'src/core/arm/dynarmic') diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 8c90c8be0..10cf72a45 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -48,6 +48,12 @@ public: CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); return memory.Read64(vaddr); } + std::optional MemoryReadCode(u32 vaddr) override { + if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) { + return std::nullopt; + } + return MemoryRead32(vaddr); + } void MemoryWrite8(u32 vaddr, u8 value) override { if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { @@ -89,21 +95,28 @@ public: void InterpreterFallback(u32 pc, std::size_t num_instructions) override { parent.LogBacktrace(); - UNIMPLEMENTED_MSG("This should never happen, pc = {:08X}, code = {:08X}", pc, - MemoryReadCode(pc)); + LOG_ERROR(Core_ARM, + "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, + num_instructions, MemoryRead32(pc)); } void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { - if (debugger_enabled) { - parent.SaveContext(parent.breakpoint_context); - parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); + switch (exception) { + case Dynarmic::A32::Exception::NoExecuteFault: + LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#08x}", pc); + ReturnException(pc, ARM_Interface::no_execute); return; - } + default: + if (debugger_enabled) { + ReturnException(pc, ARM_Interface::breakpoint); + return; + } - parent.LogBacktrace(); - LOG_CRITICAL(Core_ARM, - "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", - exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); + parent.LogBacktrace(); + LOG_CRITICAL(Core_ARM, + "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", + exception, pc, MemoryRead32(pc), parent.IsInThumbMode()); + } } void CallSVC(u32 swi) override { @@ -141,15 +154,20 @@ public: const auto match{parent.MatchingWatchpoint(addr, size, type)}; if (match) { - parent.SaveContext(parent.breakpoint_context); - parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); parent.halted_watchpoint = match; + ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint); return false; } return true; } + void ReturnException(u32 pc, Dynarmic::HaltReason hr) { + parent.SaveContext(parent.breakpoint_context); + parent.breakpoint_context.cpu_registers[15] = pc; + parent.jit.load()->HaltExecution(hr); + } + ARM_Dynarmic_32& parent; Core::Memory::Memory& memory; std::size_t num_interpreted_instructions{}; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 4370ca294..92266aa9e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -52,6 +52,12 @@ public: CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read); return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; } + std::optional MemoryReadCode(u64 vaddr) override { + if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) { + return std::nullopt; + } + return MemoryRead32(vaddr); + } void MemoryWrite8(u64 vaddr, u8 value) override { if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { @@ -105,7 +111,7 @@ public: parent.LogBacktrace(); LOG_ERROR(Core_ARM, "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, - num_instructions, MemoryReadCode(pc)); + num_instructions, MemoryRead32(pc)); } void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, @@ -138,16 +144,19 @@ public: case Dynarmic::A64::Exception::SendEventLocal: case Dynarmic::A64::Exception::Yield: return; + case Dynarmic::A64::Exception::NoExecuteFault: + LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc); + ReturnException(pc, ARM_Interface::no_execute); + return; default: if (debugger_enabled) { - parent.SaveContext(parent.breakpoint_context); - parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); + ReturnException(pc, ARM_Interface::breakpoint); return; } parent.LogBacktrace(); - ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", - static_cast(exception), pc, MemoryReadCode(pc)); + LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", + static_cast(exception), pc, MemoryRead32(pc)); } } @@ -188,15 +197,20 @@ public: const auto match{parent.MatchingWatchpoint(addr, size, type)}; if (match) { - parent.SaveContext(parent.breakpoint_context); - parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); parent.halted_watchpoint = match; + ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint); return false; } return true; } + void ReturnException(u64 pc, Dynarmic::HaltReason hr) { + parent.SaveContext(parent.breakpoint_context); + parent.breakpoint_context.pc = pc; + parent.jit.load()->HaltExecution(hr); + } + ARM_Dynarmic_64& parent; Core::Memory::Memory& memory; u64 tpidrro_el0 = 0; -- cgit v1.2.3