diff options
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 85 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.h | 28 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.ui | 39 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.cpp | 272 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.h | 76 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.ui | 81 |
6 files changed, 0 insertions, 581 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp deleted file mode 100644 index 08d2e7a22..000000000 --- a/src/citra_qt/debugger/callstack.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <QStandardItemModel> -#include "citra_qt/debugger/callstack.h" -#include "common/common_types.h" -#include "common/symbols.h" -#include "core/arm/arm_interface.h" -#include "core/arm/disassembler/arm_disasm.h" -#include "core/core.h" -#include "core/memory.h" - -CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { - ui.setupUi(this); - - callstack_model = new QStandardItemModel(this); - callstack_model->setColumnCount(4); - callstack_model->setHeaderData(0, Qt::Horizontal, "Stack Pointer"); - callstack_model->setHeaderData(2, Qt::Horizontal, "Return Address"); - callstack_model->setHeaderData(1, Qt::Horizontal, "Call Address"); - callstack_model->setHeaderData(3, Qt::Horizontal, "Function"); - ui.treeView->setModel(callstack_model); -} - -void CallstackWidget::OnDebugModeEntered() { - // Stack pointer - const u32 sp = Core::CPU().GetReg(13); - - Clear(); - - int counter = 0; - for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { - if (!Memory::IsValidVirtualAddress(addr)) - break; - - const u32 ret_addr = Memory::Read32(addr); - const u32 call_addr = ret_addr - 4; // get call address??? - - if (!Memory::IsValidVirtualAddress(call_addr)) - break; - - /* TODO (mattvail) clean me, move to debugger interface */ - u32 insn = Memory::Read32(call_addr); - if (ARM_Disasm::Decode(insn) == OP_BL) { - std::string name; - // ripped from disasm - u32 i_offset = insn & 0xffffff; - // Sign-extend the 24-bit offset - if ((i_offset >> 23) & 1) - i_offset |= 0xff000000; - - // Pre-compute the left-shift and the prefetch offset - i_offset <<= 2; - i_offset += 8; - const u32 func_addr = call_addr + i_offset; - - callstack_model->setItem( - counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); - callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg( - ret_addr, 8, 16, QLatin1Char('0')))); - callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg( - call_addr, 8, 16, QLatin1Char('0')))); - - name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; - callstack_model->setItem( - counter, 3, new QStandardItem( - QString("%1_%2") - .arg(QString::fromStdString(name)) - .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); - - counter++; - } - } -} - -void CallstackWidget::OnDebugModeLeft() {} - -void CallstackWidget::Clear() { - for (int row = 0; row < callstack_model->rowCount(); row++) { - for (int column = 0; column < callstack_model->columnCount(); column++) { - callstack_model->setItem(row, column, new QStandardItem()); - } - } -} diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h deleted file mode 100644 index f04ab9c7e..000000000 --- a/src/citra_qt/debugger/callstack.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <QDockWidget> -#include "ui_callstack.h" - -class QStandardItemModel; - -class CallstackWidget : public QDockWidget { - Q_OBJECT - -public: - explicit CallstackWidget(QWidget* parent = nullptr); - -public slots: - void OnDebugModeEntered(); - void OnDebugModeLeft(); - -private: - Ui::CallStack ui; - QStandardItemModel* callstack_model; - - /// Clears the callstack widget while keeping the column widths the same - void Clear(); -}; diff --git a/src/citra_qt/debugger/callstack.ui b/src/citra_qt/debugger/callstack.ui deleted file mode 100644 index 248ea3dd7..000000000 --- a/src/citra_qt/debugger/callstack.ui +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>CallStack</class> - <widget class="QDockWidget" name="CallStack"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle"> - <string>Call Stack</string> - </property> - <widget class="QWidget" name="dockWidgetContents"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTreeView" name="treeView"> - <property name="editTriggers"> - <set>QAbstractItemView::NoEditTriggers</set> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp deleted file mode 100644 index e9c8ad858..000000000 --- a/src/citra_qt/debugger/disassembler.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <QShortcut> -#include "citra_qt/bootmanager.h" -#include "citra_qt/debugger/disassembler.h" -#include "citra_qt/hotkeys.h" -#include "citra_qt/util/util.h" -#include "common/break_points.h" -#include "common/symbols.h" -#include "core/arm/arm_interface.h" -#include "core/arm/disassembler/arm_disasm.h" -#include "core/core.h" -#include "core/memory.h" - -DisassemblerModel::DisassemblerModel(QObject* parent) - : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), - selection(QModelIndex()) {} - -int DisassemblerModel::columnCount(const QModelIndex& parent) const { - return 3; -} - -int DisassemblerModel::rowCount(const QModelIndex& parent) const { - return code_size; -} - -QVariant DisassemblerModel::data(const QModelIndex& index, int role) const { - switch (role) { - case Qt::DisplayRole: { - u32 address = base_address + index.row() * 4; - u32 instr = Memory::Read32(address); - std::string disassembly = ARM_Disasm::Disassemble(address, instr); - - if (index.column() == 0) { - return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); - } else if (index.column() == 1) { - return QString::fromStdString(disassembly); - } else if (index.column() == 2) { - if (Symbols::HasSymbol(address)) { - TSymbol symbol = Symbols::GetSymbol(address); - return QString("%1 - Size:%2") - .arg(QString::fromStdString(symbol.name)) - .arg(symbol.size / 4); // divide by 4 to get instruction count - } else if (ARM_Disasm::Decode(instr) == OP_BL) { - u32 offset = instr & 0xFFFFFF; - - // Sign-extend the 24-bit offset - if ((offset >> 23) & 1) - offset |= 0xFF000000; - - // Pre-compute the left-shift and the prefetch offset - offset <<= 2; - offset += 8; - - TSymbol symbol = Symbols::GetSymbol(address + offset); - return QString(" --> %1").arg(QString::fromStdString(symbol.name)); - } - } - - break; - } - - case Qt::BackgroundRole: { - unsigned int address = base_address + 4 * index.row(); - - if (breakpoints.IsAddressBreakPoint(address)) - return QBrush(QColor(0xFF, 0xC0, 0xC0)); - else if (address == program_counter) - return QBrush(QColor(0xC0, 0xC0, 0xFF)); - - break; - } - - case Qt::FontRole: { - if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column - return GetMonospaceFont(); - } - break; - } - - default: - break; - } - - return QVariant(); -} - -QModelIndex DisassemblerModel::IndexFromAbsoluteAddress(unsigned int address) const { - return index((address - base_address) / 4, 0); -} - -const BreakPoints& DisassemblerModel::GetBreakPoints() const { - return breakpoints; -} - -void DisassemblerModel::ParseFromAddress(unsigned int address) { - - // NOTE: A too large value causes lagging when scrolling the disassembly - const unsigned int chunk_size = 1000 * 500; - - // If we haven't loaded anything yet, initialize base address to the parameter address - if (code_size == 0) - base_address = address; - - // If the new area is already loaded, just continue - if (base_address + code_size > address + chunk_size && base_address <= address) - return; - - // Insert rows before currently loaded data - if (base_address > address) { - unsigned int num_rows = (address - base_address) / 4; - - beginInsertRows(QModelIndex(), 0, num_rows); - code_size += num_rows; - base_address = address; - - endInsertRows(); - } - - // Insert rows after currently loaded data - if (base_address + code_size < address + chunk_size) { - unsigned int num_rows = (base_address + chunk_size - code_size - address) / 4; - - beginInsertRows(QModelIndex(), 0, num_rows); - code_size += num_rows; - endInsertRows(); - } - - SetNextInstruction(address); -} - -void DisassemblerModel::OnSelectionChanged(const QModelIndex& new_selection) { - selection = new_selection; -} - -void DisassemblerModel::OnSetOrUnsetBreakpoint() { - if (!selection.isValid()) - return; - - unsigned int address = base_address + selection.row() * 4; - - if (breakpoints.IsAddressBreakPoint(address)) { - breakpoints.Remove(address); - } else { - breakpoints.Add(address); - } - - emit dataChanged(selection, selection); -} - -void DisassemblerModel::SetNextInstruction(unsigned int address) { - QModelIndex cur_index = IndexFromAbsoluteAddress(program_counter); - QModelIndex prev_index = IndexFromAbsoluteAddress(address); - - program_counter = address; - - emit dataChanged(cur_index, cur_index); - emit dataChanged(prev_index, prev_index); -} - -DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) - : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { - - disasm_ui.setupUi(this); - - RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); - RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); - RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); - RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), - Qt::ApplicationShortcut); - - connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); - connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); - connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); - - connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, - SLOT(OnToggleStartStop())); - connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); - connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, - SLOT(OnStepInto())); - - setEnabled(false); -} - -void DisassemblerWidget::Init() { - model->ParseFromAddress(Core::CPU().GetPC()); - - disasm_ui.treeView->resizeColumnToContents(0); - disasm_ui.treeView->resizeColumnToContents(1); - disasm_ui.treeView->resizeColumnToContents(2); - - QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::CPU().GetPC()); - disasm_ui.treeView->scrollTo(model_index); - disasm_ui.treeView->selectionModel()->setCurrentIndex( - model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); -} - -void DisassemblerWidget::OnContinue() { - emu_thread->SetRunning(true); -} - -void DisassemblerWidget::OnStep() { - OnStepInto(); // change later -} - -void DisassemblerWidget::OnStepInto() { - emu_thread->SetRunning(false); - emu_thread->ExecStep(); -} - -void DisassemblerWidget::OnPause() { - emu_thread->SetRunning(false); - - // TODO: By now, the CPU might not have actually stopped... - if (Core::System::GetInstance().IsPoweredOn()) { - model->SetNextInstruction(Core::CPU().GetPC()); - } -} - -void DisassemblerWidget::OnToggleStartStop() { - emu_thread->SetRunning(!emu_thread->IsRunning()); -} - -void DisassemblerWidget::OnDebugModeEntered() { - u32 next_instr = Core::CPU().GetPC(); - - if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) - emu_thread->SetRunning(false); - - model->SetNextInstruction(next_instr); - - QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr); - disasm_ui.treeView->scrollTo(model_index); - disasm_ui.treeView->selectionModel()->setCurrentIndex( - model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); -} - -void DisassemblerWidget::OnDebugModeLeft() {} - -int DisassemblerWidget::SelectedRow() { - QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); - if (!index.isValid()) - return -1; - - return disasm_ui.treeView->selectionModel()->currentIndex().row(); -} - -void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) { - this->emu_thread = emu_thread; - - model = new DisassemblerModel(this); - disasm_ui.treeView->setModel(model); - - connect(disasm_ui.treeView->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model, - SLOT(OnSelectionChanged(const QModelIndex&))); - connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint())); - connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, - SLOT(OnSetOrUnsetBreakpoint())); - - Init(); - setEnabled(true); -} - -void DisassemblerWidget::OnEmulationStopping() { - disasm_ui.treeView->setModel(nullptr); - delete model; - emu_thread = nullptr; - setEnabled(false); -} diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h deleted file mode 100644 index a6e59515c..000000000 --- a/src/citra_qt/debugger/disassembler.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <QAbstractListModel> -#include <QDockWidget> -#include "common/break_points.h" -#include "common/common_types.h" -#include "ui_disassembler.h" - -class QAction; -class EmuThread; - -class DisassemblerModel : public QAbstractListModel { - Q_OBJECT - -public: - explicit DisassemblerModel(QObject* parent); - - int columnCount(const QModelIndex& parent = QModelIndex()) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - - QModelIndex IndexFromAbsoluteAddress(unsigned int address) const; - const BreakPoints& GetBreakPoints() const; - -public slots: - void ParseFromAddress(unsigned int address); - void OnSelectionChanged(const QModelIndex&); - void OnSetOrUnsetBreakpoint(); - void SetNextInstruction(unsigned int address); - -private: - unsigned int base_address; - unsigned int code_size; - unsigned int program_counter; - - QModelIndex selection; - BreakPoints breakpoints; -}; - -class DisassemblerWidget : public QDockWidget { - Q_OBJECT - -public: - DisassemblerWidget(QWidget* parent, EmuThread* emu_thread); - - void Init(); - -public slots: - void OnContinue(); - void OnStep(); - void OnStepInto(); - void OnPause(); - void OnToggleStartStop(); - - void OnDebugModeEntered(); - void OnDebugModeLeft(); - - void OnEmulationStarting(EmuThread* emu_thread); - void OnEmulationStopping(); - -private: - // returns -1 if no row is selected - int SelectedRow(); - - Ui::DockWidget disasm_ui; - - DisassemblerModel* model; - - u32 base_addr; - - EmuThread* emu_thread; -}; diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui deleted file mode 100644 index 5ca6dc5d2..000000000 --- a/src/citra_qt/debugger/disassembler.ui +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>DockWidget</class> - <widget class="QDockWidget" name="DockWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>430</width> - <height>401</height> - </rect> - </property> - <property name="windowTitle"> - <string>Disassembly</string> - </property> - <widget class="QWidget" name="dockWidgetContents"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="button_step"> - <property name="text"> - <string>Step</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_pause"> - <property name="text"> - <string>Pause</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_continue"> - <property name="text"> - <string>Continue</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton"> - <property name="text"> - <string>Step Into</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_breakpoint"> - <property name="text"> - <string>Set Breakpoint</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTreeView" name="treeView"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="indentation"> - <number>20</number> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="uniformRowHeights"> - <bool>true</bool> - </property> - <attribute name="headerVisible"> - <bool>false</bool> - </attribute> - </widget> - </item> - </layout> - </widget> - </widget> - <resources/> - <connections/> -</ui> |