From bf293ebbfc59b2f0a652d4d5e42628b76bbf8e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Sat, 21 Sep 2013 02:40:36 +0200 Subject: [PATCH] Debugger improved: Instruction editor added How to use the instruction editor: 1. Load an .ELF file 2. Select an instruction from any valid memory address inside any thread. 3. Press 'E' key and have fun. :P Note1: I suggest to remove the function InterpreterDisAsmFrame::DClick and use InterpreterDisAsmFrame::InstrKey to do all debugging-related actions (Add breakpoint, Edit, Step, Run, etc.) using the same keyboard layout as debuggers like OllyDbg. Note2: The final binary is 200 KB larger due to this feature. This issue should be fixed in the future. This has probably something to do with the #include's. --- rpcs3/Gui/InstructionEditor.cpp | 88 +++++++++++++++++++++++++++++++++ rpcs3/Gui/InstructionEditor.h | 24 +++++++++ rpcs3/Gui/InterpreterDisAsm.cpp | 19 +++++++ rpcs3/Gui/InterpreterDisAsm.h | 1 + rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 ++ 6 files changed, 136 insertions(+) create mode 100644 rpcs3/Gui/InstructionEditor.cpp create mode 100644 rpcs3/Gui/InstructionEditor.h diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp new file mode 100644 index 0000000000..83011e37e7 --- /dev/null +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#include "InstructionEditor.h" + +InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) + : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) + , pc(_pc) + , CPU(_CPU) + , decoder(_decoder) + , disasm(_disasm) +{ + wxBoxSizer* s_panel_margin_x(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_panel_margin_y(new wxBoxSizer(wxVERTICAL)); + + wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_t1_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t2_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t3_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + wxStaticText* t1_text = new wxStaticText(this, wxID_ANY, "Address: "); + wxStaticText* t1_addr = new wxStaticText(this, wxID_ANY, wxString::Format("%08x",pc)); + wxStaticText* t2_text = new wxStaticText(this, wxID_ANY, "Instruction:"); + t2_instr = new wxTextCtrl(this, wxID_ANY); + wxStaticText* t3_text = new wxStaticText(this, wxID_ANY, "Preview: "); + t3_preview = new wxStaticText(this, wxID_ANY, ""); + + s_t1_panel->Add(t1_text); + s_t1_panel->AddSpacer(8); + s_t1_panel->Add(t1_addr); + + s_t2_panel->Add(t2_text); + s_t2_panel->AddSpacer(8); + s_t2_panel->Add(t2_instr); + + s_t3_panel->Add(t3_text); + s_t3_panel->AddSpacer(8); + s_t3_panel->Add(t3_preview); + + s_b_panel->Add(new wxButton(this, wxID_OK), wxLEFT, 0, 5); + s_b_panel->AddSpacer(5); + s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxRIGHT, 0, 5); + + s_panel->Add(s_t1_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t3_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t2_panel); + s_panel->AddSpacer(16); + s_panel->Add(s_b_panel); + + s_panel_margin_y->AddSpacer(12); + s_panel_margin_y->Add(s_panel); + s_panel_margin_y->AddSpacer(12); + s_panel_margin_x->AddSpacer(12); + s_panel_margin_x->Add(s_panel_margin_y); + s_panel_margin_x->AddSpacer(12); + + this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); + t2_instr->SetValue(wxString::Format("%08x", Memory.Read32(pc))); + + this->SetSizerAndFit(s_panel_margin_x); + + if(this->ShowModal() == wxID_OK) + { + unsigned long opcode; + if (!t2_instr->GetValue().ToULong(&opcode, 16)) + wxMessageBox("This instruction could not be parsed.\nNo changes were made.","Error"); + else + Memory.Write32(CPU->GetOffset() + pc, (u32)opcode); + } +} + +void InstructionEditorDialog::updatePreview(wxCommandEvent& event) +{ + unsigned long opcode; + if (t2_instr->GetValue().ToULong(&opcode, 16)) + { + decoder->Decode((u32)opcode); + wxString preview = disasm->last_opcode; + while (preview[0] != ':') preview.Remove(0,1); + preview.Remove(0,1); + t3_preview->SetLabel(preview); + } + else + { + t3_preview->SetLabel("Could not parse instruction."); + } +} \ No newline at end of file diff --git a/rpcs3/Gui/InstructionEditor.h b/rpcs3/Gui/InstructionEditor.h new file mode 100644 index 0000000000..7edb0ef1a8 --- /dev/null +++ b/rpcs3/Gui/InstructionEditor.h @@ -0,0 +1,24 @@ +#pragma once +#include "Emu/Cell/PPCThread.h" +#include "Emu/Cell/PPUDecoder.h" +#include "Emu/Cell/PPUDisAsm.h" +#include "Emu/Cell/SPUDecoder.h" +#include "Emu/Cell/SPUDisAsm.h" + +class InstructionEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxTextCtrl* t2_instr; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updatePreview(wxCommandEvent& event); +}; \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 346a03810c..2475a7f24c 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "InterpreterDisAsm.h" +#include "InstructionEditor.h" //static const int show_lines = 30; @@ -67,6 +68,7 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent) Connect(m_btn_step->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoStep)); Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun)); Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause)); + Connect(m_list->GetId(), wxEVT_COMMAND_LIST_KEY_DOWN, wxListEventHandler(InterpreterDisAsmFrame::InstrKey)); Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick)); Connect(m_choice_units->GetId(),wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(InterpreterDisAsmFrame::OnSelectUnit)); Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); @@ -442,6 +444,23 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) ThreadBase::Start(); } +void InterpreterDisAsmFrame::InstrKey(wxListEvent& event) +{ + long i = m_list->GetFirstSelected(); + if(i < 0) return; + + const u64 start_pc = PC - m_item_count*4; + const u64 pc = start_pc + i*4; + + switch(event.GetKeyCode()) + { + case 'E': + InstructionEditorDialog(this, pc, CPU, decoder, disasm); + DoUpdate(); + return; + } +} + void InterpreterDisAsmFrame::DClick(wxListEvent& event) { long i = m_list->GetFirstSelected(); diff --git a/rpcs3/Gui/InterpreterDisAsm.h b/rpcs3/Gui/InterpreterDisAsm.h index b86db3ab2a..f14068db35 100644 --- a/rpcs3/Gui/InterpreterDisAsm.h +++ b/rpcs3/Gui/InterpreterDisAsm.h @@ -46,6 +46,7 @@ public: void DoRun(wxCommandEvent& event); void DoPause(wxCommandEvent& event); void DoStep(wxCommandEvent& event); + void InstrKey(wxListEvent& event); void DClick(wxListEvent& event); void MouseWheel(wxMouseEvent& event); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 893c671409..0558b5154b 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -265,6 +265,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 1606f87a8a..fd5bf44ddf 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -307,6 +307,9 @@ Emu\SysCalls\lv2 + + Gui +