mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 18:54:14 +01:00 
			
		
		
		
	dynarmic: Stop ReadCode callbacks to unmapped addresses
This commit is contained in:
		
							parent
							
								
									737c446fc1
								
							
						
					
					
						commit
						1fd194141a
					
				
							
								
								
									
										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(); | ||||
| 
 | ||||
|         // 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; | ||||
|         } | ||||
|  | ||||
| @ -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.
 | ||||
|  | ||||
| @ -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{}; | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user