mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Debugger: Merge redundant memory interfaces
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "MemoryInterface.h"
|
||||
|
||||
#include <bit>
|
||||
|
||||
template <MemoryAccessType Value>
|
||||
Value MemoryInterface::Read(u32 address, bool* valid)
|
||||
{
|
||||
@@ -24,6 +26,10 @@ Value MemoryInterface::Read(u32 address, bool* valid)
|
||||
.hi = static_cast<s64>(value.hi),
|
||||
};
|
||||
}
|
||||
else if constexpr (std::is_same_v<Value, float>)
|
||||
return std::bit_cast<float>(Read32(address, valid));
|
||||
else if constexpr (std::is_same_v<Value, double>)
|
||||
return std::bit_cast<double>(Read64(address, valid));
|
||||
else
|
||||
return Value(0);
|
||||
}
|
||||
@@ -48,6 +54,10 @@ bool MemoryInterface::Write(u32 address, Value value)
|
||||
unsigned_value.hi = static_cast<u64>(value.hi);
|
||||
return Write128(address, unsigned_value);
|
||||
}
|
||||
else if constexpr (std::is_same_v<Value, float>)
|
||||
return Write32(address, std::bit_cast<u32>(value));
|
||||
else if constexpr (std::is_same_v<Value, double>)
|
||||
return Write64(address, std::bit_cast<u64>(value));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -135,4 +145,6 @@ EXPLICITLY_INSTANTIATE_TEMPLATES(u64)
|
||||
EXPLICITLY_INSTANTIATE_TEMPLATES(s64)
|
||||
EXPLICITLY_INSTANTIATE_TEMPLATES(u128)
|
||||
EXPLICITLY_INSTANTIATE_TEMPLATES(s128)
|
||||
EXPLICITLY_INSTANTIATE_TEMPLATES(float)
|
||||
EXPLICITLY_INSTANTIATE_TEMPLATES(double)
|
||||
#undef EXPLICITLY_INSTANTIATE_TEMPLATES
|
||||
|
||||
@@ -12,12 +12,15 @@ concept MemoryAccessType = std::is_same_v<Value, u8> || std::is_same_v<Value, s8
|
||||
std::is_same_v<Value, u16> || std::is_same_v<Value, s16> ||
|
||||
std::is_same_v<Value, u32> || std::is_same_v<Value, s32> ||
|
||||
std::is_same_v<Value, u64> || std::is_same_v<Value, s64> ||
|
||||
std::is_same_v<Value, u128> || std::is_same_v<Value, s128>;
|
||||
std::is_same_v<Value, u128> || std::is_same_v<Value, s128> ||
|
||||
std::is_same_v<Value, float> || std::is_same_v<Value, double>;
|
||||
|
||||
/// Interface for reading/writing guest memory.
|
||||
class MemoryInterface
|
||||
{
|
||||
public:
|
||||
virtual ~MemoryInterface() {}
|
||||
|
||||
virtual u8 Read8(u32 address, bool* valid = nullptr) = 0;
|
||||
virtual u16 Read16(u32 address, bool* valid = nullptr) = 0;
|
||||
virtual u32 Read32(u32 address, bool* valid = nullptr) = 0;
|
||||
|
||||
@@ -204,7 +204,7 @@ void DisassemblyView::contextRestoreInstruction()
|
||||
{
|
||||
u32 address = start + i * 4;
|
||||
if (original_instructions[i].has_value())
|
||||
cpu->write32(address, *original_instructions[i]);
|
||||
cpu->Write32(address, *original_instructions[i]);
|
||||
}
|
||||
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
|
||||
});
|
||||
@@ -332,11 +332,11 @@ void DisassemblyView::contextStubFunction()
|
||||
|
||||
const QPointer<DisassemblyView> view(this);
|
||||
Host::RunOnCPUThread([view, address, cpu = &cpu()] {
|
||||
const u32 first_instruction = cpu->read32(address);
|
||||
const u32 second_instruction = cpu->read32(address + 4);
|
||||
const u32 first_instruction = cpu->Read32(address);
|
||||
const u32 second_instruction = cpu->Read32(address + 4);
|
||||
|
||||
cpu->write32(address, 0x03E00008); // jr ra
|
||||
cpu->write32(address + 4, 0x00000000); // nop
|
||||
cpu->Write32(address, 0x03E00008); // jr ra
|
||||
cpu->Write32(address + 4, 0x00000000); // nop
|
||||
|
||||
QtHost::RunOnUIThread([view, address, first_instruction, second_instruction]() {
|
||||
if (!view)
|
||||
@@ -364,8 +364,8 @@ void DisassemblyView::contextRestoreFunction()
|
||||
m_stubbedFunctions.erase(stub);
|
||||
|
||||
Host::RunOnCPUThread([address, cpu = &cpu(), first_instruction, second_instruction] {
|
||||
cpu->write32(address, first_instruction);
|
||||
cpu->write32(address + 4, second_instruction);
|
||||
cpu->Write32(address, first_instruction);
|
||||
cpu->Write32(address + 4, second_instruction);
|
||||
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
|
||||
});
|
||||
}
|
||||
@@ -919,7 +919,7 @@ inline QString DisassemblyView::DisassemblyStringFromAddress(u32 address, QFont
|
||||
|
||||
if (showOpcode)
|
||||
{
|
||||
const u32 opcode = cpu().read32(address);
|
||||
const u32 opcode = cpu().Read32(address);
|
||||
lineString = lineString.arg(QtUtils::FilledQStringFromValue(opcode, 16));
|
||||
}
|
||||
|
||||
@@ -989,7 +989,7 @@ QString DisassemblyView::FetchSelectionInfo(SelectionInfo selInfo)
|
||||
}
|
||||
else // INSTRUCTIONHEX
|
||||
{
|
||||
infoBlock += FilledQStringFromValue(cpu().read32(i), 16);
|
||||
infoBlock += FilledQStringFromValue(cpu().Read32(i), 16);
|
||||
}
|
||||
}
|
||||
return infoBlock;
|
||||
@@ -1050,8 +1050,8 @@ void DisassemblyView::setInstructions(u32 start, u32 end, u32 value)
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
const u32 address = start + i * 4;
|
||||
original_instructions.emplace_back(cpu->read32(address));
|
||||
cpu->write32(address, value);
|
||||
original_instructions.emplace_back(cpu->Read32(address));
|
||||
cpu->Write32(address, value);
|
||||
}
|
||||
|
||||
QtHost::RunOnUIThread([view, start, count, original_instructions = std::move(original_instructions)]() {
|
||||
|
||||
@@ -112,46 +112,6 @@ void MemorySearchView::onListSearchResultsContextMenu(QPoint pos)
|
||||
menu->popup(m_ui.listSearchResults->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T readValueAtAddress(DebugInterface* cpu, u32 addr);
|
||||
template <>
|
||||
float readValueAtAddress<float>(DebugInterface* cpu, u32 addr)
|
||||
{
|
||||
return std::bit_cast<float>(cpu->read32(addr));
|
||||
}
|
||||
|
||||
template <>
|
||||
double readValueAtAddress<double>(DebugInterface* cpu, u32 addr)
|
||||
{
|
||||
return std::bit_cast<double>(cpu->read64(addr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T readValueAtAddress(DebugInterface* cpu, u32 addr)
|
||||
{
|
||||
T val = 0;
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case sizeof(u8):
|
||||
val = cpu->read8(addr);
|
||||
break;
|
||||
case sizeof(u16):
|
||||
val = cpu->read16(addr);
|
||||
break;
|
||||
case sizeof(u32):
|
||||
{
|
||||
val = cpu->read32(addr);
|
||||
break;
|
||||
}
|
||||
case sizeof(u64):
|
||||
{
|
||||
val = cpu->read64(addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool memoryValueComparator(SearchComparison searchComparison, T searchValue, T readValue)
|
||||
{
|
||||
@@ -294,7 +254,7 @@ void searchWorker(DebugInterface* cpu, std::vector<SearchResult>& searchResults,
|
||||
if (!cpu->isValidAddress(addr))
|
||||
continue;
|
||||
|
||||
T readValue = readValueAtAddress<T>(cpu, addr);
|
||||
T readValue = cpu->Read<T>(addr);
|
||||
if (handleSearchComparison(searchComparison, addr, nullptr, searchValue, readValue))
|
||||
{
|
||||
searchResults.push_back(MemorySearchView::SearchResult(addr, QVariant::fromValue(readValue), searchType));
|
||||
@@ -308,7 +268,7 @@ void searchWorker(DebugInterface* cpu, std::vector<SearchResult>& searchResults,
|
||||
if (!cpu->isValidAddress(addr))
|
||||
return true;
|
||||
|
||||
const auto readValue = readValueAtAddress<T>(cpu, addr);
|
||||
const auto readValue = cpu->Read<T>(addr);
|
||||
|
||||
const bool doesMatch = handleSearchComparison(searchComparison, addr, &searchResult, searchValue, readValue);
|
||||
if (doesMatch)
|
||||
@@ -325,7 +285,7 @@ static bool compareByteArrayAtAddress(DebugInterface* cpu, SearchComparison sear
|
||||
const bool isNotOperator = searchComparison == SearchComparison::NotEquals;
|
||||
for (qsizetype i = 0; i < value.length(); i++)
|
||||
{
|
||||
const char nextByte = cpu->read8(addr + i);
|
||||
const char nextByte = cpu->Read8(addr + i);
|
||||
switch (searchComparison)
|
||||
{
|
||||
case SearchComparison::Equals:
|
||||
@@ -383,7 +343,7 @@ static QByteArray readArrayAtAddress(DebugInterface* cpu, u32 address, u32 lengt
|
||||
QByteArray readArray;
|
||||
for (u32 i = address; i < address + length; i++)
|
||||
{
|
||||
readArray.append(cpu->read8(i));
|
||||
readArray.append(cpu->Read8(i));
|
||||
}
|
||||
return readArray;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
{
|
||||
case MemoryViewType::BYTE:
|
||||
{
|
||||
const u8 val = static_cast<u8>(cpu.read8(thisSegmentsStart, valid));
|
||||
const u8 val = cpu.Read8(thisSegmentsStart, &valid);
|
||||
if (penDefault && val == 0)
|
||||
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "??");
|
||||
@@ -127,7 +127,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
}
|
||||
case MemoryViewType::BYTEHW:
|
||||
{
|
||||
const u16 val = convertEndian<u16>(static_cast<u16>(cpu.read16(thisSegmentsStart, valid)));
|
||||
const u16 val = convertEndian<u16>(cpu.Read16(thisSegmentsStart, &valid));
|
||||
if (penDefault && val == 0)
|
||||
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????");
|
||||
@@ -135,7 +135,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
}
|
||||
case MemoryViewType::WORD:
|
||||
{
|
||||
const u32 val = convertEndian<u32>(cpu.read32(thisSegmentsStart, valid));
|
||||
const u32 val = convertEndian<u32>(cpu.Read32(thisSegmentsStart, &valid));
|
||||
if (penDefault && val == 0)
|
||||
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????");
|
||||
@@ -143,7 +143,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
}
|
||||
case MemoryViewType::DWORD:
|
||||
{
|
||||
const u64 val = convertEndian<u64>(cpu.read64(thisSegmentsStart, valid));
|
||||
const u64 val = convertEndian<u64>(cpu.Read64(thisSegmentsStart, &valid));
|
||||
if (penDefault && val == 0)
|
||||
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????????????");
|
||||
@@ -151,7 +151,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
}
|
||||
case MemoryViewType::FLOAT:
|
||||
{
|
||||
const u32 intVal = convertEndian<u32>(cpu.read32(thisSegmentsStart, valid));
|
||||
const u32 intVal = convertEndian<u32>(cpu.Read32(thisSegmentsStart, &valid));
|
||||
float val = 0.0;
|
||||
std::memcpy(&val, &intVal, sizeof(val));
|
||||
if (penDefault && val == 0.0)
|
||||
@@ -177,7 +177,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
painter.setPen(palette.text().color());
|
||||
|
||||
bool valid;
|
||||
const u8 value = cpu.read8(currentRowAddress + j, valid);
|
||||
const u8 value = cpu.Read8(currentRowAddress + j, &valid);
|
||||
if (valid)
|
||||
{
|
||||
QChar curChar = QChar::fromLatin1(value);
|
||||
@@ -258,19 +258,19 @@ u128 MemoryViewTable::GetSelectedSegment(DebugInterface& cpu)
|
||||
switch (displayType)
|
||||
{
|
||||
case MemoryViewType::BYTE:
|
||||
val.lo = cpu.read8(selectedAddress);
|
||||
val.lo = cpu.Read8(selectedAddress);
|
||||
break;
|
||||
case MemoryViewType::BYTEHW:
|
||||
val.lo = convertEndian(static_cast<u16>(cpu.read16(selectedAddress & ~1)));
|
||||
val.lo = convertEndian(static_cast<u16>(cpu.Read16(selectedAddress & ~1)));
|
||||
break;
|
||||
case MemoryViewType::WORD:
|
||||
val.lo = convertEndian(cpu.read32(selectedAddress & ~3));
|
||||
val.lo = convertEndian(cpu.Read32(selectedAddress & ~3));
|
||||
break;
|
||||
case MemoryViewType::DWORD:
|
||||
val._u64[0] = convertEndian(cpu.read64(selectedAddress & ~7));
|
||||
val._u64[0] = convertEndian(cpu.Read64(selectedAddress & ~7));
|
||||
break;
|
||||
case MemoryViewType::FLOAT:
|
||||
val.lo = convertEndian(cpu.read32(selectedAddress & ~3));
|
||||
val.lo = convertEndian(cpu.Read32(selectedAddress & ~3));
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
@@ -279,13 +279,13 @@ u128 MemoryViewTable::GetSelectedSegment(DebugInterface& cpu)
|
||||
void MemoryViewTable::InsertIntoSelectedHexView(u8 value, DebugInterface& cpu)
|
||||
{
|
||||
const u8 mask = selectedNibbleHI ? 0x0f : 0xf0;
|
||||
u8 curVal = cpu.read8(selectedAddress) & mask;
|
||||
u8 curVal = cpu.Read8(selectedAddress) & mask;
|
||||
u8 newVal = value << (selectedNibbleHI ? 4 : 0);
|
||||
curVal |= newVal;
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = curVal] {
|
||||
cpu.write8(address, val);
|
||||
cpu.Write8(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
@@ -323,7 +323,7 @@ bool MemoryViewTable::InsertFloatIntoSelectedHexView(DebugInterface& cpu)
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
|
||||
cpu.write32(address, val);
|
||||
cpu.Write32(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
@@ -360,7 +360,7 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterfa
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
|
||||
cpu.write32(address, val);
|
||||
cpu.Write32(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
@@ -384,7 +384,7 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterfa
|
||||
u32 currAddr = address;
|
||||
for (int i = 0; i < input.size(); i++)
|
||||
{
|
||||
cpu.write8(currAddr, input[i]);
|
||||
cpu.Write8(currAddr, input[i]);
|
||||
currAddr = nextAddress(currAddr, address, display_type, little_endian);
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
|
||||
{
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = keychar.toLatin1()] {
|
||||
cpu.write8(address, val);
|
||||
cpu.Write8(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table, address]() {
|
||||
if (!table)
|
||||
@@ -572,7 +572,7 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
|
||||
{
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu] {
|
||||
cpu.write8(address, 0);
|
||||
cpu.Write8(address, 0);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
@@ -865,7 +865,7 @@ void MemoryView::openContextMenu(QPoint pos)
|
||||
|
||||
void MemoryView::contextCopyByte()
|
||||
{
|
||||
QApplication::clipboard()->setText(QString::number(cpu().read8(m_table.selectedAddress), 16).toUpper());
|
||||
QApplication::clipboard()->setText(QString::number(cpu().Read8(m_table.selectedAddress), 16).toUpper());
|
||||
}
|
||||
|
||||
void MemoryView::contextCopySegment()
|
||||
@@ -885,7 +885,7 @@ void MemoryView::contextCopySegment()
|
||||
|
||||
void MemoryView::contextCopyCharacter()
|
||||
{
|
||||
QApplication::clipboard()->setText(QChar::fromLatin1(cpu().read8(m_table.selectedAddress)).toUpper());
|
||||
QApplication::clipboard()->setText(QChar::fromLatin1(cpu().Read8(m_table.selectedAddress)).toUpper());
|
||||
}
|
||||
|
||||
void MemoryView::contextPaste()
|
||||
@@ -913,7 +913,7 @@ void MemoryView::contextGoToAddress()
|
||||
void MemoryView::contextFollowAddress()
|
||||
{
|
||||
bool valid;
|
||||
u32 address = cpu().read32(m_table.selectedAddress & ~3, valid);
|
||||
u32 address = cpu().Read32(m_table.selectedAddress & ~3, &valid);
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ u8 SymbolTreeLocation::read8(DebugInterface& cpu) const
|
||||
return cpu.getRegister(EECAT_GPR, address)._u8[0];
|
||||
break;
|
||||
case MEMORY:
|
||||
return (u8)cpu.read8(address);
|
||||
return cpu.Read8(address);
|
||||
default:
|
||||
{
|
||||
}
|
||||
@@ -77,7 +77,7 @@ u16 SymbolTreeLocation::read16(DebugInterface& cpu) const
|
||||
return cpu.getRegister(EECAT_GPR, address)._u16[0];
|
||||
break;
|
||||
case MEMORY:
|
||||
return (u16)cpu.read16(address);
|
||||
return cpu.Read16(address);
|
||||
default:
|
||||
{
|
||||
}
|
||||
@@ -94,7 +94,7 @@ u32 SymbolTreeLocation::read32(DebugInterface& cpu) const
|
||||
return cpu.getRegister(EECAT_GPR, address)._u32[0];
|
||||
break;
|
||||
case MEMORY:
|
||||
return cpu.read32(address);
|
||||
return cpu.Read32(address);
|
||||
default:
|
||||
{
|
||||
}
|
||||
@@ -111,7 +111,7 @@ u64 SymbolTreeLocation::read64(DebugInterface& cpu) const
|
||||
return cpu.getRegister(EECAT_GPR, address)._u64[0];
|
||||
break;
|
||||
case MEMORY:
|
||||
return cpu.read64(address);
|
||||
return cpu.Read64(address);
|
||||
default:
|
||||
{
|
||||
}
|
||||
@@ -128,7 +128,7 @@ u128 SymbolTreeLocation::read128(DebugInterface& cpu) const
|
||||
return cpu.getRegister(EECAT_GPR, address);
|
||||
break;
|
||||
case MEMORY:
|
||||
return cpu.read128(address);
|
||||
return cpu.Read128(address);
|
||||
default:
|
||||
{
|
||||
}
|
||||
@@ -145,7 +145,7 @@ void SymbolTreeLocation::write8(u8 value, DebugInterface& cpu) const
|
||||
cpu.setRegister(0, address, u128::From32(value));
|
||||
break;
|
||||
case MEMORY:
|
||||
cpu.write8(address, value);
|
||||
cpu.Write8(address, value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -162,7 +162,7 @@ void SymbolTreeLocation::write16(u16 value, DebugInterface& cpu) const
|
||||
cpu.setRegister(0, address, u128::From32(value));
|
||||
break;
|
||||
case MEMORY:
|
||||
cpu.write16(address, value);
|
||||
cpu.Write16(address, value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -179,7 +179,7 @@ void SymbolTreeLocation::write32(u32 value, DebugInterface& cpu) const
|
||||
cpu.setRegister(0, address, u128::From32(value));
|
||||
break;
|
||||
case MEMORY:
|
||||
cpu.write32(address, value);
|
||||
cpu.Write32(address, value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -196,7 +196,7 @@ void SymbolTreeLocation::write64(u64 value, DebugInterface& cpu) const
|
||||
cpu.setRegister(0, address, u128::From64(value));
|
||||
break;
|
||||
case MEMORY:
|
||||
cpu.write64(address, value);
|
||||
cpu.Write64(address, value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -213,7 +213,7 @@ void SymbolTreeLocation::write128(u128 value, DebugInterface& cpu) const
|
||||
cpu.setRegister(0, address, value);
|
||||
break;
|
||||
case MEMORY:
|
||||
cpu.write128(address, value);
|
||||
cpu.Write128(address, value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
|
||||
+220
-209
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@
|
||||
#include "SymbolGuardian.h"
|
||||
#include "SymbolImporter.h"
|
||||
|
||||
#include "common/MemoryInterface.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
enum
|
||||
@@ -38,20 +40,7 @@ inline const std::array<BreakPointCpu, 2> DEBUG_CPUS = {
|
||||
BREAKPOINT_IOP,
|
||||
};
|
||||
|
||||
class MemoryReader
|
||||
{
|
||||
public:
|
||||
virtual u32 read8(u32 address) = 0;
|
||||
virtual u32 read8(u32 address, bool& valid) = 0;
|
||||
virtual u32 read16(u32 address) = 0;
|
||||
virtual u32 read16(u32 address, bool& valid) = 0;
|
||||
virtual u32 read32(u32 address) = 0;
|
||||
virtual u32 read32(u32 address, bool& valid) = 0;
|
||||
virtual u64 read64(u32 address) = 0;
|
||||
virtual u64 read64(u32 address, bool& valid) = 0;
|
||||
};
|
||||
|
||||
class DebugInterface : public MemoryReader
|
||||
class DebugInterface : public MemoryInterface
|
||||
{
|
||||
public:
|
||||
enum RegisterType
|
||||
@@ -60,13 +49,6 @@ public:
|
||||
SPECIAL
|
||||
};
|
||||
|
||||
virtual u128 read128(u32 address) = 0;
|
||||
virtual void write8(u32 address, u8 value) = 0;
|
||||
virtual void write16(u32 address, u16 value) = 0;
|
||||
virtual void write32(u32 address, u32 value) = 0;
|
||||
virtual void write64(u32 address, u64 value) = 0;
|
||||
virtual void write128(u32 address, u128 value) = 0;
|
||||
|
||||
// register stuff
|
||||
virtual int getRegisterCategoryCount() = 0;
|
||||
virtual const char* getRegisterCategoryName(int cat) = 0;
|
||||
@@ -119,20 +101,21 @@ private:
|
||||
class R5900DebugInterface : public DebugInterface
|
||||
{
|
||||
public:
|
||||
u32 read8(u32 address) override;
|
||||
u32 read8(u32 address, bool& valid) override;
|
||||
u32 read16(u32 address) override;
|
||||
u32 read16(u32 address, bool& valid) override;
|
||||
u32 read32(u32 address) override;
|
||||
u32 read32(u32 address, bool& valid) override;
|
||||
u64 read64(u32 address) override;
|
||||
u64 read64(u32 address, bool& valid) override;
|
||||
u128 read128(u32 address) override;
|
||||
void write8(u32 address, u8 value) override;
|
||||
void write16(u32 address, u16 value) override;
|
||||
void write32(u32 address, u32 value) override;
|
||||
void write64(u32 address, u64 value) override;
|
||||
void write128(u32 address, u128 value) override;
|
||||
u8 Read8(u32 address, bool* valid = nullptr) override;
|
||||
u16 Read16(u32 address, bool* valid = nullptr) override;
|
||||
u32 Read32(u32 address, bool* valid = nullptr) override;
|
||||
u64 Read64(u32 address, bool* valid = nullptr) override;
|
||||
u128 Read128(u32 address, bool* valid = nullptr) override;
|
||||
bool ReadBytes(u32 address, void* dest, u32 size) override;
|
||||
|
||||
bool Write8(u32 address, u8 value) override;
|
||||
bool Write16(u32 address, u16 value) override;
|
||||
bool Write32(u32 address, u32 value) override;
|
||||
bool Write64(u32 address, u64 value) override;
|
||||
bool Write128(u32 address, u128 value) override;
|
||||
bool WriteBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
bool CompareBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
// register stuff
|
||||
int getRegisterCategoryCount() override;
|
||||
@@ -163,20 +146,21 @@ public:
|
||||
class R3000DebugInterface : public DebugInterface
|
||||
{
|
||||
public:
|
||||
u32 read8(u32 address) override;
|
||||
u32 read8(u32 address, bool& valid) override;
|
||||
u32 read16(u32 address) override;
|
||||
u32 read16(u32 address, bool& valid) override;
|
||||
u32 read32(u32 address) override;
|
||||
u32 read32(u32 address, bool& valid) override;
|
||||
u64 read64(u32 address) override;
|
||||
u64 read64(u32 address, bool& valid) override;
|
||||
u128 read128(u32 address) override;
|
||||
void write8(u32 address, u8 value) override;
|
||||
void write16(u32 address, u16 value) override;
|
||||
void write32(u32 address, u32 value) override;
|
||||
void write64(u32 address, u64 value) override;
|
||||
void write128(u32 address, u128 value) override;
|
||||
u8 Read8(u32 address, bool* valid = nullptr) override;
|
||||
u16 Read16(u32 address, bool* valid = nullptr) override;
|
||||
u32 Read32(u32 address, bool* valid = nullptr) override;
|
||||
u64 Read64(u32 address, bool* valid = nullptr) override;
|
||||
u128 Read128(u32 address, bool* valid = nullptr) override;
|
||||
bool ReadBytes(u32 address, void* dest, u32 size) override;
|
||||
|
||||
bool Write8(u32 address, u8 value) override;
|
||||
bool Write16(u32 address, u16 value) override;
|
||||
bool Write32(u32 address, u32 value) override;
|
||||
bool Write64(u32 address, u64 value) override;
|
||||
bool Write128(u32 address, u128 value) override;
|
||||
bool WriteBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
bool CompareBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
// register stuff
|
||||
int getRegisterCategoryCount() override;
|
||||
@@ -205,19 +189,26 @@ public:
|
||||
};
|
||||
|
||||
// Provides access to the loadable segments from the ELF as they are on disk.
|
||||
class ElfMemoryReader : public MemoryReader
|
||||
class ElfMemoryReader : public MemoryInterface
|
||||
{
|
||||
public:
|
||||
ElfMemoryReader(const ccc::ElfFile& elf);
|
||||
|
||||
u32 read8(u32 address) override;
|
||||
u32 read8(u32 address, bool& valid) override;
|
||||
u32 read16(u32 address) override;
|
||||
u32 read16(u32 address, bool& valid) override;
|
||||
u32 read32(u32 address) override;
|
||||
u32 read32(u32 address, bool& valid) override;
|
||||
u64 read64(u32 address) override;
|
||||
u64 read64(u32 address, bool& valid) override;
|
||||
u8 Read8(u32 address, bool* valid = nullptr) override;
|
||||
u16 Read16(u32 address, bool* valid = nullptr) override;
|
||||
u32 Read32(u32 address, bool* valid = nullptr) override;
|
||||
u64 Read64(u32 address, bool* valid = nullptr) override;
|
||||
u128 Read128(u32 address, bool* valid = nullptr) override;
|
||||
bool ReadBytes(u32 address, void* dest, u32 size) override;
|
||||
|
||||
bool Write8(u32 address, u8 value) override;
|
||||
bool Write16(u32 address, u16 value) override;
|
||||
bool Write32(u32 address, u32 value) override;
|
||||
bool Write64(u32 address, u64 value) override;
|
||||
bool Write128(u32 address, u128 value) override;
|
||||
bool WriteBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
bool CompareBytes(u32 address, void* src, u32 size) override;
|
||||
|
||||
protected:
|
||||
const ccc::ElfFile& m_elf;
|
||||
|
||||
@@ -23,7 +23,7 @@ static u32 computeHash(u32 address, u32 size)
|
||||
u32 hash = 0xBACD7814;
|
||||
while (address < end)
|
||||
{
|
||||
hash += r5900Debug.read32(address);
|
||||
hash += r5900Debug.Read32(address);
|
||||
address += 4;
|
||||
}
|
||||
return hash;
|
||||
@@ -918,7 +918,7 @@ void DisassemblyData::createLines()
|
||||
bool inString = false;
|
||||
while (pos < end)
|
||||
{
|
||||
u8 b = r5900Debug.read8(pos++);
|
||||
u8 b = r5900Debug.Read8(pos++);
|
||||
if (b >= 0x20 && b <= 0x7F)
|
||||
{
|
||||
if (currentLine.size()+1 >= maxChars)
|
||||
@@ -995,18 +995,18 @@ void DisassemblyData::createLines()
|
||||
switch (type)
|
||||
{
|
||||
case DATATYPE_BYTE:
|
||||
value = cpu->read8(pos);
|
||||
value = cpu->Read8(pos);
|
||||
std::snprintf(buffer,std::size(buffer),"0x%02X",value);
|
||||
pos++;
|
||||
break;
|
||||
case DATATYPE_HALFWORD:
|
||||
value = cpu->read16(pos);
|
||||
value = cpu->Read16(pos);
|
||||
std::snprintf(buffer,std::size(buffer),"0x%04X",value);
|
||||
pos += 2;
|
||||
break;
|
||||
case DATATYPE_WORD:
|
||||
{
|
||||
value = cpu->read32(pos);
|
||||
value = cpu->Read32(pos);
|
||||
const std::string label = cpu->GetSymbolGuardian().SymbolStartingAtAddress(value).name;
|
||||
if (!label.empty())
|
||||
std::snprintf(buffer,std::size(buffer),"%s",label.c_str());
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
namespace MIPSAnalyst
|
||||
{
|
||||
u32 GetJumpTarget(u32 addr, MemoryReader& reader)
|
||||
u32 GetJumpTarget(u32 addr, MemoryInterface& reader)
|
||||
{
|
||||
u32 op = reader.read32(addr);
|
||||
u32 op = reader.Read32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
if ((opcode.flags & IS_BRANCH) && (opcode.flags & BRANCHTYPE_MASK) == BRANCHTYPE_JUMP)
|
||||
@@ -38,9 +38,9 @@ namespace MIPSAnalyst
|
||||
return INVALIDTARGET;
|
||||
}
|
||||
|
||||
u32 GetBranchTarget(u32 addr, MemoryReader& reader)
|
||||
u32 GetBranchTarget(u32 addr, MemoryInterface& reader)
|
||||
{
|
||||
u32 op = reader.read32(addr);
|
||||
u32 op = reader.Read32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
int branchType = (opcode.flags & BRANCHTYPE_MASK);
|
||||
@@ -50,9 +50,9 @@ namespace MIPSAnalyst
|
||||
return INVALIDTARGET;
|
||||
}
|
||||
|
||||
u32 GetBranchTargetNoRA(u32 addr, MemoryReader& reader)
|
||||
u32 GetBranchTargetNoRA(u32 addr, MemoryInterface& reader)
|
||||
{
|
||||
u32 op = reader.read32(addr);
|
||||
u32 op = reader.Read32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
int branchType = (opcode.flags & BRANCHTYPE_MASK);
|
||||
@@ -67,9 +67,9 @@ namespace MIPSAnalyst
|
||||
return INVALIDTARGET;
|
||||
}
|
||||
|
||||
u32 GetSureBranchTarget(u32 addr, MemoryReader& reader)
|
||||
u32 GetSureBranchTarget(u32 addr, MemoryInterface& reader)
|
||||
{
|
||||
u32 op = reader.read32(addr);
|
||||
u32 op = reader.Read32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
if ((opcode.flags & IS_BRANCH) && (opcode.flags & BRANCHTYPE_MASK) == BRANCHTYPE_BRANCH)
|
||||
@@ -115,7 +115,7 @@ namespace MIPSAnalyst
|
||||
return INVALIDTARGET;
|
||||
}
|
||||
|
||||
static u32 ScanAheadForJumpback(u32 fromAddr, u32 knownStart, u32 knownEnd, MemoryReader& reader) {
|
||||
static u32 ScanAheadForJumpback(u32 fromAddr, u32 knownStart, u32 knownEnd, MemoryInterface& reader) {
|
||||
static const u32 MAX_AHEAD_SCAN = 0x1000;
|
||||
// Maybe a bit high... just to make sure we don't get confused by recursive tail recursion.
|
||||
static const u32 MAX_FUNC_SIZE = 0x20000;
|
||||
@@ -134,7 +134,7 @@ namespace MIPSAnalyst
|
||||
u32 furthestJumpbackAddr = INVALIDTARGET;
|
||||
|
||||
for (u32 ahead = fromAddr; ahead < fromAddr + MAX_AHEAD_SCAN; ahead += 4) {
|
||||
u32 aheadOp = reader.read32(ahead);
|
||||
u32 aheadOp = reader.Read32(ahead);
|
||||
u32 target = GetBranchTargetNoRA(ahead, reader);
|
||||
if (target == INVALIDTARGET && ((aheadOp & 0xFC000000) == 0x08000000)) {
|
||||
target = GetJumpTarget(ahead, reader);
|
||||
@@ -158,7 +158,7 @@ namespace MIPSAnalyst
|
||||
|
||||
if (closestJumpbackAddr != INVALIDTARGET && furthestJumpbackAddr == INVALIDTARGET) {
|
||||
for (u32 behind = closestJumpbackTarget; behind < fromAddr; behind += 4) {
|
||||
u32 behindOp = reader.read32(behind);
|
||||
u32 behindOp = reader.Read32(behind);
|
||||
u32 target = GetBranchTargetNoRA(behind, reader);
|
||||
if (target == INVALIDTARGET && ((behindOp & 0xFC000000) == 0x08000000)) {
|
||||
target = GetJumpTarget(behind, reader);
|
||||
@@ -175,7 +175,7 @@ namespace MIPSAnalyst
|
||||
return furthestJumpbackAddr;
|
||||
}
|
||||
|
||||
void ScanForFunctions(ccc::SymbolDatabase& database, MemoryReader& reader, u32 startAddr, u32 endAddr, bool generateHashes) {
|
||||
void ScanForFunctions(ccc::SymbolDatabase& database, MemoryInterface& reader, u32 startAddr, u32 endAddr, bool generateHashes) {
|
||||
std::vector<MIPSAnalyst::AnalyzedFunction> functions;
|
||||
AnalyzedFunction currentFunction = {startAddr};
|
||||
|
||||
@@ -200,7 +200,7 @@ namespace MIPSAnalyst
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 op = reader.read32(addr);
|
||||
u32 op = reader.Read32(addr);
|
||||
|
||||
u32 target = GetBranchTargetNoRA(addr, reader);
|
||||
if (target != INVALIDTARGET) {
|
||||
@@ -288,7 +288,7 @@ namespace MIPSAnalyst
|
||||
// Most functions are aligned to 8 or 16 bytes, so add padding
|
||||
// to this one unless a symbol exists implying a new function
|
||||
// follows immediately.
|
||||
while (next_symbol == nullptr && ((addr+8) % 16) && reader.read32(addr+8) == 0)
|
||||
while (next_symbol == nullptr && ((addr+8) % 16) && reader.Read32(addr+8) == 0)
|
||||
addr += 4;
|
||||
|
||||
currentFunction.end = addr + 4;
|
||||
@@ -373,7 +373,7 @@ namespace MIPSAnalyst
|
||||
|
||||
info.cpu = cpu;
|
||||
info.opcodeAddress = address;
|
||||
info.encodedOpcode = cpu->read32(address);
|
||||
info.encodedOpcode = cpu->Read32(address);
|
||||
u32 op = info.encodedOpcode;
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "DebugInterface.h"
|
||||
#include "SymbolGuardian.h"
|
||||
|
||||
#include "common/MemoryInterface.h"
|
||||
|
||||
#define MIPS_GET_OP(op) ((op>>26) & 0x3F)
|
||||
#define MIPS_GET_FUNC(op) (op & 0x3F)
|
||||
#define MIPS_GET_SA(op) ((op>>6) & 0x1F)
|
||||
@@ -27,7 +29,7 @@ namespace MIPSAnalyst
|
||||
char name[64];
|
||||
};
|
||||
|
||||
void ScanForFunctions(ccc::SymbolDatabase& database, MemoryReader& reader, u32 startAddr, u32 endAddr, bool generateHashes);
|
||||
void ScanForFunctions(ccc::SymbolDatabase& database, MemoryInterface& reader, u32 startAddr, u32 endAddr, bool generateHashes);
|
||||
|
||||
enum LoadStoreLRType { LOADSTORE_NORMAL, LOADSTORE_LEFT, LOADSTORE_RIGHT };
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace MipsStackWalk
|
||||
u32 stop = pc - 32 * 4;
|
||||
for (; cpu->isValidAddress(pc) && pc >= stop; pc -= 4)
|
||||
{
|
||||
u32 rawOp = cpu->read32(pc);
|
||||
u32 rawOp = cpu->Read32(pc);
|
||||
const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
|
||||
|
||||
// We're looking for a "mov fp, sp" close by a "addiu sp, sp, -N".
|
||||
@@ -113,7 +113,7 @@ namespace MipsStackWalk
|
||||
|
||||
for (u32 pc = start; cpu->isValidAddress(pc) && pc >= stop; pc -= 4)
|
||||
{
|
||||
u32 rawOp = cpu->read32(pc);
|
||||
u32 rawOp = cpu->Read32(pc);
|
||||
const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
|
||||
|
||||
// Look for RA write to ram
|
||||
@@ -154,7 +154,7 @@ namespace MipsStackWalk
|
||||
frame.stackSize = -_IMM16;
|
||||
if (ra_offset != -1 && cpu->isValidAddress(frame.sp + ra_offset))
|
||||
{
|
||||
ra = cpu->read32(frame.sp + ra_offset);
|
||||
ra = cpu->Read32(frame.sp + ra_offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ FunctionInfo SymbolGuardian::FunctionOverlappingAddress(u32 address) const
|
||||
return info;
|
||||
}
|
||||
|
||||
void SymbolGuardian::GenerateFunctionHashes(ccc::SymbolDatabase& database, MemoryReader& reader)
|
||||
void SymbolGuardian::GenerateFunctionHashes(ccc::SymbolDatabase& database, MemoryInterface& reader)
|
||||
{
|
||||
for (ccc::Function& function : database.functions)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ void SymbolGuardian::GenerateFunctionHashes(ccc::SymbolDatabase& database, Memor
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolGuardian::UpdateFunctionHashes(ccc::SymbolDatabase& database, MemoryReader& reader)
|
||||
void SymbolGuardian::UpdateFunctionHashes(ccc::SymbolDatabase& database, MemoryInterface& reader)
|
||||
{
|
||||
for (ccc::Function& function : database.functions)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ void SymbolGuardian::UpdateFunctionHashes(ccc::SymbolDatabase& database, MemoryR
|
||||
source_file.check_functions_match(database);
|
||||
}
|
||||
|
||||
std::optional<ccc::FunctionHash> SymbolGuardian::HashFunction(const ccc::Function& function, MemoryReader& reader)
|
||||
std::optional<ccc::FunctionHash> SymbolGuardian::HashFunction(const ccc::Function& function, MemoryInterface& reader)
|
||||
{
|
||||
if (!function.address().valid())
|
||||
return std::nullopt;
|
||||
@@ -195,7 +195,7 @@ std::optional<ccc::FunctionHash> SymbolGuardian::HashFunction(const ccc::Functio
|
||||
for (u32 i = 0; i < function.size() / 4; i++)
|
||||
{
|
||||
bool valid;
|
||||
u32 value = reader.read32(function.address().value + i * 4, valid);
|
||||
u32 value = reader.Read32(function.address().value + i * 4, &valid);
|
||||
if (!valid)
|
||||
return std::nullopt;
|
||||
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include "common/MemoryInterface.h"
|
||||
#include "common/Pcsx2Types.h"
|
||||
|
||||
#include <ccc/ast.h>
|
||||
#include <ccc/symbol_database.h>
|
||||
#include <ccc/symbol_file.h>
|
||||
|
||||
#include "common/Pcsx2Types.h"
|
||||
|
||||
class MemoryReader;
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
|
||||
struct SymbolInfo
|
||||
{
|
||||
@@ -76,14 +75,14 @@ public:
|
||||
|
||||
// Hash all the functions in the database and store the hashes in the
|
||||
// original hash field of said objects.
|
||||
static void GenerateFunctionHashes(ccc::SymbolDatabase& database, MemoryReader& reader);
|
||||
static void GenerateFunctionHashes(ccc::SymbolDatabase& database, MemoryInterface& reader);
|
||||
|
||||
// Hash all the functions in the database that have original hashes and
|
||||
// store the results in the current hash fields of said objects.
|
||||
static void UpdateFunctionHashes(ccc::SymbolDatabase& database, MemoryReader& reader);
|
||||
static void UpdateFunctionHashes(ccc::SymbolDatabase& database, MemoryInterface& reader);
|
||||
|
||||
// Hash a function and return the result.
|
||||
static std::optional<ccc::FunctionHash> HashFunction(const ccc::Function& function, MemoryReader& reader);
|
||||
static std::optional<ccc::FunctionHash> HashFunction(const ccc::Function& function, MemoryInterface& reader);
|
||||
|
||||
// Delete all symbols from modules that have the "is_irx" flag set.
|
||||
void ClearIrxModules();
|
||||
|
||||
Reference in New Issue
Block a user