Core: Show exception on misaligned jump.

This commit is contained in:
Unknown W. Brackets 2022-08-21 14:00:15 -07:00
parent b296bc7282
commit 80e481bbdc
7 changed files with 30 additions and 34 deletions

View File

@ -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.

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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));