diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 57f62944f4..86a234cd3b 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1086,6 +1086,12 @@ void __KernelStartIdleThreads(SceUID moduleId) } } +void KernelValidateThreadTarget(uint32_t pc) { + if (!Memory::IsValidAddress(pc) || (pc & 3) != 0) { + Core_ExecException(pc, currentMIPS->pc, ExecExceptionType::THREAD); + } +} + bool __KernelSwitchOffThread(const char *reason) { if (!reason) @@ -1141,9 +1147,7 @@ bool __KernelSwitchToThread(SceUID threadID, const char *reason) if (current && current->isRunning()) __KernelChangeReadyState(current, currentThread, true); - if (!Memory::IsValidAddress(t->context.pc)) { - Core_ExecException(t->context.pc, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(t->context.pc); __KernelSwitchContext(t, reason); return true; @@ -1471,9 +1475,7 @@ void __KernelLoadContext(PSPThreadContext *ctx, bool vfpuEnabled) { memcpy(currentMIPS->vfpuCtrl, ctx->vfpuCtrl, sizeof(ctx->vfpuCtrl)); } - if (!Memory::IsValidAddress(ctx->pc)) { - Core_ExecException(ctx->pc, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(ctx->pc); memcpy(currentMIPS->other, ctx->other, sizeof(ctx->other)); // Not locking here, we assume the jit isn't switched during execution. @@ -1924,9 +1926,7 @@ SceUID __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int strcpy(thread->nt.name, "root"); - if (!Memory::IsValidAddress(thread->context.pc)) { - Core_ExecException(thread->context.pc, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(thread->context.pc); __KernelLoadContext(&thread->context, (attr & PSP_THREAD_ATTR_VFPU) != 0); currentMIPS->r[MIPS_REG_A0] = args; @@ -2057,9 +2057,7 @@ int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bo // Smaller is better for priority. Only switch if the new thread is better. if (cur && cur->nt.currentPriority > startThread->nt.currentPriority) { - if (!Memory::IsValidAddress(startThread->context.pc)) { - Core_ExecException(startThread->context.pc, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(startThread->context.pc); __KernelChangeReadyState(cur, currentThread, true); if (__InterruptsEnabled()) hleReSchedule("thread started"); @@ -2939,9 +2937,7 @@ u32 sceKernelExtendThreadStack(u32 size, u32 entryAddr, u32 entryParameter) Memory::Write_U32(currentMIPS->r[MIPS_REG_SP], thread->currentStack.end - 8); Memory::Write_U32(currentMIPS->pc, thread->currentStack.end - 12); - if (!Memory::IsValidAddress(entryAddr)) { - Core_ExecException(entryAddr, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(entryAddr); currentMIPS->pc = entryAddr; currentMIPS->r[MIPS_REG_A0] = entryParameter; @@ -2975,9 +2971,7 @@ void __KernelReturnFromExtendStack() return; } - if (!Memory::IsValidAddress(restorePC)) { - Core_ExecException(restorePC, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(restorePC); DEBUG_LOG(SCEKERNEL, "__KernelReturnFromExtendStack()"); currentMIPS->r[MIPS_REG_RA] = restoreRA; @@ -3259,9 +3253,7 @@ bool __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter) call->savedId = cur->currentMipscallId; call->reschedAfter = reschedAfter; - if (!Memory::IsValidAddress(call->entryPoint)) { - Core_ExecException(call->entryPoint, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(call->entryPoint); // Set up the new state currentMIPS->pc = call->entryPoint; @@ -3312,9 +3304,7 @@ void __KernelReturnFromMipsCall() currentMIPS->r[MIPS_REG_RA] = Memory::Read_U32(sp + MIPS_REG_RA * 4); sp += 32 * 4; - if (!Memory::IsValidAddress(call->savedPc)) { - Core_ExecException(call->savedPc, currentMIPS->pc, ExecExceptionType::THREAD); - } + KernelValidateThreadTarget(call->savedPc); currentMIPS->pc = call->savedPc; // This is how we set the return value. diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index bf687c045d..ec3d180be9 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -466,7 +466,7 @@ void ArmJit::Comp_Jump(MIPSOpcode op) { u32 targetAddr = (GetCompilerPC() & 0xF0000000) | off; // Might be a stubbed address or something? - if (!Memory::IsValidAddress(targetAddr)) { + if (!Memory::IsValidAddress(targetAddr) || (targetAddr & 3) != 0) { if (js.nextExit == 0) { ERROR_LOG_REPORT(JIT, "Jump to invalid address: %08x", targetAddr); } else { diff --git a/Core/MIPS/ARM64/Arm64CompBranch.cpp b/Core/MIPS/ARM64/Arm64CompBranch.cpp index ee86994211..026cf539e3 100644 --- a/Core/MIPS/ARM64/Arm64CompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64CompBranch.cpp @@ -481,7 +481,7 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { u32 targetAddr = (GetCompilerPC() & 0xF0000000) | off; // Might be a stubbed address or something? - if (!Memory::IsValidAddress(targetAddr)) { + if (!Memory::IsValidAddress(targetAddr) || (targetAddr & 3) != 0) { if (js.nextExit == 0) { ERROR_LOG_REPORT(JIT, "Jump to invalid address: %08x", targetAddr); } else { diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index f029f56731..66608fc86f 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -227,9 +227,10 @@ void IRJit::RunLoopUntil(u64 globalticks) { if (opcode == MIPS_EMUHACK_OPCODE) { u32 data = inst & 0xFFFFFF; IRBlock *block = blocks_.GetBlock(data); + u32 startPC = mips_->pc; mips_->pc = IRInterpret(mips_, block->GetInstructions(), block->GetNumInstructions()); - if (!Memory::IsValidAddress(mips_->pc)) { - Core_ExecException(mips_->pc, mips_->pc, ExecExceptionType::JUMP); + if (!Memory::IsValidAddress(mips_->pc) || (mips_->pc & 3) != 0) { + Core_ExecException(mips_->pc, startPC, ExecExceptionType::JUMP); break; } } else { diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index 305041ecb6..99cad4df3e 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -57,8 +57,7 @@ static inline void DelayBranchTo(u32 where) { - if (!Memory::IsValidAddress(where)) { - // TODO: What about misaligned? + if (!Memory::IsValidAddress(where) || (where & 3) != 0) { Core_ExecException(where, PC, ExecExceptionType::JUMP); } PC += 4; diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 835768bf96..9bd167d2e2 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -612,7 +612,7 @@ void Jit::Comp_Jump(MIPSOpcode op) { u32 targetAddr = (GetCompilerPC() & 0xF0000000) | off; // Might be a stubbed address or something? - if (!Memory::IsValidAddress(targetAddr)) { + if (!Memory::IsValidAddress(targetAddr) || (targetAddr & 3) != 0) { if (js.nextExit == 0) { ERROR_LOG_REPORT(JIT, "Jump to invalid address: %08x PC %08x LR %08x", targetAddr, GetCompilerPC(), currentMIPS->r[MIPS_REG_RA]); } else { diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 5c3f2121f9..c27ee3b502 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -275,7 +275,7 @@ void Jit::Compile(u32 em_address) { ClearCache(); } - if (!Memory::IsValidAddress(em_address)) { + if (!Memory::IsValidAddress(em_address) || (em_address & 3) != 0) { Core_ExecException(em_address, em_address, ExecExceptionType::JUMP); return; } @@ -672,7 +672,7 @@ static void HitInvalidBranch(uint32_t dest) { void Jit::WriteExit(u32 destination, int exit_num) { _dbg_assert_msg_(exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num"); - if (!Memory::IsValidAddress(destination)) { + if (!Memory::IsValidAddress(destination) || (destination & 3) != 0) { ERROR_LOG_REPORT(JIT, "Trying to write block exit to illegal destination %08x: pc = %08x", destination, currentMIPS->pc); MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC())); ABI_CallFunctionC(&HitInvalidBranch, destination); @@ -721,6 +721,12 @@ void Jit::WriteExit(u32 destination, int exit_num) { } } +static u32 IsValidJumpTarget(uint32_t addr) { + if (Memory::IsValidAddress(addr) && (addr & 3) == 0) + return 1; + return 0; +} + static void HitInvalidJumpReg(uint32_t source) { Core_ExecException(currentMIPS->pc, source, ExecExceptionType::JUMP); currentMIPS->pc = source + 8; @@ -762,7 +768,7 @@ void Jit::WriteExitDestInReg(X64Reg reg) { SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionA((const void *)&Memory::IsValidAddress, R(reg)); + ABI_CallFunctionA((const void *)&IsValidJumpTarget, R(reg)); // If we're ignoring, coreState didn't trip - so trip it now. CMP(32, R(EAX), Imm32(0));