Handle exec addr errors better - don't let IgnoreBadMemoryAccesses skip dispatcher exceptions.

It would then just fall through into the compiler and die.

Should remove one of the "mystery" crashes from #14082.
This commit is contained in:
Henrik Rydgård committed 2021-02-09 09:32:38 +01:00
1 parent b539ce8c2c
commit 6b4356a060
10 files changed
+37 -5

No files matched your search

+1
View File
@@ -398,6 +398,7 @@ const char *MemoryExceptionTypeAsString(MemoryExceptionType type) {
case MemoryExceptionType::WRITE_WORD: return "Write Word";
case MemoryExceptionType::READ_BLOCK: return "Read Block";
case MemoryExceptionType::WRITE_BLOCK: return "Read/Write Block";
case MemoryExceptionType::EXEC_ADDR: return "Bad Exec Addr";
default:
return "N/A";
}
+1
View File
@@ -88,6 +88,7 @@ enum class MemoryExceptionType {
WRITE_WORD,
READ_BLOCK,
WRITE_BLOCK,
EXEC_ADDR,
};
enum class ExecExceptionType {
JUMP,
+1
View File
@@ -250,6 +250,7 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
#ifdef MASKED_PSP_MEMORY
ANDI2R(SCRATCH1, SCRATCH1, 0x3FFFFFFF);
#endif
dispatcherFetch = GetCodePtr();
LDR(SCRATCH1, MEMBASEREG, SCRATCH1_64);
LSR(SCRATCH2, SCRATCH1, 24); // or UBFX(SCRATCH2, SCRATCH1, 24, 8)
ANDI2R(SCRATCH1, SCRATCH1, 0x00FFFFFF);
+4
View File
@@ -185,6 +185,9 @@ public:
const u8 *GetDispatcher() const override {
return dispatcher;
}
bool IsAtDispatchFetch(const u8 *ptr) const override {
return ptr == dispatcherFetch;
}
void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;
void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;
@@ -275,6 +278,7 @@ public:
const u8 *dispatcherPCInSCRATCH1;
const u8 *dispatcher;
const u8 *dispatcherNoCheck;
const u8 *dispatcherFetch;
const u8 *saveStaticRegisters;
const u8 *loadStaticRegisters;
+3
View File
@@ -123,6 +123,9 @@ namespace MIPSComp {
virtual bool CodeInRange(const u8 *ptr) const = 0;
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;
virtual bool IsAtDispatchFetch(const u8 *ptr) const {
return false;
}
virtual const u8 *GetDispatcher() const = 0;
virtual const u8 *GetCrashHandler() const = 0;
virtual JitBlockCache *GetBlockCache() = 0;
+1 -1
View File
@@ -161,7 +161,7 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
#ifdef MASKED_PSP_MEMORY
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
#endif
dispatcherFetch = GetCodePtr();
#ifdef _M_IX86
_assert_msg_( Memory::base != 0, "Memory base bogus");
MOV(32, R(EAX), MDisp(EAX, (u32)Memory::base));
+5
View File
@@ -274,6 +274,11 @@ void Jit::Compile(u32 em_address) {
ClearCache();
}
if (!Memory::IsValidAddress(em_address)) {
Core_ExecException(em_address, em_address, ExecExceptionType::JUMP);
return;
}
BeginWrite();
int block_num = blocks.AllocateBlock(em_address);
+6
View File
@@ -298,6 +298,11 @@ private:
}
return true;
}
bool IsAtDispatchFetch(const u8 *codePtr) const override {
return codePtr == dispatcherFetch;
}
void SaveFlags();
void LoadFlags();
@@ -321,6 +326,7 @@ private:
const u8 *dispatcherCheckCoreState;
const u8 *dispatcherNoCheck;
const u8 *dispatcherInEAXNoCheck;
const u8 *dispatcherFetch;
const u8 *restoreRoundingMode;
const u8 *applyRoundingMode;
+14 -3
View File
@@ -41,16 +41,19 @@ namespace Memory {
static int64_t g_numReportedBadAccesses = 0;
const uint8_t *g_lastCrashAddress;
MemoryExceptionType g_lastMemoryExceptionType;
std::unordered_set<const uint8_t *> g_ignoredAddresses;
void MemFault_Init() {
g_numReportedBadAccesses = 0;
g_lastCrashAddress = nullptr;
g_lastMemoryExceptionType = MemoryExceptionType::NONE;
g_ignoredAddresses.clear();
}
bool MemFault_MayBeResumable() {
return g_lastCrashAddress != nullptr;
return g_lastCrashAddress != nullptr && g_lastMemoryExceptionType != MemoryExceptionType::EXEC_ADDR;
}
void MemFault_IgnoreLastCrash() {
@@ -122,11 +125,15 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
std::string infoString = "";
bool isAtDispatch = false;
if (MIPSComp::jit) {
std::string desc;
if (MIPSComp::jit->DescribeCodePtr(codePtr, desc)) {
infoString += desc + "\n";
}
if (MIPSComp::jit->IsAtDispatchFetch(codePtr)) {
isAtDispatch = true;
}
}
int instructionSize = 4;
@@ -158,7 +165,9 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
infoString += disassembly + "\n";
}
if (success) {
if (isAtDispatch) {
type = MemoryExceptionType::EXEC_ADDR;
} else if (success) {
if (info.isMemoryWrite) {
type = MemoryExceptionType::WRITE_WORD;
} else {
@@ -168,7 +177,9 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
type = MemoryExceptionType::UNKNOWN;
}
if (success && (g_Config.bIgnoreBadMemAccess || g_ignoredAddresses.find(codePtr) != g_ignoredAddresses.end())) {
g_lastMemoryExceptionType = type;
if (success && !isAtDispatch && (g_Config.bIgnoreBadMemAccess || g_ignoredAddresses.find(codePtr) != g_ignoredAddresses.end())) {
if (!info.isMemoryWrite) {
// It was a read. Fill the destination register with 0.
// TODO