mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Skip bad reads/writes by the guest executable.
This commit is contained in:
parent
1fce6de8b1
commit
aa802ecc0f
4 changed files with 59 additions and 24 deletions
|
@ -90,6 +90,7 @@ void InstallExceptionHandler(BadAccessHandler badAccessHandler) {
|
|||
|
||||
void UninstallExceptionHandler() {
|
||||
RemoveVectoredExceptionHandler(g_vectoredExceptionHandle);
|
||||
g_badAccessHandler = nullptr;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) && !defined(USE_SIGACTION_ON_APPLE)
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int accessType)
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info)
|
||||
{
|
||||
int accessType = 0;
|
||||
|
||||
unsigned const char *startCodePtr = codePtr;
|
||||
u8 rex = 0;
|
||||
u8 codeByte = 0;
|
||||
|
@ -80,6 +82,12 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
|||
modRMbyte = *codePtr++;
|
||||
hasModRM = true;
|
||||
}
|
||||
|
||||
// TODO: Add more cases.
|
||||
if ((codeByte & 0xF0) == 0x80)
|
||||
accessType = 1;
|
||||
if ((codeByte & 0xF0) == 0xC0)
|
||||
accessType = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -135,7 +143,6 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
|||
else
|
||||
info.displacement = *((s32 *)codePtr);
|
||||
codePtr += displacementSize;
|
||||
|
||||
|
||||
if (accessType == 1)
|
||||
{
|
||||
|
|
|
@ -60,4 +60,4 @@ enum AccessType {
|
|||
OP_ACCESS_WRITE = 1
|
||||
};
|
||||
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int accessType);
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Common/MemArena.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/MachineContext.h"
|
||||
#include "Common/x64Analyzer.h"
|
||||
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/HDRemaster.h"
|
||||
|
@ -463,29 +464,55 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
|||
const uint8_t *codePtr = (uint8_t *)(context->CTX_PC);
|
||||
|
||||
// TODO: Check that codePtr is within the current JIT space.
|
||||
// bool inJitSpace = MIPSComp::jit->IsInSpace(codePtr);
|
||||
// if (!inJitSpace) return false;
|
||||
|
||||
// TODO: Disassemble at codePtr to figure out if it's a read or a write.
|
||||
|
||||
uintptr_t baseAddress = (uintptr_t)base;
|
||||
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
const uintptr_t addressSpaceSize = 0x100000000ULL;
|
||||
#else
|
||||
const uintptr_t addressSpaceSize = 0x40000000ULL;
|
||||
#endif
|
||||
|
||||
// Check whether hostAddress is within the PSP memory space, which (likely) means it was a game that did the bad access.
|
||||
if (hostAddress >= baseAddress && hostAddress <= baseAddress + addressSpaceSize) {
|
||||
uint32_t guestAddress = hostAddress - baseAddress;
|
||||
// Maybe we should also somehow check whether the JIT is on the stack.
|
||||
ERROR_LOG(SYSTEM, "Bad memory access detected and ignored: %08x (%p)", guestAddress, hostAddress);
|
||||
return true;
|
||||
bool inJitSpace = true; // MIPSComp::jit->IsInSpace(codePtr);
|
||||
if (!inJitSpace) {
|
||||
// This is a crash in non-jitted code. Not something we want to handle here, ignore.
|
||||
return false;
|
||||
}
|
||||
|
||||
// A regular crash of some sort. Pass it on.
|
||||
return false;
|
||||
uintptr_t baseAddress = (uintptr_t)base;
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
const uintptr_t addressSpaceSize = 0x40000000ULL;
|
||||
#else
|
||||
const uintptr_t addressSpaceSize = 0x100000000ULL;
|
||||
#endif
|
||||
|
||||
// Check whether hostAddress is within the PSP memory space, which (likely) means it was a guest executable that did the bad access.
|
||||
if (hostAddress < baseAddress || hostAddress >= baseAddress + addressSpaceSize) {
|
||||
// Host address outside - this was a different kind of crash.
|
||||
return false;
|
||||
}
|
||||
|
||||
// OK, a guest executable did a bad access. Take care of it.
|
||||
|
||||
uint32_t guestAddress = hostAddress - baseAddress;
|
||||
ERROR_LOG(SYSTEM, "Bad memory access detected and ignored: %08x (%p)", guestAddress, hostAddress);
|
||||
// To ignore the access, we need to disassemble the instruction and modify context->CTX_PC
|
||||
|
||||
#if defined(PPSSPP_ARCH_AMD64) || defined(PPSSPP_ARCH_X86)
|
||||
|
||||
InstructionInfo info;
|
||||
DisassembleMov(codePtr, info);
|
||||
|
||||
if (g_Config.bIgnoreBadMemAccess) {
|
||||
if (!info.isMemoryWrite) {
|
||||
// Must have been a read. Fill the register with 0.
|
||||
// TODO
|
||||
}
|
||||
// Move on to the next instruction.
|
||||
context->CTX_PC += info.instructionSize;
|
||||
} else {
|
||||
// Jump to a crash handler.
|
||||
// TODO
|
||||
context->CTX_PC += info.instructionSize;
|
||||
}
|
||||
|
||||
#else
|
||||
// ARM, ARM64 : All instructions are always 4 bytes in size. As an initial implementation,
|
||||
// let's just skip the offending instruction.
|
||||
context->CTX_PC += 4;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue