mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Implement the disassembly mode too
This commit is contained in:
@@ -1092,3 +1092,87 @@ bool DisassemblyComment::disassemble(u32 address, DisassemblyLineInfo &dest, boo
|
||||
dest.totalSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData, bool displaySymbols) {
|
||||
if (displaySymbols) {
|
||||
const std::string addressSymbol = g_symbolMap->GetLabelString(address);
|
||||
if (!addressSymbol.empty()) {
|
||||
for (int k = 0; addressSymbol[k] != 0; k++) {
|
||||
// abbreviate long names
|
||||
if (abbreviateLabels && k == 16 && addressSymbol[k+1] != 0) {
|
||||
*dest++ = '+';
|
||||
break;
|
||||
}
|
||||
*dest++ = addressSymbol[k];
|
||||
}
|
||||
*dest++ = ':';
|
||||
*dest = 0;
|
||||
return true;
|
||||
} else {
|
||||
sprintf(dest," %08X",address);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (showData) {
|
||||
u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0;
|
||||
sprintf(dest, "%08X %08X", address, encoding);
|
||||
} else {
|
||||
sprintf(dest, "%08X", address);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Utilify function from the old debugger.
|
||||
std::string DisassembleRange(u32 start, u32 size, bool displaySymbols, MIPSDebugInterface *debugger) {
|
||||
auto memLock = Memory::Lock();
|
||||
std::string result;
|
||||
|
||||
// gather all branch targets without labels
|
||||
std::set<u32> branchAddresses;
|
||||
for (u32 i = 0; i < size; i += debugger->getInstructionSize(0)) {
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger, start + i);
|
||||
|
||||
if (info.isBranch && g_symbolMap->GetLabelString(info.branchTarget).empty()) {
|
||||
if (branchAddresses.find(info.branchTarget) == branchAddresses.end()) {
|
||||
branchAddresses.insert(info.branchTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 disAddress = start;
|
||||
bool previousLabel = true;
|
||||
DisassemblyLineInfo line;
|
||||
while (disAddress < start + size) {
|
||||
char addressText[64], buffer[512];
|
||||
|
||||
g_disassemblyManager.getLine(disAddress, displaySymbols, line, debugger);
|
||||
bool isLabel = GetDisasmAddressText(disAddress, addressText, false, line.type == DISTYPE_OPCODE, displaySymbols);
|
||||
|
||||
if (isLabel) {
|
||||
if (!previousLabel)
|
||||
result += "\r\n";
|
||||
sprintf(buffer, "%s\r\n\r\n", addressText);
|
||||
result += buffer;
|
||||
} else if (branchAddresses.find(disAddress) != branchAddresses.end()) {
|
||||
if (!previousLabel)
|
||||
result += "\r\n";
|
||||
sprintf(buffer, "pos_%08X:\r\n\r\n", disAddress);
|
||||
result += buffer;
|
||||
}
|
||||
|
||||
if (line.info.isBranch && !line.info.isBranchToRegister
|
||||
&& g_symbolMap->GetLabelString(line.info.branchTarget).empty()
|
||||
&& branchAddresses.find(line.info.branchTarget) != branchAddresses.end()) {
|
||||
sprintf(buffer, "pos_%08X", line.info.branchTarget);
|
||||
line.params = line.params.substr(0, line.params.find("0x")) + buffer;
|
||||
}
|
||||
|
||||
sprintf(buffer, "\t%s\t%s\r\n", line.name.c_str(), line.params.c_str());
|
||||
result += buffer;
|
||||
previousLabel = isLabel;
|
||||
disAddress += line.totalSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -226,3 +226,6 @@ extern DisassemblyManager g_disassemblyManager;
|
||||
|
||||
bool isInInterval(u32 start, u32 size, u32 value);
|
||||
bool IsLikelyStringAt(uint32_t addr);
|
||||
|
||||
std::string DisassembleRange(u32 start, u32 size, bool displaySymbols, MIPSDebugInterface *debugger);
|
||||
bool GetDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData, bool displaySymbols);
|
||||
|
||||
@@ -58,7 +58,7 @@ void ShowInMemoryViewerMenuItem(uint32_t addr, ImControl &control) {
|
||||
|
||||
void ShowInMemoryDumperMenuItem(uint32_t addr, uint32_t size, MemDumpMode mode, ImControl &control) {
|
||||
if (ImGui::MenuItem(mode == MemDumpMode::Raw ? "Dump bytes to file..." : "Disassemble to file...")) {
|
||||
control.command = { ImCmd::SHOW_IN_MEMORY_DUMPER, addr, size };
|
||||
control.command = { ImCmd::SHOW_IN_MEMORY_DUMPER, addr, size, (u32)mode};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1261,7 +1261,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
|
||||
}
|
||||
|
||||
if (cfg_.memDumpOpen) {
|
||||
memDumpWindow_.Draw(cfg_);
|
||||
memDumpWindow_.Draw(cfg_, mipsDebug);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -1302,7 +1302,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
|
||||
case ImCmd::SHOW_IN_MEMORY_DUMPER:
|
||||
{
|
||||
cfg_.memDumpOpen = true;
|
||||
memDumpWindow_.SetRange(control.command.param, control.command.param2);
|
||||
memDumpWindow_.SetRange(control.command.param, control.command.param2, (MemDumpMode)control.command.param3);
|
||||
ImGui::SetWindowFocus(memDumpWindow_.Title());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -53,33 +53,7 @@ bool ImDisasmView::getDisasmAddressText(u32 address, char* dest, bool abbreviate
|
||||
if (!PSP_IsInited())
|
||||
return false;
|
||||
|
||||
if (displaySymbols_) {
|
||||
const std::string addressSymbol = g_symbolMap->GetLabelString(address);
|
||||
if (!addressSymbol.empty()) {
|
||||
for (int k = 0; addressSymbol[k] != 0; k++) {
|
||||
// abbreviate long names
|
||||
if (abbreviateLabels && k == 16 && addressSymbol[k + 1] != 0) {
|
||||
*dest++ = '+';
|
||||
break;
|
||||
}
|
||||
*dest++ = addressSymbol[k];
|
||||
}
|
||||
*dest++ = ':';
|
||||
*dest = 0;
|
||||
return true;
|
||||
} else {
|
||||
sprintf(dest, " %08X", address);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (showData) {
|
||||
u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0;
|
||||
sprintf(dest, "%08X %08X", address, encoding);
|
||||
} else {
|
||||
sprintf(dest, "%08X", address);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return GetDisasmAddressText(address, dest, abbreviateLabels, showData, displaySymbols_);
|
||||
}
|
||||
|
||||
void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) {
|
||||
|
||||
@@ -841,7 +841,7 @@ void ImMemView::setHighlightType(MemBlockFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
void ImMemDumpWindow::Draw(ImConfig &cfg) {
|
||||
void ImMemDumpWindow::Draw(ImConfig &cfg, MIPSDebugInterface *debug) {
|
||||
ImGui::SetNextWindowSize(ImVec2(200, 300), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin(Title(), &cfg.memDumpOpen)) {
|
||||
@@ -854,12 +854,19 @@ void ImMemDumpWindow::Draw(ImConfig &cfg) {
|
||||
size_ = 0x01800000; // 24MB
|
||||
}
|
||||
|
||||
ImGui::InputScalar("Starting address: ", ImGuiDataType_U32, &address_, NULL, NULL, "%08X");
|
||||
ImGui::InputScalar("Size: ", ImGuiDataType_U32, &size_, NULL, NULL, "%08X");
|
||||
ImGui::InputScalar("Starting address", ImGuiDataType_U32, &address_, NULL, NULL, "%08X");
|
||||
ImGui::InputScalar("Size", ImGuiDataType_U32, &size_, NULL, NULL, "%08X");
|
||||
|
||||
ImGui::InputText("Filename: ", filename_, ARRAY_SIZE(filename_));
|
||||
ImGui::InputText("Filename", filename_, ARRAY_SIZE(filename_));
|
||||
|
||||
if (ImGui::Button("Dump!")) {
|
||||
const char* modes[] = { "Raw", "Disassembly" };
|
||||
int modeIndex = static_cast<int>(mode_);
|
||||
if (ImGui::Combo("Memory Dump Mode", &modeIndex, modes, IM_ARRAYSIZE(modes))) {
|
||||
// Update the current mode if the user selects a new one
|
||||
mode_ = static_cast<MemDumpMode>(modeIndex);
|
||||
}
|
||||
|
||||
if (ImGui::Button(mode_ == MemDumpMode::Raw ? "Dump to file" : "Disassemble to file")) {
|
||||
uint32_t validSize = Memory::ValidSize(address_, size_);
|
||||
if (validSize != size_) {
|
||||
errorMsg_ = "Address range out of bounds";
|
||||
@@ -873,10 +880,15 @@ void ImMemDumpWindow::Draw(ImConfig &cfg) {
|
||||
if (!file) {
|
||||
errorMsg_ = "Couldn't open file for writing";
|
||||
} else {
|
||||
const uint8_t *ptr = Memory::GetPointer(address_);
|
||||
fwrite(ptr, 1, size_, file);
|
||||
fclose(file);
|
||||
if (mode_ == MemDumpMode::Raw) {
|
||||
const uint8_t *ptr = Memory::GetPointer(address_);
|
||||
fwrite(ptr, 1, size_, file);
|
||||
} else {
|
||||
std::string disassembly = DisassembleRange(address_, size_, true, debug);
|
||||
fprintf(file, "%s", disassembly.c_str());
|
||||
}
|
||||
errorMsg_.clear();
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,15 +134,17 @@ public:
|
||||
static const char *Title() {
|
||||
return "Memory Dumper";
|
||||
}
|
||||
void Draw(ImConfig &cfg);
|
||||
void SetRange(uint32_t addr, uint32_t size) {
|
||||
void Draw(ImConfig &cfg, MIPSDebugInterface *debug);
|
||||
void SetRange(uint32_t addr, uint32_t size, MemDumpMode mode) {
|
||||
address_ = addr;
|
||||
size_ = size;
|
||||
mode_ = mode;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t address_;
|
||||
uint32_t size_;
|
||||
MemDumpMode mode_ = MemDumpMode::Raw;
|
||||
char filename_[1024];
|
||||
std::string errorMsg_;
|
||||
};
|
||||
|
||||
@@ -218,44 +218,6 @@ static COLORREF scaleColor(COLORREF color, float factor)
|
||||
return (color & 0xFF000000) | (b << 16) | (g << 8) | r;
|
||||
}
|
||||
|
||||
bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData)
|
||||
{
|
||||
if (!PSP_IsInited())
|
||||
return false;
|
||||
|
||||
if (displaySymbols)
|
||||
{
|
||||
const std::string addressSymbol = g_symbolMap->GetLabelString(address);
|
||||
if (!addressSymbol.empty())
|
||||
{
|
||||
for (int k = 0; addressSymbol[k] != 0; k++)
|
||||
{
|
||||
// abbreviate long names
|
||||
if (abbreviateLabels && k == 16 && addressSymbol[k+1] != 0)
|
||||
{
|
||||
*dest++ = '+';
|
||||
break;
|
||||
}
|
||||
*dest++ = addressSymbol[k];
|
||||
}
|
||||
*dest++ = ':';
|
||||
*dest = 0;
|
||||
return true;
|
||||
} else {
|
||||
sprintf(dest," %08X",address);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (showData) {
|
||||
u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0;
|
||||
sprintf(dest, "%08X %08X", address, encoding);
|
||||
} else {
|
||||
sprintf(dest, "%08X", address);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string trimString(std::string input)
|
||||
{
|
||||
size_t pos = input.find_first_not_of(" \t");
|
||||
@@ -567,7 +529,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
|
||||
SetTextColor(hdc,textColor);
|
||||
|
||||
char addressText[64];
|
||||
getDisasmAddressText(address,addressText,true,line.type == DISTYPE_OPCODE);
|
||||
GetDisasmAddressText(address,addressText,true,line.type == DISTYPE_OPCODE, displaySymbols);
|
||||
TextOutA(hdc,pixelPositions.addressStart,rowY1+2,addressText,(int)strlen(addressText));
|
||||
|
||||
if (isInInterval(address,line.totalSize,debugger->GetPC()))
|
||||
@@ -935,7 +897,7 @@ void CtrlDisAsmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructio
|
||||
W32Util::CopyTextToClipboard(wnd, temp);
|
||||
delete [] temp;
|
||||
} else {
|
||||
std::string disassembly = disassembleRange(startAddr,endAddr-startAddr);
|
||||
std::string disassembly = DisassembleRange(startAddr,endAddr-startAddr, displaySymbols, debugger);
|
||||
W32Util::CopyTextToClipboard(wnd, disassembly.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1290,7 +1252,7 @@ void CtrlDisAsmView::search(bool continueSearch)
|
||||
g_disassemblyManager.getLine(searchAddress,displaySymbols,lineInfo, debugger);
|
||||
|
||||
char addressText[64];
|
||||
getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE);
|
||||
GetDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE, displaySymbols);
|
||||
|
||||
const char* opcode = lineInfo.name.c_str();
|
||||
const char* arguments = lineInfo.params.c_str();
|
||||
@@ -1330,65 +1292,6 @@ void CtrlDisAsmView::search(bool continueSearch)
|
||||
searching = false;
|
||||
}
|
||||
|
||||
std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size)
|
||||
{
|
||||
auto memLock = Memory::Lock();
|
||||
std::string result;
|
||||
|
||||
// gather all branch targets without labels
|
||||
std::set<u32> branchAddresses;
|
||||
for (u32 i = 0; i < size; i += debugger->getInstructionSize(0))
|
||||
{
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,start+i);
|
||||
|
||||
if (info.isBranch && g_symbolMap->GetLabelString(info.branchTarget).empty())
|
||||
{
|
||||
if (branchAddresses.find(info.branchTarget) == branchAddresses.end())
|
||||
{
|
||||
branchAddresses.insert(info.branchTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 disAddress = start;
|
||||
bool previousLabel = true;
|
||||
DisassemblyLineInfo line;
|
||||
while (disAddress < start+size)
|
||||
{
|
||||
char addressText[64],buffer[512];
|
||||
|
||||
g_disassemblyManager.getLine(disAddress,displaySymbols,line, debugger);
|
||||
bool isLabel = getDisasmAddressText(disAddress,addressText,false,line.type == DISTYPE_OPCODE);
|
||||
|
||||
if (isLabel)
|
||||
{
|
||||
if (!previousLabel) result += "\r\n";
|
||||
sprintf(buffer,"%s\r\n\r\n",addressText);
|
||||
result += buffer;
|
||||
} else if (branchAddresses.find(disAddress) != branchAddresses.end())
|
||||
{
|
||||
if (!previousLabel) result += "\r\n";
|
||||
sprintf(buffer,"pos_%08X:\r\n\r\n",disAddress);
|
||||
result += buffer;
|
||||
}
|
||||
|
||||
if (line.info.isBranch && !line.info.isBranchToRegister
|
||||
&& g_symbolMap->GetLabelString(line.info.branchTarget).empty()
|
||||
&& branchAddresses.find(line.info.branchTarget) != branchAddresses.end())
|
||||
{
|
||||
sprintf(buffer,"pos_%08X",line.info.branchTarget);
|
||||
line.params = line.params.substr(0,line.params.find("0x")) + buffer;
|
||||
}
|
||||
|
||||
sprintf(buffer,"\t%s\t%s\r\n",line.name.c_str(),line.params.c_str());
|
||||
result += buffer;
|
||||
previousLabel = isLabel;
|
||||
disAddress += line.totalSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CtrlDisAsmView::disassembleToFile() {
|
||||
// get size
|
||||
u32 size;
|
||||
@@ -1408,7 +1311,7 @@ void CtrlDisAsmView::disassembleToFile() {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string disassembly = disassembleRange(curAddress, size);
|
||||
std::string disassembly = DisassembleRange(curAddress, size, displaySymbols, debugger);
|
||||
fprintf(output, "%s", disassembly.c_str());
|
||||
|
||||
fclose(output);
|
||||
|
||||
@@ -70,12 +70,10 @@ class CtrlDisAsmView
|
||||
};
|
||||
|
||||
void assembleOpcode(u32 address, const std::string &defaultText);
|
||||
std::string disassembleRange(u32 start, u32 size);
|
||||
void disassembleToFile();
|
||||
void search(bool continueSearch);
|
||||
void followBranch();
|
||||
void calculatePixelPositions();
|
||||
bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData);
|
||||
void updateStatusBarText();
|
||||
void drawBranchLine(HDC hdc, std::map<u32, int> &addressPositions, const BranchLine &line);
|
||||
void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode);
|
||||
|
||||
Reference in New Issue
Block a user