mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Crash: Show disassembly of the instruction causing the crash, and the symbol name.
This commit is contained in:
parent
626d173d10
commit
8c38d7305e
4 changed files with 76 additions and 8 deletions
|
@ -436,6 +436,28 @@ void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
|
|||
}
|
||||
}
|
||||
|
||||
void Core_MemoryExceptionInfo(u32 address, u32 pc, MemoryExceptionType type, std::string additionalInfo) {
|
||||
const char *desc = MemoryExceptionTypeAsString(type);
|
||||
// In jit, we only flush PC when bIgnoreBadMemAccess is off.
|
||||
if (g_Config.iCpuCore == (int)CPUCore::JIT && g_Config.bIgnoreBadMemAccess) {
|
||||
WARN_LOG(MEMMAP, "%s: Invalid address %08x. %s", desc, address, additionalInfo.c_str());
|
||||
} else {
|
||||
WARN_LOG(MEMMAP, "%s: Invalid address %08x PC %08x LR %08x %s", desc, address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA], additionalInfo.c_str());
|
||||
}
|
||||
|
||||
if (!g_Config.bIgnoreBadMemAccess) {
|
||||
ExceptionInfo &e = g_exceptionInfo;
|
||||
e = {};
|
||||
e.type = ExceptionType::MEMORY;
|
||||
e.info = additionalInfo;
|
||||
e.memory_type = type;
|
||||
e.address = address;
|
||||
e.pc = pc;
|
||||
Core_EnableStepping(true);
|
||||
host->SetDebugMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) {
|
||||
const char *desc = ExecExceptionTypeAsString(type);
|
||||
WARN_LOG(MEMMAP, "%s: Invalid destination %08x PC %08x LR %08x", desc, address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Core/System.h"
|
||||
#include "Core/CoreParameter.h"
|
||||
|
||||
|
@ -92,7 +94,11 @@ enum class ExecExceptionType {
|
|||
THREAD,
|
||||
};
|
||||
|
||||
// Separate one for without info, to avoid having to allocate a string
|
||||
void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type);
|
||||
|
||||
void Core_MemoryExceptionInfo(u32 address, u32 pc, MemoryExceptionType type, std::string additionalInfo);
|
||||
|
||||
void Core_ExecException(u32 address, u32 pc, ExecExceptionType type);
|
||||
void Core_Break();
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86)
|
||||
#include "Common/x64Analyzer.h"
|
||||
|
||||
#elif PPSSPP_ARCH(ARM64)
|
||||
#include "Core/Util/DisArm64.h"
|
||||
#elif PPSSPP_ARCH(ARM)
|
||||
|
@ -42,6 +43,29 @@ void MemFault_Init() {
|
|||
|
||||
#ifdef MACHINE_CONTEXT_SUPPORTED
|
||||
|
||||
static bool DisassembleNativeAt(const uint8_t *codePtr, int instructionSize, std::string *dest) {
|
||||
#if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86)
|
||||
auto lines = DisassembleX86(codePtr, instructionSize);
|
||||
if (!lines.empty()) {
|
||||
*dest = lines[0];
|
||||
return true;
|
||||
}
|
||||
#elif PPSSPP_ARCH(ARM64)
|
||||
auto lines = DisassembleArm64(codePtr, instructionSize);
|
||||
if (!lines.empty()) {
|
||||
*dest = lines[0];
|
||||
return true;
|
||||
}
|
||||
#elif PPSSPP_ARCH(ARM)
|
||||
auto lines = DisassembleArm2(codePtr, instructionSize);
|
||||
if (!lines.empty()) {
|
||||
*dest = lines[0];
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
||||
SContext *context = (SContext *)ctx;
|
||||
const uint8_t *codePtr = (uint8_t *)(context->CTX_PC);
|
||||
|
@ -76,15 +100,23 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
|||
|
||||
MemoryExceptionType type = MemoryExceptionType::NONE;
|
||||
|
||||
std::string disassembly;
|
||||
std::string infoString = "";
|
||||
|
||||
if (MIPSComp::jit) {
|
||||
std::string desc;
|
||||
if (MIPSComp::jit->DescribeCodePtr(codePtr, desc)) {
|
||||
infoString += desc + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
int instructionSize = 4;
|
||||
#if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86)
|
||||
// X86, X86-64. Variable instruction size so need to analyze the mov instruction in detail.
|
||||
|
||||
// To ignore the access, we need to disassemble the instruction and modify context->CTX_PC
|
||||
LSInstructionInfo info;
|
||||
success = X86AnalyzeMOV(codePtr, info);
|
||||
|
||||
instructionSize = info.instructionSize;
|
||||
#elif PPSSPP_ARCH(ARM64)
|
||||
uint32_t word;
|
||||
memcpy(&word, codePtr, 4);
|
||||
|
@ -98,6 +130,12 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
|||
ArmLSInstructionInfo info;
|
||||
success = ArmAnalyzeLoadStore((uint32_t)codePtr, word, &info);
|
||||
#endif
|
||||
|
||||
std::string disassembly;
|
||||
if (DisassembleNativeAt(codePtr, instructionSize, &disassembly)) {
|
||||
infoString += disassembly + "\n";
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (info.isMemoryWrite) {
|
||||
type = MemoryExceptionType::WRITE_WORD;
|
||||
|
@ -122,11 +160,11 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
|||
} else {
|
||||
// Either bIgnoreBadMemAccess is off, or we failed recovery analysis.
|
||||
uint32_t approximatePC = currentMIPS->pc;
|
||||
Core_MemoryException(guestAddress, currentMIPS->pc, type);
|
||||
Core_MemoryExceptionInfo(guestAddress, approximatePC, type, infoString);
|
||||
|
||||
// Redirect execution to a crash handler that will exit the game.
|
||||
// Redirect execution to a crash handler that will exit the game immediately.
|
||||
context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler();
|
||||
ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation.", guestAddress, (void *)hostAddress);
|
||||
ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation. Info:\n%s", guestAddress, (void *)hostAddress, infoString.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1302,12 +1302,14 @@ ABI: %s
|
|||
if (info.type == ExceptionType::MEMORY) {
|
||||
snprintf(statbuf, sizeof(statbuf), R"(
|
||||
Access: %s at %08x
|
||||
PC: %08x)",
|
||||
PC: %08x
|
||||
%s)",
|
||||
MemoryExceptionTypeAsString(info.memory_type),
|
||||
info.address,
|
||||
info.pc);
|
||||
info.pc,
|
||||
info.info.c_str());
|
||||
draw2d->DrawTextShadow(ubuntu24, statbuf, x, y, 0xFFFFFFFF);
|
||||
y += 120;
|
||||
y += 180;
|
||||
} else if (info.type == ExceptionType::BAD_EXEC_ADDR) {
|
||||
snprintf(statbuf, sizeof(statbuf), R"(
|
||||
Destination: %s to %08x
|
||||
|
|
Loading…
Add table
Reference in a new issue