Skip to content

Commit

Permalink
Merge pull request #16695 from hrydgard/memory-exception-report-size
Browse files Browse the repository at this point in the history
Memory exceptions: Keep track of access size
  • Loading branch information
hrydgard authored Jan 4, 2023
2 parents 933c909 + 700a018 commit 0076897
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 19 deletions.
16 changes: 9 additions & 7 deletions Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,13 +434,13 @@ const char *ExecExceptionTypeAsString(ExecExceptionType type) {
}
}

void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type) {
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", desc, address);
WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x)", desc, address, accessSize);
} else {
WARN_LOG(MEMMAP, "%s: Invalid address %08x PC %08x LR %08x", desc, address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
}

if (!g_Config.bIgnoreBadMemAccess) {
Expand All @@ -450,18 +450,19 @@ void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
e.info.clear();
e.memory_type = type;
e.address = address;
e.accessSize = accessSize;
e.pc = pc;
Core_EnableStepping(true, "memory.exception", address);
}
}

void Core_MemoryExceptionInfo(u32 address, u32 pc, MemoryExceptionType type, std::string additionalInfo, bool forceReport) {
void Core_MemoryExceptionInfo(u32 address, u32 pc, u32 accessSize, MemoryExceptionType type, std::string additionalInfo, bool forceReport) {
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());
WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x). %s", desc, address, accessSize, 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());
WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x %s", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA], additionalInfo.c_str());
}

if (!g_Config.bIgnoreBadMemAccess || forceReport) {
Expand All @@ -479,14 +480,15 @@ void Core_MemoryExceptionInfo(u32 address, u32 pc, MemoryExceptionType type, std
// Can't be ignored
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, pc, currentMIPS->r[MIPS_REG_RA]);
WARN_LOG(MEMMAP, "%s: Invalid exec address %08x PC %08x LR %08x", desc, address, pc, currentMIPS->r[MIPS_REG_RA]);

ExceptionInfo &e = g_exceptionInfo;
e = {};
e.type = ExceptionType::BAD_EXEC_ADDR;
e.info.clear();
e.exec_type = type;
e.address = address;
e.accessSize = 4; // size of an instruction
e.pc = pc;
// This just records the closest value that could be useful as reference.
e.ra = currentMIPS->r[MIPS_REG_RA];
Expand Down
5 changes: 3 additions & 2 deletions Core/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ enum class ExecExceptionType {
};

// Separate one for without info, to avoid having to allocate a string
void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type);
void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type);

void Core_MemoryExceptionInfo(u32 address, u32 pc, MemoryExceptionType type, std::string additionalInfo, bool forceReport);
void Core_MemoryExceptionInfo(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string additionalInfo, bool forceReport);

void Core_ExecException(u32 address, u32 pc, ExecExceptionType type);
void Core_Break(u32 pc);
Expand All @@ -125,6 +125,7 @@ struct ExceptionInfo {
MemoryExceptionType memory_type;
uint32_t pc;
uint32_t address;
uint32_t accessSize;
uint32_t ra = 0;

// Reuses pc and address from memory type, where address is the failed destination.
Expand Down
2 changes: 1 addition & 1 deletion Core/MIPS/IR/IRInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ u32 RunMemCheck(u32 pc, u32 addr) {
template <uint32_t alignment>
u32 RunValidateAddress(u32 pc, u32 addr, u32 isWrite) {
const auto toss = [&](MemoryExceptionType t) {
Core_MemoryException(addr, pc, t);
Core_MemoryException(addr, alignment, pc, t);
return coreState != CORE_RUNNING ? 1 : 0;
};

Expand Down
4 changes: 3 additions & 1 deletion Core/MemFault.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
// Either bIgnoreBadMemAccess is off, or we failed recovery analysis.
// We can't ignore this memory access.
uint32_t approximatePC = currentMIPS->pc;
Core_MemoryExceptionInfo(guestAddress, approximatePC, type, infoString, true);
// TODO: Determine access size from the disassembled native instruction. We have some partial info already,
// just need to clean it up.
Core_MemoryExceptionInfo(guestAddress, 0, approximatePC, type, infoString, true);

// There's a small chance we can resume from this type of crash.
g_lastCrashAddress = codePtr;
Expand Down
2 changes: 1 addition & 1 deletion Core/MemMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ inline void MemcpyUnchecked(const u32 to_address, const void *from_data, const u
}

inline void MemcpyUnchecked(const u32 to_address, const u32 from_address, const u32 len) {
MemcpyUnchecked(GetPointerWrite(to_address), from_address, len);
MemcpyUnchecked(GetPointerWriteUnchecked(to_address), from_address, len);
}

inline bool IsValidAddress(const u32 address) {
Expand Down
15 changes: 9 additions & 6 deletions Core/MemMapFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ u8 *GetPointerWrite(const u32 address) {
Reporting::ReportMessage("Unknown GetPointerWrite %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
reported = true;
}
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);

// Size is not known, we pass 0 to signal that.
Core_MemoryException(address, 0, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);
return nullptr;
}
}
Expand All @@ -57,7 +59,8 @@ const u8 *GetPointer(const u32 address) {
Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
reported = true;
}
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::READ_BLOCK);
// Size is not known, we pass 0 to signal that.
Core_MemoryException(address, 0, currentMIPS->pc, MemoryExceptionType::READ_BLOCK);
return nullptr;
}
}
Expand All @@ -67,7 +70,7 @@ u8 *GetPointerWriteRange(const u32 address, const u32 size) {
if (ptr) {
if (ValidSize(address, size) != size) {
// That's a memory exception! TODO: Adjust reported address to the end of the range?
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);
Core_MemoryException(address, size, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);
return nullptr;
} else {
return ptr;
Expand All @@ -83,7 +86,7 @@ const u8 *GetPointerRange(const u32 address, const u32 size) {
if (ptr) {
if (ValidSize(address, size) != size) {
// That's a memory exception! TODO: Adjust reported address to the end of the range?
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::READ_BLOCK);
Core_MemoryException(address, size, currentMIPS->pc, MemoryExceptionType::READ_BLOCK);
return nullptr;
} else {
return ptr;
Expand Down Expand Up @@ -115,7 +118,7 @@ inline void ReadFromHardware(T &var, const u32 address) {
Reporting::ReportMessage("ReadFromHardware: Invalid address %08x near PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
reported = true;
}
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::READ_WORD);
Core_MemoryException(address, sizeof(T), currentMIPS->pc, MemoryExceptionType::READ_WORD);
var = 0;
}
}
Expand All @@ -140,7 +143,7 @@ inline void WriteToHardware(u32 address, const T data) {
Reporting::ReportMessage("WriteToHardware: Invalid address %08x near PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
reported = true;
}
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::WRITE_WORD);
Core_MemoryException(address, sizeof(T), currentMIPS->pc, MemoryExceptionType::WRITE_WORD);
}
}

Expand Down
3 changes: 2 additions & 1 deletion UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,11 +1219,12 @@ static void DrawCrashDump(UIContext *ctx) {

if (info.type == ExceptionType::MEMORY) {
snprintf(statbuf, sizeof(statbuf), R"(
Access: %s at %08x
Access: %s at %08x (sz: %d)
PC: %08x
%s)",
MemoryExceptionTypeAsString(info.memory_type),
info.address,
info.accessSize,
info.pc,
info.info.c_str());
ctx->Draw()->DrawTextShadow(ubuntu24, statbuf, x, y, 0xFFFFFFFF);
Expand Down

0 comments on commit 0076897

Please sign in to comment.