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";
else {
u32 addr = blocks.GetAddressFromBlockPtr(ptr);
std::vector<int> numbers;
blocks.GetBlockNumbersFromAddress(addr, &numbers);
if (!numbers.empty()) {
const JitBlock *block = blocks.GetBlock(numbers[0]);
// Returns 0 when it's valid, but unknown.
if (addr == 0) {
name = "(unknown or deleted block)";
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) {
name = StringFromFormat("(block %d at %08x)", numbers[0], block->originalAddress);
name = StringFromFormat("(block %d at %08x)", number, block->originalAddress);
return true;
}
}

View File

@ -375,6 +375,15 @@ void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int>
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 {
if (!codeBlock_->IsInSpace(ptr))
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.
// 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);
// Similar to above, but only the first matching address.
int GetBlockNumberFromAddress(u32 em_address);
int GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad = false) const;
u32 GetAddressFromBlockPtr(const u8 *ptr) const;

View File

@ -44,6 +44,7 @@ namespace Memory {
static int64_t g_numReportedBadAccesses = 0;
const uint8_t *g_lastCrashAddress;
MemoryExceptionType g_lastMemoryExceptionType;
static bool inCrashHandler = false;
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) {
if (inCrashHandler)
return false;
inCrashHandler = true;
SContext *context = (SContext *)ctx;
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);
if (!inJitSpace) {
// This is a crash in non-jitted code. Not something we want to handle here, ignore.
inCrashHandler = false;
return false;
}
@ -114,8 +120,10 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
bool invalidHostAddress = hostAddress == (uintptr_t)0xFFFFFFFFFFFFFFFFULL;
if (hostAddress < baseAddress || hostAddress >= baseAddress + addressSpaceSize) {
// Host address outside - this was a different kind of crash.
if (!invalidHostAddress)
if (!invalidHostAddress) {
inCrashHandler = 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.
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);
inCrashHandler = false;
return true;
} else if (success) {
if (info.isMemoryWrite) {
@ -218,6 +227,8 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
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());
}
inCrashHandler = false;
return true;
}

View File

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