Merge pull request #16636 from unknownbrackets/exception-safety

Crash: Ensure we never handle faults in faults
This commit is contained in:
Henrik Rydgård 2022-12-21 08:09:46 +01:00 committed by GitHub
commit d4f5bff360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 13 deletions

View File

@ -427,12 +427,20 @@ bool Arm64Jit::DescribeCodePtr(const u8 *ptr, std::string &name) {
name = "loadStaticRegisters"; name = "loadStaticRegisters";
else { else {
u32 addr = blocks.GetAddressFromBlockPtr(ptr); u32 addr = blocks.GetAddressFromBlockPtr(ptr);
std::vector<int> numbers; // Returns 0 when it's valid, but unknown.
blocks.GetBlockNumbersFromAddress(addr, &numbers); if (addr == 0) {
if (!numbers.empty()) { name = "(unknown or deleted block)";
const JitBlock *block = blocks.GetBlock(numbers[0]); return true;
} else if (addr != (u32)-1) {
name = "(outside space)";
return true;
}
int number = blocks.GetBlockNumberFromAddress(addr);
if (number != -1) {
const JitBlock *block = blocks.GetBlock(number);
if (block) { if (block) {
name = StringFromFormat("(block %d at %08x)", numbers[0], block->originalAddress); name = StringFromFormat("(block %d at %08x)", number, block->originalAddress);
return true; return true;
} }
} }

View File

@ -375,6 +375,15 @@ void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int>
block_numbers->push_back(i); block_numbers->push_back(i);
} }
int JitBlockCache::GetBlockNumberFromAddress(u32 em_address) {
for (int i = 0; i < num_blocks_; i++) {
if (blocks_[i].ContainsAddress(em_address))
return i;
}
return -1;
}
u32 JitBlockCache::GetAddressFromBlockPtr(const u8 *ptr) const { u32 JitBlockCache::GetAddressFromBlockPtr(const u8 *ptr) const {
if (!codeBlock_->IsInSpace(ptr)) if (!codeBlock_->IsInSpace(ptr))
return (u32)-1; return (u32)-1;

View File

@ -143,6 +143,8 @@ public:
// Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap. // Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap.
// This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime. // This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime.
void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers); void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers);
// Similar to above, but only the first matching address.
int GetBlockNumberFromAddress(u32 em_address);
int GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad = false) const; int GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad = false) const;
u32 GetAddressFromBlockPtr(const u8 *ptr) const; u32 GetAddressFromBlockPtr(const u8 *ptr) const;

View File

@ -44,6 +44,7 @@ namespace Memory {
static int64_t g_numReportedBadAccesses = 0; static int64_t g_numReportedBadAccesses = 0;
const uint8_t *g_lastCrashAddress; const uint8_t *g_lastCrashAddress;
MemoryExceptionType g_lastMemoryExceptionType; MemoryExceptionType g_lastMemoryExceptionType;
static bool inCrashHandler = false;
std::unordered_set<const uint8_t *> g_ignoredAddresses; std::unordered_set<const uint8_t *> g_ignoredAddresses;
@ -88,6 +89,10 @@ static bool DisassembleNativeAt(const uint8_t *codePtr, int instructionSize, std
} }
bool HandleFault(uintptr_t hostAddress, void *ctx) { bool HandleFault(uintptr_t hostAddress, void *ctx) {
if (inCrashHandler)
return false;
inCrashHandler = true;
SContext *context = (SContext *)ctx; SContext *context = (SContext *)ctx;
const uint8_t *codePtr = (uint8_t *)(context->CTX_PC); const uint8_t *codePtr = (uint8_t *)(context->CTX_PC);
@ -100,6 +105,7 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
bool inJitSpace = MIPSComp::jit && MIPSComp::jit->CodeInRange(codePtr); bool inJitSpace = MIPSComp::jit && MIPSComp::jit->CodeInRange(codePtr);
if (!inJitSpace) { if (!inJitSpace) {
// This is a crash in non-jitted code. Not something we want to handle here, ignore. // This is a crash in non-jitted code. Not something we want to handle here, ignore.
inCrashHandler = false;
return false; return false;
} }
@ -114,8 +120,10 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
bool invalidHostAddress = hostAddress == (uintptr_t)0xFFFFFFFFFFFFFFFFULL; bool invalidHostAddress = hostAddress == (uintptr_t)0xFFFFFFFFFFFFFFFFULL;
if (hostAddress < baseAddress || hostAddress >= baseAddress + addressSpaceSize) { if (hostAddress < baseAddress || hostAddress >= baseAddress + addressSpaceSize) {
// Host address outside - this was a different kind of crash. // Host address outside - this was a different kind of crash.
if (!invalidHostAddress) if (!invalidHostAddress) {
inCrashHandler = false;
return false; return false;
}
} }
@ -182,6 +190,7 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
// Redirect execution to a crash handler that will switch to CoreState::CORE_RUNTIME_ERROR immediately. // Redirect execution to a crash handler that will switch to CoreState::CORE_RUNTIME_ERROR immediately.
context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler(); context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler();
ERROR_LOG(MEMMAP, "Bad execution access detected, halting: %08x (last known pc %08x, host: %p)", targetAddr, currentMIPS->pc, (void *)hostAddress); ERROR_LOG(MEMMAP, "Bad execution access detected, halting: %08x (last known pc %08x, host: %p)", targetAddr, currentMIPS->pc, (void *)hostAddress);
inCrashHandler = false;
return true; return true;
} else if (success) { } else if (success) {
if (info.isMemoryWrite) { if (info.isMemoryWrite) {
@ -218,6 +227,8 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler(); context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler();
ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation. Info:\n%s", guestAddress, (void *)hostAddress, infoString.c_str()); ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation. Info:\n%s", guestAddress, (void *)hostAddress, infoString.c_str());
} }
inCrashHandler = false;
return true; return true;
} }

View File

@ -1145,13 +1145,7 @@ UI::EventReturn JitCompareScreen::OnCurrentBlock(UI::EventParams &e) {
JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache(); JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache();
if (!blockCache) if (!blockCache)
return UI::EVENT_DONE; return UI::EVENT_DONE;
std::vector<int> blockNum; currentBlock_ = blockCache->GetBlockNumberFromAddress(currentMIPS->pc);
blockCache->GetBlockNumbersFromAddress(currentMIPS->pc, &blockNum);
if (blockNum.size() > 0) {
currentBlock_ = blockNum[0];
} else {
currentBlock_ = -1;
}
UpdateDisasm(); UpdateDisasm();
return UI::EVENT_DONE; return UI::EVENT_DONE;
} }