forked from eden-emu/eden
		
	Merge pull request #8490 from liamwhite/read-code-stop
dynarmic: Stop ReadCode callbacks to unmapped addresses
This commit is contained in:
		
						commit
						78ce053b4d
					
				
					 5 changed files with 65 additions and 25 deletions
				
			
		
							
								
								
									
										2
									
								
								externals/dynarmic
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								externals/dynarmic
									
										
									
									
										vendored
									
									
								
							|  | @ -1 +1 @@ | ||||||
| Subproject commit 5ad1d02351bf4fee681a3d701d210b419f41a505 | Subproject commit 7f84870712ac2fe06aa62dc2bebbe46b51a2cc2e | ||||||
|  | @ -119,16 +119,23 @@ void ARM_Interface::Run() { | ||||||
|         } |         } | ||||||
|         system.ExitDynarmicProfile(); |         system.ExitDynarmicProfile(); | ||||||
| 
 | 
 | ||||||
|         // Notify the debugger and go to sleep if a breakpoint was hit.
 |         // Notify the debugger and go to sleep if a breakpoint was hit,
 | ||||||
|         if (Has(hr, breakpoint)) { |         // or if the thread is unable to continue for any reason.
 | ||||||
|  |         if (Has(hr, breakpoint) || Has(hr, no_execute)) { | ||||||
|             RewindBreakpointInstruction(); |             RewindBreakpointInstruction(); | ||||||
|  |             if (system.DebuggerEnabled()) { | ||||||
|                 system.GetDebugger().NotifyThreadStopped(current_thread); |                 system.GetDebugger().NotifyThreadStopped(current_thread); | ||||||
|             current_thread->RequestSuspend(SuspendType::Debug); |             } | ||||||
|  |             current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         // Notify the debugger and go to sleep if a watchpoint was hit.
 | ||||||
|         if (Has(hr, watchpoint)) { |         if (Has(hr, watchpoint)) { | ||||||
|             RewindBreakpointInstruction(); |             RewindBreakpointInstruction(); | ||||||
|  |             if (system.DebuggerEnabled()) { | ||||||
|                 system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); |                 system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); | ||||||
|  |             } | ||||||
|             current_thread->RequestSuspend(SuspendType::Debug); |             current_thread->RequestSuspend(SuspendType::Debug); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -204,6 +204,7 @@ public: | ||||||
|     static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; |     static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||||||
|     static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; |     static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||||||
|     static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5; |     static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5; | ||||||
|  |     static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     /// System context that this ARM interface is running under.
 |     /// System context that this ARM interface is running under.
 | ||||||
|  |  | ||||||
|  | @ -48,6 +48,12 @@ public: | ||||||
|         CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); |         CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); | ||||||
|         return memory.Read64(vaddr); |         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 { |     void MemoryWrite8(u32 vaddr, u8 value) override { | ||||||
|         if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { |         if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { | ||||||
|  | @ -89,21 +95,28 @@ public: | ||||||
| 
 | 
 | ||||||
|     void InterpreterFallback(u32 pc, std::size_t num_instructions) override { |     void InterpreterFallback(u32 pc, std::size_t num_instructions) override { | ||||||
|         parent.LogBacktrace(); |         parent.LogBacktrace(); | ||||||
|         UNIMPLEMENTED_MSG("This should never happen, pc = {:08X}, code = {:08X}", pc, |         LOG_ERROR(Core_ARM, | ||||||
|                           MemoryReadCode(pc)); |                   "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, | ||||||
|  |                   num_instructions, MemoryRead32(pc)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { |     void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { | ||||||
|  |         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) { |             if (debugger_enabled) { | ||||||
|             parent.SaveContext(parent.breakpoint_context); |                 ReturnException(pc, ARM_Interface::breakpoint); | ||||||
|             parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             parent.LogBacktrace(); |             parent.LogBacktrace(); | ||||||
|             LOG_CRITICAL(Core_ARM, |             LOG_CRITICAL(Core_ARM, | ||||||
|                          "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", |                          "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", | ||||||
|                      exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); |                          exception, pc, MemoryRead32(pc), parent.IsInThumbMode()); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void CallSVC(u32 swi) override { |     void CallSVC(u32 swi) override { | ||||||
|  | @ -141,15 +154,20 @@ public: | ||||||
| 
 | 
 | ||||||
|         const auto match{parent.MatchingWatchpoint(addr, size, type)}; |         const auto match{parent.MatchingWatchpoint(addr, size, type)}; | ||||||
|         if (match) { |         if (match) { | ||||||
|             parent.SaveContext(parent.breakpoint_context); |  | ||||||
|             parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); |  | ||||||
|             parent.halted_watchpoint = match; |             parent.halted_watchpoint = match; | ||||||
|  |             ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return true; |         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; |     ARM_Dynarmic_32& parent; | ||||||
|     Core::Memory::Memory& memory; |     Core::Memory::Memory& memory; | ||||||
|     std::size_t num_interpreted_instructions{}; |     std::size_t num_interpreted_instructions{}; | ||||||
|  |  | ||||||
|  | @ -52,6 +52,12 @@ public: | ||||||
|         CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read); |         CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read); | ||||||
|         return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; |         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 { |     void MemoryWrite8(u64 vaddr, u8 value) override { | ||||||
|         if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { |         if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { | ||||||
|  | @ -105,7 +111,7 @@ public: | ||||||
|         parent.LogBacktrace(); |         parent.LogBacktrace(); | ||||||
|         LOG_ERROR(Core_ARM, |         LOG_ERROR(Core_ARM, | ||||||
|                   "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, |                   "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, | ||||||
|                   num_instructions, MemoryReadCode(pc)); |                   num_instructions, MemoryRead32(pc)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, |     void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, | ||||||
|  | @ -138,16 +144,19 @@ public: | ||||||
|         case Dynarmic::A64::Exception::SendEventLocal: |         case Dynarmic::A64::Exception::SendEventLocal: | ||||||
|         case Dynarmic::A64::Exception::Yield: |         case Dynarmic::A64::Exception::Yield: | ||||||
|             return; |             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: |         default: | ||||||
|             if (debugger_enabled) { |             if (debugger_enabled) { | ||||||
|                 parent.SaveContext(parent.breakpoint_context); |                 ReturnException(pc, ARM_Interface::breakpoint); | ||||||
|                 parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             parent.LogBacktrace(); |             parent.LogBacktrace(); | ||||||
|             ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", |             LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", | ||||||
|                        static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); |                          static_cast<std::size_t>(exception), pc, MemoryRead32(pc)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -188,15 +197,20 @@ public: | ||||||
| 
 | 
 | ||||||
|         const auto match{parent.MatchingWatchpoint(addr, size, type)}; |         const auto match{parent.MatchingWatchpoint(addr, size, type)}; | ||||||
|         if (match) { |         if (match) { | ||||||
|             parent.SaveContext(parent.breakpoint_context); |  | ||||||
|             parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); |  | ||||||
|             parent.halted_watchpoint = match; |             parent.halted_watchpoint = match; | ||||||
|  |             ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return true; |         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; |     ARM_Dynarmic_64& parent; | ||||||
|     Core::Memory::Memory& memory; |     Core::Memory::Memory& memory; | ||||||
|     u64 tpidrro_el0 = 0; |     u64 tpidrro_el0 = 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Morph
						Morph