Skip to content

Commit

Permalink
Debugger: Added right click context menu to disasm view + small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Exzap committed Dec 16, 2024
1 parent adab729 commit 6aaad1e
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 20 deletions.
28 changes: 28 additions & 0 deletions src/Cafe/HW/Espresso/Debugger/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,34 @@ bool debugger_hasPatch(uint32 address)
return false;
}

void debugger_removePatch(uint32 address)
{
for (sint32 i = 0; i < debuggerState.patches.size(); i++)
{
auto& patch = debuggerState.patches[i];
if (address < patch->address || address >= (patch->address + patch->length))
continue;
MPTR startAddress = patch->address;
MPTR endAddress = patch->address + patch->length;
// remove any breakpoints overlapping with the patch
for (auto& bp : debuggerState.breakpoints)
{
if (bp->address + 4 > startAddress && bp->address < endAddress)
{
bp->enabled = false;
debugger_updateExecutionBreakpoint(bp->address);
}
}
// restore original data
memcpy(MEMPTR<void>(startAddress).GetPtr(), patch->origData.data(), patch->length);
PPCRecompiler_invalidateRange(startAddress, endAddress);
// remove patch
delete patch;
debuggerState.patches.erase(debuggerState.patches.begin() + i);
return;
}
}

void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
{
bool isRecEnabled = ppcRecompilerEnabled;
Expand Down
1 change: 1 addition & 0 deletions src/Cafe/HW/Espresso/Debugger/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void debugger_updateExecutionBreakpoint(uint32 address, bool forceRestore = fals

void debugger_createPatch(uint32 address, std::span<uint8> patchData);
bool debugger_hasPatch(uint32 address);
void debugger_removePatch(uint32 address);

void debugger_forceBreak(); // force breakpoint at the next possible instruction
bool debugger_isTrapped();
Expand Down
11 changes: 9 additions & 2 deletions src/gui/debugger/DebuggerWindow2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ wxBEGIN_EVENT_TABLE(DebuggerWindow2, wxFrame)
EVT_COMMAND(wxID_ANY, wxEVT_RUN, DebuggerWindow2::OnRunProgram)
EVT_COMMAND(wxID_ANY, wxEVT_NOTIFY_MODULE_LOADED, DebuggerWindow2::OnNotifyModuleLoaded)
EVT_COMMAND(wxID_ANY, wxEVT_NOTIFY_MODULE_UNLOADED, DebuggerWindow2::OnNotifyModuleUnloaded)
EVT_COMMAND(wxID_ANY, wxEVT_DISASMCTRL_NOTIFY_GOTO_ADDRESS, DebuggerWindow2::OnDisasmCtrlGotoAddress)
// file menu
EVT_MENU(MENU_ID_FILE_EXIT, DebuggerWindow2::OnExit)
// window
Expand Down Expand Up @@ -383,6 +384,12 @@ void DebuggerWindow2::OnMoveIP(wxCommandEvent& event)
m_disasm_ctrl->CenterOffset(ip);
}

void DebuggerWindow2::OnDisasmCtrlGotoAddress(wxCommandEvent& event)
{
uint32 address = static_cast<uint32>(event.GetExtraLong());
UpdateModuleLabel(address);
}

void DebuggerWindow2::OnParentMove(const wxPoint& main_position, const wxSize& main_size)
{
m_main_position = main_position;
Expand Down Expand Up @@ -416,7 +423,7 @@ void DebuggerWindow2::OnNotifyModuleLoaded(wxCommandEvent& event)

void DebuggerWindow2::OnNotifyModuleUnloaded(wxCommandEvent& event)
{
RPLModule* module = (RPLModule*)event.GetClientData();
RPLModule* module = (RPLModule*)event.GetClientData(); // todo - the RPL module is already unloaded at this point. Find a better way to handle this
SaveModuleStorage(module, true);
m_module_window->OnGameLoaded();
m_symbol_window->OnGameLoaded();
Expand Down Expand Up @@ -659,7 +666,7 @@ void DebuggerWindow2::CreateMenuBar()

void DebuggerWindow2::UpdateModuleLabel(uint32 address)
{
if(address == 0)
if (address == 0)
address = m_disasm_ctrl->GetViewBaseAddress();

RPLModule* module = RPLLoader_FindModuleByCodeAddr(address);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/debugger/DebuggerWindow2.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class DebuggerWindow2 : public wxFrame
void OnMoveIP(wxCommandEvent& event);
void OnNotifyModuleLoaded(wxCommandEvent& event);
void OnNotifyModuleUnloaded(wxCommandEvent& event);
// events from DisasmCtrl
void OnDisasmCtrlGotoAddress(wxCommandEvent& event);

void CreateMenuBar();
void UpdateModuleLabel(uint32 address = 0);
Expand Down
86 changes: 68 additions & 18 deletions src/gui/debugger/DisasmCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "Cafe/HW/Espresso/Debugger/DebugSymbolStorage.h"
#include <wx/mstream.h> // for wxMemoryInputStream

wxDEFINE_EVENT(wxEVT_DISASMCTRL_NOTIFY_GOTO_ADDRESS, wxCommandEvent);

#define MAX_SYMBOL_LEN (120)

#define COLOR_DEBUG_ACTIVE_BP 0xFFFFA0FF
Expand Down Expand Up @@ -74,6 +76,8 @@ DisasmCtrl::DisasmCtrl(wxWindow* parent, const wxWindowID& id, const wxPoint& po
auto tooltip_sizer = new wxBoxSizer(wxVERTICAL);
tooltip_sizer->Add(new wxStaticText(m_tooltip_window, wxID_ANY, wxEmptyString), 0, wxALL, 5);
m_tooltip_window->SetSizer(tooltip_sizer);

Bind(wxEVT_MENU, &DisasmCtrl::OnContextMenuEntryClicked, this, IDContextMenu_ToggleBreakpoint, IDContextMenu_Last);
}

void DisasmCtrl::Init()
Expand Down Expand Up @@ -662,29 +666,67 @@ void DisasmCtrl::CopyToClipboard(std::string text) {
#endif
}

static uint32 GetUnrelocatedAddress(MPTR address)
{
RPLModule* rplModule = RPLLoader_FindModuleByCodeAddr(address);
if (!rplModule)
return 0;
if (address >= rplModule->regionMappingBase_text.GetMPTR() && address < (rplModule->regionMappingBase_text.GetMPTR() + rplModule->regionSize_text))
return 0x02000000 + (address - rplModule->regionMappingBase_text.GetMPTR());
return 0;
}

void DisasmCtrl::OnContextMenu(const wxPoint& position, uint32 line)
{
wxPoint pos = position;
auto optVirtualAddress = LinePixelPosToAddress(position.y - GetViewStart().y * m_line_height);
if (!optVirtualAddress)
return;
MPTR virtualAddress = *optVirtualAddress;
m_contextMenuAddress = virtualAddress;
// show dialog
wxMenu menu;
menu.Append(IDContextMenu_ToggleBreakpoint, _("Toggle breakpoint"));
if(debugger_hasPatch(virtualAddress))
menu.Append(IDContextMenu_RestoreOriginalInstructions, _("Restore original instructions"));
menu.AppendSeparator();
menu.Append(IDContextMenu_CopyAddress, _("Copy address"));
uint32 unrelocatedAddress = GetUnrelocatedAddress(virtualAddress);
if (unrelocatedAddress && unrelocatedAddress != virtualAddress)
menu.Append(IDContextMenu_CopyUnrelocatedAddress, _("Copy virtual address (for IDA/Ghidra)"));
PopupMenu(&menu);
}

// address
if (pos.x <= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE)
{
CopyToClipboard(fmt::format("{:#10x}", virtualAddress));
return;
}
else if (pos.x <= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE + OFFSET_DISASSEMBLY)
{
// double-clicked on disassembly (operation and operand data)
return;
}
else
void DisasmCtrl::OnContextMenuEntryClicked(wxCommandEvent& event)
{
switch(event.GetId())
{
// comment
return;
case IDContextMenu_ToggleBreakpoint:
{
debugger_toggleExecuteBreakpoint(m_contextMenuAddress);
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE);
wxPostEvent(this->m_parent, evt);
break;
}
case IDContextMenu_RestoreOriginalInstructions:
{
debugger_removePatch(m_contextMenuAddress);
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE); // This also refreshes the disassembly view
wxPostEvent(this->m_parent, evt);
break;
}
case IDContextMenu_CopyAddress:
{
CopyToClipboard(fmt::format("{:#10x}", m_contextMenuAddress));
break;
}
case IDContextMenu_CopyUnrelocatedAddress:
{
uint32 unrelocatedAddress = GetUnrelocatedAddress(m_contextMenuAddress);
CopyToClipboard(fmt::format("{:#10x}", unrelocatedAddress));
break;
}
default:
UNREACHABLE;
}
}

Expand Down Expand Up @@ -722,7 +764,6 @@ std::optional<MPTR> DisasmCtrl::LinePixelPosToAddress(sint32 posY)
if (posY < 0)
return std::nullopt;


sint32 lineIndex = posY / m_line_height;
if (lineIndex >= m_lineToAddress.size())
return std::nullopt;
Expand Down Expand Up @@ -751,8 +792,6 @@ void DisasmCtrl::CenterOffset(uint32 offset)

m_active_line = line;
RefreshLine(m_active_line);

debug_printf("scroll to %x\n", debuggerState.debugSession.instructionPointer);
}

void DisasmCtrl::GoToAddressDialog()
Expand All @@ -765,6 +804,10 @@ void DisasmCtrl::GoToAddressDialog()
auto value = goto_dialog.GetValue().ToStdString();
std::transform(value.begin(), value.end(), value.begin(), tolower);

// trim any leading spaces
while(!value.empty() && value[0] == ' ')
value.erase(value.begin());

debugger_addParserSymbols(parser);

// try to parse expression as hex value first (it should interpret 1234 as 0x1234, not 1234)
Expand All @@ -773,17 +816,24 @@ void DisasmCtrl::GoToAddressDialog()
const auto result = (uint32)parser.Evaluate("0x"+value);
m_lastGotoTarget = result;
CenterOffset(result);
wxCommandEvent evt(wxEVT_DISASMCTRL_NOTIFY_GOTO_ADDRESS);
evt.SetExtraLong(static_cast<long>(result));
wxPostEvent(GetParent(), evt);
}
else if (parser.IsConstantExpression(value))
{
const auto result = (uint32)parser.Evaluate(value);
m_lastGotoTarget = result;
CenterOffset(result);
wxCommandEvent evt(wxEVT_DISASMCTRL_NOTIFY_GOTO_ADDRESS);
evt.SetExtraLong(static_cast<long>(result));
wxPostEvent(GetParent(), evt);
}
else
{
try
{
// if not a constant expression (i.e. relying on unknown variables), then evaluating will throw an exception with a detailed error message
const auto _ = (uint32)parser.Evaluate(value);
}
catch (const std::exception& ex)
Expand Down
13 changes: 13 additions & 0 deletions src/gui/debugger/DisasmCtrl.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
#pragma once
#include "gui/components/TextList.h"

wxDECLARE_EVENT(wxEVT_DISASMCTRL_NOTIFY_GOTO_ADDRESS, wxCommandEvent); // Notify parent that goto address operation completed. Event contains the address that was jumped to.

class DisasmCtrl : public TextList
{
enum
{
IDContextMenu_ToggleBreakpoint = wxID_HIGHEST + 1,
IDContextMenu_RestoreOriginalInstructions,
IDContextMenu_CopyAddress,
IDContextMenu_CopyUnrelocatedAddress,
IDContextMenu_Last
};
public:

DisasmCtrl(wxWindow* parent, const wxWindowID& id, const wxPoint& pos, const wxSize& size, long style);

void Init();
Expand All @@ -26,6 +37,7 @@ class DisasmCtrl : public TextList
void OnKeyPressed(sint32 key_code, const wxPoint& position) override;
void OnMouseDClick(const wxPoint& position, uint32 line) override;
void OnContextMenu(const wxPoint& position, uint32 line) override;
void OnContextMenuEntryClicked(wxCommandEvent& event);
bool OnShowTooltip(const wxPoint& position, uint32 line) override;
void ScrollWindow(int dx, int dy, const wxRect* prect) override;

Expand All @@ -40,6 +52,7 @@ class DisasmCtrl : public TextList
sint32 m_mouse_line, m_mouse_line_drawn;
sint32 m_active_line;
uint32 m_lastGotoTarget{};
uint32 m_contextMenuAddress{};
// code region info
uint32 currentCodeRegionStart;
uint32 currentCodeRegionEnd;
Expand Down

0 comments on commit 6aaad1e

Please sign in to comment.