debugger: Add logging breakpoint + misc fixes (#927)

This commit is contained in:
Crementif 2023-08-03 06:45:11 -07:00 committed by GitHub
parent 1d1e1e781b
commit 651e5336b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 193 additions and 132 deletions

View file

@ -11,9 +11,11 @@
enum
{
MENU_ID_CREATE_MEM_BP_READ = 1,
MENU_ID_CREATE_CODE_BP_EXECUTION = 1,
MENU_ID_CREATE_CODE_BP_LOGGING,
MENU_ID_CREATE_MEM_BP_READ,
MENU_ID_CREATE_MEM_BP_WRITE,
MENU_ID_DELETE_BP,
};
enum ItemColumns
@ -118,6 +120,8 @@ void BreakpointWindow::OnUpdateView()
const char* typeName = "UKN";
if (bp->bpType == DEBUGGER_BP_T_NORMAL)
typeName = "X";
else if (bp->bpType == DEBUGGER_BP_T_LOGGING)
typeName = "LOG";
else if (bp->bpType == DEBUGGER_BP_T_ONE_SHOT)
typeName = "XS";
else if (bp->bpType == DEBUGGER_BP_T_MEMORY_READ)
@ -211,31 +215,56 @@ void BreakpointWindow::OnLeftDClick(wxMouseEvent& event)
void BreakpointWindow::OnRightDown(wxMouseEvent& event)
{
wxMenu menu;
const auto position = event.GetPosition();
const sint32 index = (position.y / m_breakpoints->GetCharHeight()) - 2;
if (index < 0 || index >= m_breakpoints->GetItemCount())
{
wxMenu menu;
menu.Append(MENU_ID_CREATE_CODE_BP_EXECUTION, _("Create execution breakpoint"));
menu.Append(MENU_ID_CREATE_CODE_BP_LOGGING, _("Create logging breakpoint"));
menu.Append(MENU_ID_CREATE_MEM_BP_READ, _("Create memory breakpoint (read)"));
menu.Append(MENU_ID_CREATE_MEM_BP_WRITE, _("Create memory breakpoint (write)"));
menu.Append(MENU_ID_CREATE_MEM_BP_READ, _("Create memory breakpoint (read)"));
menu.Append(MENU_ID_CREATE_MEM_BP_WRITE, _("Create memory breakpoint (write)"));
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BreakpointWindow::OnContextMenuClick), nullptr, this);
PopupMenu(&menu);
}
else
{
m_breakpoints->SetItemState(index, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED);
m_breakpoints->SetItemState(index, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BreakpointWindow::OnContextMenuClick), nullptr, this);
PopupMenu(&menu);
wxMenu menu;
menu.Append(MENU_ID_DELETE_BP, _("Delete breakpoint"));
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BreakpointWindow::OnContextMenuClickSelected), nullptr, this);
PopupMenu(&menu);
}
}
void BreakpointWindow::OnContextMenuClickSelected(wxCommandEvent& evt)
{
if (evt.GetId() == MENU_ID_DELETE_BP)
{
long sel = m_breakpoints->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (sel != -1)
{
if (sel >= debuggerState.breakpoints.size())
return;
auto it = debuggerState.breakpoints.begin();
std::advance(it, sel);
debugger_deleteBreakpoint(*it);
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE);
wxPostEvent(this->m_parent, evt);
}
}
}
void BreakpointWindow::OnContextMenuClick(wxCommandEvent& evt)
{
switch (evt.GetId())
{
case MENU_ID_CREATE_MEM_BP_READ:
MemoryBreakpointDialog(false);
return;
case MENU_ID_CREATE_MEM_BP_WRITE:
MemoryBreakpointDialog(true);
return;
}
}
void BreakpointWindow::MemoryBreakpointDialog(bool isWrite)
{
wxTextEntryDialog goto_dialog(this, _("Enter a memory address"), _("Memory breakpoint"), wxEmptyString);
wxTextEntryDialog goto_dialog(this, _("Enter a memory address"), _("Set breakpoint"), wxEmptyString);
if (goto_dialog.ShowModal() == wxID_OK)
{
ExpressionParser parser;
@ -243,22 +272,34 @@ void BreakpointWindow::MemoryBreakpointDialog(bool isWrite)
auto value = goto_dialog.GetValue().ToStdString();
std::transform(value.begin(), value.end(), value.begin(), tolower);
uint32_t newBreakpointAddress = 0;
try
{
debugger_addParserSymbols(parser);
const auto result = (uint32)parser.Evaluate(value);
debug_printf("goto eval result: %x\n", result);
debugger_createMemoryBreakpoint(result, isWrite == false, isWrite == true);
this->OnUpdateView();
newBreakpointAddress = parser.IsConstantExpression("0x"+value) ? (uint32)parser.Evaluate("0x"+value) : (uint32)parser.Evaluate(value);
}
catch (const std::exception& e)
catch (const std::exception& ex)
{
//ctx.errorHandler.printError(nullptr, -1, fmt::format("Unexpected error in expression \"{}\"", expressionString));
//return EXPRESSION_RESOLVE_RESULT::EXPRESSION_ERROR;
wxMessageBox(e.what(), "Invalid expression");
wxMessageBox(ex.what(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
return;
}
switch (evt.GetId())
{
case MENU_ID_CREATE_CODE_BP_EXECUTION:
debugger_createCodeBreakpoint(newBreakpointAddress, DEBUGGER_BP_T_NORMAL);
break;
case MENU_ID_CREATE_CODE_BP_LOGGING:
debugger_createCodeBreakpoint(newBreakpointAddress, DEBUGGER_BP_T_LOGGING);
break;
case MENU_ID_CREATE_MEM_BP_READ:
debugger_createMemoryBreakpoint(newBreakpointAddress, true, false);
break;
case MENU_ID_CREATE_MEM_BP_WRITE:
debugger_createMemoryBreakpoint(newBreakpointAddress, false, true);
break;
}
this->OnUpdateView();
}
}
}

View file

@ -19,8 +19,7 @@ private:
void OnRightDown(wxMouseEvent& event);
void OnContextMenuClick(wxCommandEvent& evt);
void MemoryBreakpointDialog(bool isWrite);
void OnContextMenuClickSelected(wxCommandEvent& evt);
wxCheckedListCtrl* m_breakpoints;
};

View file

@ -118,7 +118,7 @@ void DebuggerModuleStorage::Load(XMLConfigParser& parser)
const auto comment = element.get("Comment", "");
// calculate absolute address
uint32 module_base_address = (type == DEBUGGER_BP_T_NORMAL ? this->rpl_module->regionMappingBase_text.GetMPTR() : this->rpl_module->regionMappingBase_data);
uint32 module_base_address = (type == DEBUGGER_BP_T_NORMAL || type == DEBUGGER_BP_T_LOGGING) ? this->rpl_module->regionMappingBase_text.GetMPTR() : this->rpl_module->regionMappingBase_data;
uint32 address = module_base_address + relative_address;
// don't change anything if there's already a breakpoint
@ -127,7 +127,9 @@ void DebuggerModuleStorage::Load(XMLConfigParser& parser)
// register breakpoints in debugger
if (type == DEBUGGER_BP_T_NORMAL)
debugger_createExecuteBreakpoint(address);
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_NORMAL);
else if (type == DEBUGGER_BP_T_LOGGING)
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_LOGGING);
else if (type == DEBUGGER_BP_T_MEMORY_READ)
debugger_createMemoryBreakpoint(address, true, false);
else if (type == DEBUGGER_BP_T_MEMORY_WRITE)
@ -173,7 +175,7 @@ void DebuggerModuleStorage::Save(XMLConfigParser& parser)
// check whether the breakpoint is part of the current module being saved
RPLModule* address_module;
if (bp->bpType == DEBUGGER_BP_T_NORMAL) address_module = RPLLoader_FindModuleByCodeAddr(bp->address);
if (bp->bpType == DEBUGGER_BP_T_NORMAL || bp->bpType == DEBUGGER_BP_T_LOGGING) address_module = RPLLoader_FindModuleByCodeAddr(bp->address);
else if (bp->isMemBP()) address_module = RPLLoader_FindModuleByDataAddr(bp->address);
else continue;
@ -259,7 +261,7 @@ void DebuggerWindow2::LoadModuleStorage(const RPLModule* module)
bool already_loaded = std::any_of(m_modules_storage.begin(), m_modules_storage.end(), [path](const std::unique_ptr<XMLDebuggerModuleConfig>& debug) { return debug->GetFilename() == path; });
if (!path.empty() && !already_loaded)
{
m_modules_storage.emplace_back(std::move(new XMLDebuggerModuleConfig(path, { module->moduleName2, module->patchCRC, module, false })));
m_modules_storage.emplace_back(new XMLDebuggerModuleConfig(path, { module->moduleName2, module->patchCRC, module, false }))->Load();
}
}
@ -522,6 +524,7 @@ void DebuggerWindow2::OnToolClicked(wxCommandEvent& event)
void DebuggerWindow2::OnBreakpointChange(wxCommandEvent& event)
{
m_breakpoint_window->OnUpdateView();
m_disasm_ctrl->RefreshControl();
UpdateModuleLabel();
}

View file

@ -147,7 +147,7 @@ void DisasmCtrl::DrawDisassemblyLine(wxDC& dc, const wxPoint& linePosition, MPTR
else if (is_active_bp)
background_colour = wxColour(0xFF80A0FF);
else if (bp != nullptr)
background_colour = wxColour(0xFF8080FF);
background_colour = wxColour(bp->bpType == DEBUGGER_BP_T_NORMAL ? 0xFF8080FF : 0x80FFFFFF);
else if(virtualAddress == m_lastGotoTarget)
background_colour = wxColour(0xFFE0E0E0);
else
@ -540,8 +540,6 @@ void DisasmCtrl::OnKeyPressed(sint32 key_code, const wxPoint& position)
{
debugger_toggleExecuteBreakpoint(*optVirtualAddress);
RefreshControl();
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE);
wxPostEvent(this->m_parent, evt);
}
@ -767,40 +765,31 @@ void DisasmCtrl::GoToAddressDialog()
auto value = goto_dialog.GetValue().ToStdString();
std::transform(value.begin(), value.end(), value.begin(), tolower);
const auto module_count = RPLLoader_GetModuleCount();
const auto module_list = RPLLoader_GetModuleList();
debugger_addParserSymbols(parser);
std::vector<double> module_tmp(module_count);
for (int i = 0; i < module_count; i++)
// try to parse expression as hex value first (it should interpret 1234 as 0x1234, not 1234)
if (parser.IsConstantExpression("0x"+value))
{
const auto module = module_list[i];
if (module)
{
module_tmp[i] = (double)module->regionMappingBase_text.GetMPTR();
parser.AddConstant(module->moduleName2, module_tmp[i]);
}
}
double grp_tmp[32];
PPCSnapshot& ppc_snapshot = debuggerState.debugSession.ppcSnapshot;
for (int i = 0; i < 32; i++)
{
char var_name[32];
sprintf(var_name, "r%d", i);
grp_tmp[i] = ppc_snapshot.gpr[i];
parser.AddConstant(var_name, grp_tmp[i]);
}
try
{
const auto result = (uint32)parser.Evaluate(value);
debug_printf("goto eval result: %x\n", result);
const auto result = (uint32)parser.Evaluate("0x"+value);
m_lastGotoTarget = result;
CenterOffset(result);
debuggerWindow_updateViewThreadsafe2();
}
catch (const std::exception& )
else if (parser.IsConstantExpression(value))
{
const auto result = (uint32)parser.Evaluate(value);
m_lastGotoTarget = result;
CenterOffset(result);
}
else
{
try
{
const auto _ = (uint32)parser.Evaluate(value);
}
catch (const std::exception& ex)
{
wxMessageBox(ex.what(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
}
}
}
}

View file

@ -214,46 +214,36 @@ void DumpCtrl::GoToAddressDialog()
wxTextEntryDialog goto_dialog(this, _("Enter a target address."), _("GoTo address"), wxEmptyString);
if (goto_dialog.ShowModal() == wxID_OK)
{
try
ExpressionParser parser;
auto value = goto_dialog.GetValue().ToStdString();
std::transform(value.begin(), value.end(), value.begin(), tolower);
debugger_addParserSymbols(parser);
// try to parse expression as hex value first (it should interpret 1234 as 0x1234, not 1234)
if (parser.IsConstantExpression("0x"+value))
{
ExpressionParser parser;
auto value = goto_dialog.GetValue().ToStdString();
std::transform(value.begin(), value.end(), value.begin(), tolower);
//parser.SetExpr(value);
const auto module_count = RPLLoader_GetModuleCount();
const auto module_list = RPLLoader_GetModuleList();
std::vector<double> module_tmp(module_count);
for (int i = 0; i < module_count; i++)
{
const auto module = module_list[i];
if (module)
{
module_tmp[i] = (double)module->regionMappingBase_text.GetMPTR();
parser.AddConstant(module->moduleName2, module_tmp[i]);
}
}
double grp_tmp[32];
PPCSnapshot& ppc_snapshot = debuggerState.debugSession.ppcSnapshot;
for (int i = 0; i < 32; i++)
{
char var_name[32];
sprintf(var_name, "r%d", i);
grp_tmp[i] = ppc_snapshot.gpr[i];
parser.AddConstant(var_name, grp_tmp[i]);
}
const auto result = (uint32)parser.Evaluate(value);
debug_printf("goto eval result: %x\n", result);
const auto result = (uint32)parser.Evaluate("0x"+value);
m_lastGotoOffset = result;
CenterOffset(result);
}
catch (const std::exception& ex)
else if (parser.IsConstantExpression(value))
{
wxMessageBox(ex.what(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
const auto result = (uint32)parser.Evaluate(value);
m_lastGotoOffset = result;
CenterOffset(result);
}
else
{
try
{
const auto _ = (uint32)parser.Evaluate(value);
}
catch (const std::exception& ex)
{
wxMessageBox(ex.what(), _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
}
}
}
}