diff options
| author | Liam <byteslice@airmail.cc> | 2022-06-20 20:39:16 -0400 | 
|---|---|---|
| committer | Liam <byteslice@airmail.cc> | 2022-06-21 20:01:43 -0400 | 
| commit | 1fd194141a5643e3d274108a4a886ba8173270bd (patch) | |
| tree | 0f2c564bee9afd0660cc6471cd3d8d41908397a8 | |
| parent | 737c446fc18618cf80a1243104ac8f5114c29a22 (diff) | |
dynarmic: Stop ReadCode callbacks to unmapped addresses
| m--------- | externals/dynarmic | 0 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 17 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.h | 1 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 42 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 28 | 
5 files changed, 64 insertions, 24 deletions
diff --git a/externals/dynarmic b/externals/dynarmic -Subproject 5ad1d02351bf4fee681a3d701d210b419f41a50 +Subproject 7f84870712ac2fe06aa62dc2bebbe46b51a2cc2 diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 6425e131f..56d7d7b3c 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -119,16 +119,23 @@ void ARM_Interface::Run() {          }          system.ExitDynarmicProfile(); -        // Notify the debugger and go to sleep if a breakpoint was hit. -        if (Has(hr, breakpoint)) { +        // Notify the debugger and go to sleep if a breakpoint was hit, +        // or if the thread is unable to continue for any reason. +        if (Has(hr, breakpoint) || Has(hr, no_execute)) {              RewindBreakpointInstruction(); -            system.GetDebugger().NotifyThreadStopped(current_thread); -            current_thread->RequestSuspend(SuspendType::Debug); +            if (system.DebuggerEnabled()) { +                system.GetDebugger().NotifyThreadStopped(current_thread); +            } +            current_thread->RequestSuspend(Kernel::SuspendType::Debug);              break;          } + +        // Notify the debugger and go to sleep if a watchpoint was hit.          if (Has(hr, watchpoint)) {              RewindBreakpointInstruction(); -            system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); +            if (system.DebuggerEnabled()) { +                system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); +            }              current_thread->RequestSuspend(SuspendType::Debug);              break;          } diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 4e431e27a..8a066ed91 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -204,6 +204,7 @@ public:      static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;      static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;      static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5; +    static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6;  protected:      /// System context that this ARM interface is running under. 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<u32> 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<u32> 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<std::size_t>(exception), pc, MemoryReadCode(pc)); +            LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", +                         static_cast<std::size_t>(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;  | 
