mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #2689 from yuriks/remove-disassembler
Remove built-in disassembler and related code
This commit is contained in:
		
						commit
						7325413cd8
					
				| @ -11,8 +11,6 @@ set(SRCS | ||||
|             configuration/configure_graphics.cpp | ||||
|             configuration/configure_input.cpp | ||||
|             configuration/configure_system.cpp | ||||
|             debugger/callstack.cpp | ||||
|             debugger/disassembler.cpp | ||||
|             debugger/graphics/graphics.cpp | ||||
|             debugger/graphics/graphics_breakpoint_observer.cpp | ||||
|             debugger/graphics/graphics_breakpoints.cpp | ||||
| @ -43,8 +41,6 @@ set(HEADERS | ||||
|             configuration/configure_graphics.h | ||||
|             configuration/configure_input.h | ||||
|             configuration/configure_system.h | ||||
|             debugger/callstack.h | ||||
|             debugger/disassembler.h | ||||
|             debugger/graphics/graphics.h | ||||
|             debugger/graphics/graphics_breakpoint_observer.h | ||||
|             debugger/graphics/graphics_breakpoints.h | ||||
| @ -74,8 +70,6 @@ set(UIS | ||||
|             configuration/configure_graphics.ui | ||||
|             configuration/configure_input.ui | ||||
|             configuration/configure_system.ui | ||||
|             debugger/callstack.ui | ||||
|             debugger/disassembler.ui | ||||
|             debugger/registers.ui | ||||
|             hotkeys.ui | ||||
|             main.ui | ||||
|  | ||||
| @ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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(); | ||||
| }; | ||||
| @ -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> | ||||
| @ -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); | ||||
| } | ||||
| @ -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; | ||||
| }; | ||||
| @ -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> | ||||
| @ -16,8 +16,6 @@ | ||||
| #include "citra_qt/bootmanager.h" | ||||
| #include "citra_qt/configuration/config.h" | ||||
| #include "citra_qt/configuration/configure_dialog.h" | ||||
| #include "citra_qt/debugger/callstack.h" | ||||
| #include "citra_qt/debugger/disassembler.h" | ||||
| #include "citra_qt/debugger/graphics/graphics.h" | ||||
| #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | ||||
| #include "citra_qt/debugger/graphics/graphics_cmdlists.h" | ||||
| @ -40,7 +38,6 @@ | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/arm/disassembler/load_symbol_map.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/archive_source_sd_savedata.h" | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
| @ -130,15 +127,6 @@ void GMainWindow::InitializeDebugWidgets() { | ||||
|     debug_menu->addAction(microProfileDialog->toggleViewAction()); | ||||
| #endif | ||||
| 
 | ||||
|     disasmWidget = new DisassemblerWidget(this, emu_thread.get()); | ||||
|     addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); | ||||
|     disasmWidget->hide(); | ||||
|     debug_menu->addAction(disasmWidget->toggleViewAction()); | ||||
|     connect(this, &GMainWindow::EmulationStarting, disasmWidget, | ||||
|             &DisassemblerWidget::OnEmulationStarting); | ||||
|     connect(this, &GMainWindow::EmulationStopping, disasmWidget, | ||||
|             &DisassemblerWidget::OnEmulationStopping); | ||||
| 
 | ||||
|     registersWidget = new RegistersWidget(this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, registersWidget); | ||||
|     registersWidget->hide(); | ||||
| @ -148,11 +136,6 @@ void GMainWindow::InitializeDebugWidgets() { | ||||
|     connect(this, &GMainWindow::EmulationStopping, registersWidget, | ||||
|             &RegistersWidget::OnEmulationStopping); | ||||
| 
 | ||||
|     callstackWidget = new CallstackWidget(this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, callstackWidget); | ||||
|     callstackWidget->hide(); | ||||
|     debug_menu->addAction(callstackWidget->toggleViewAction()); | ||||
| 
 | ||||
|     graphicsWidget = new GPUCommandStreamWidget(this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); | ||||
|     graphicsWidget->hide(); | ||||
| @ -269,8 +252,6 @@ void GMainWindow::ConnectWidgetEvents() { | ||||
| void GMainWindow::ConnectMenuEvents() { | ||||
|     // File
 | ||||
|     connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile); | ||||
|     connect(ui.action_Load_Symbol_Map, &QAction::triggered, this, | ||||
|             &GMainWindow::OnMenuLoadSymbolMap); | ||||
|     connect(ui.action_Select_Game_List_Root, &QAction::triggered, this, | ||||
|             &GMainWindow::OnMenuSelectGameListRoot); | ||||
|     connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); | ||||
| @ -391,26 +372,17 @@ void GMainWindow::BootGame(const QString& filename) { | ||||
|     connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame())); | ||||
|     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
 | ||||
|     // before the CPU continues
 | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, | ||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, | ||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget, | ||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), waitTreeWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
| 
 | ||||
|     // Update the GUI
 | ||||
|     registersWidget->OnDebugModeEntered(); | ||||
|     callstackWidget->OnDebugModeEntered(); | ||||
|     if (ui.action_Single_Window_Mode->isChecked()) { | ||||
|         game_list->hide(); | ||||
|     } | ||||
| @ -531,16 +503,6 @@ void GMainWindow::OnMenuLoadFile() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnMenuLoadSymbolMap() { | ||||
|     QString filename = QFileDialog::getOpenFileName( | ||||
|         this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol Map (*.*)")); | ||||
|     if (!filename.isEmpty()) { | ||||
|         UISettings::values.symbols_path = QFileInfo(filename).path(); | ||||
| 
 | ||||
|         LoadSymbolMap(filename.toStdString()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnMenuSelectGameListRoot() { | ||||
|     QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); | ||||
|     if (!dir_path.isEmpty()) { | ||||
|  | ||||
| @ -10,9 +10,7 @@ | ||||
| #include <QTimer> | ||||
| #include "ui_main.h" | ||||
| 
 | ||||
| class CallstackWidget; | ||||
| class Config; | ||||
| class DisassemblerWidget; | ||||
| class EmuThread; | ||||
| class GameList; | ||||
| class GImageInfo; | ||||
| @ -118,7 +116,6 @@ private slots: | ||||
|     void OnGameListLoadFile(QString game_path); | ||||
|     void OnGameListOpenSaveFolder(u64 program_id); | ||||
|     void OnMenuLoadFile(); | ||||
|     void OnMenuLoadSymbolMap(); | ||||
|     /// Called whenever a user selects the "File->Select Game List Root" menu item
 | ||||
|     void OnMenuSelectGameListRoot(); | ||||
|     void OnMenuRecentFile(); | ||||
| @ -152,9 +149,7 @@ private: | ||||
|     // Debugger panes
 | ||||
|     ProfilerWidget* profilerWidget; | ||||
|     MicroProfileDialog* microProfileDialog; | ||||
|     DisassemblerWidget* disasmWidget; | ||||
|     RegistersWidget* registersWidget; | ||||
|     CallstackWidget* callstackWidget; | ||||
|     GPUCommandStreamWidget* graphicsWidget; | ||||
|     GPUCommandListWidget* graphicsCommandsWidget; | ||||
|     GraphicsBreakPointsWidget* graphicsBreakpointsWidget; | ||||
|  | ||||
| @ -58,7 +58,6 @@ | ||||
|      </property> | ||||
|     </widget> | ||||
|     <addaction name="action_Load_File"/> | ||||
|     <addaction name="action_Load_Symbol_Map"/> | ||||
|     <addaction name="separator"/> | ||||
|     <addaction name="action_Select_Game_List_Root"/> | ||||
|     <addaction name="menu_recent_files"/> | ||||
|  | ||||
| @ -38,7 +38,6 @@ set(SRCS | ||||
|             param_package.cpp | ||||
|             scm_rev.cpp | ||||
|             string_util.cpp | ||||
|             symbols.cpp | ||||
|             thread.cpp | ||||
|             timer.cpp | ||||
|             ) | ||||
| @ -74,7 +73,6 @@ set(HEADERS | ||||
|             scope_exit.h | ||||
|             string_util.h | ||||
|             swap.h | ||||
|             symbols.h | ||||
|             synchronized_wrapper.h | ||||
|             thread.h | ||||
|             thread_queue_list.h | ||||
|  | ||||
| @ -1,46 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/symbols.h" | ||||
| 
 | ||||
| TSymbolsMap g_symbols; | ||||
| 
 | ||||
| namespace Symbols { | ||||
| bool HasSymbol(u32 address) { | ||||
|     return g_symbols.find(address) != g_symbols.end(); | ||||
| } | ||||
| 
 | ||||
| void Add(u32 address, const std::string& name, u32 size, u32 type) { | ||||
|     if (!HasSymbol(address)) { | ||||
|         TSymbol symbol; | ||||
|         symbol.address = address; | ||||
|         symbol.name = name; | ||||
|         symbol.size = size; | ||||
|         symbol.type = type; | ||||
| 
 | ||||
|         g_symbols.emplace(address, symbol); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| TSymbol GetSymbol(u32 address) { | ||||
|     const auto iter = g_symbols.find(address); | ||||
| 
 | ||||
|     if (iter != g_symbols.end()) | ||||
|         return iter->second; | ||||
| 
 | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| const std::string GetName(u32 address) { | ||||
|     return GetSymbol(address).name; | ||||
| } | ||||
| 
 | ||||
| void Remove(u32 address) { | ||||
|     g_symbols.erase(address); | ||||
| } | ||||
| 
 | ||||
| void Clear() { | ||||
|     g_symbols.clear(); | ||||
| } | ||||
| } | ||||
| @ -1,30 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <map> | ||||
| #include <string> | ||||
| #include <utility> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| struct TSymbol { | ||||
|     u32 address = 0; | ||||
|     std::string name; | ||||
|     u32 size = 0; | ||||
|     u32 type = 0; | ||||
| }; | ||||
| 
 | ||||
| typedef std::map<u32, TSymbol> TSymbolsMap; | ||||
| typedef std::pair<u32, TSymbol> TSymbolsPair; | ||||
| 
 | ||||
| namespace Symbols { | ||||
| bool HasSymbol(u32 address); | ||||
| 
 | ||||
| void Add(u32 address, const std::string& name, u32 size, u32 type); | ||||
| TSymbol GetSymbol(u32 address); | ||||
| const std::string GetName(u32 address); | ||||
| void Remove(u32 address); | ||||
| void Clear(); | ||||
| } | ||||
| @ -1,6 +1,4 @@ | ||||
| set(SRCS | ||||
|             arm/disassembler/arm_disasm.cpp | ||||
|             arm/disassembler/load_symbol_map.cpp | ||||
|             arm/dynarmic/arm_dynarmic.cpp | ||||
|             arm/dynarmic/arm_dynarmic_cp15.cpp | ||||
|             arm/dyncom/arm_dyncom.cpp | ||||
| @ -179,8 +177,6 @@ set(SRCS | ||||
| 
 | ||||
| set(HEADERS | ||||
|             arm/arm_interface.h | ||||
|             arm/disassembler/arm_disasm.h | ||||
|             arm/disassembler/load_symbol_map.h | ||||
|             arm/dynarmic/arm_dynarmic.h | ||||
|             arm/dynarmic/arm_dynarmic_cp15.h | ||||
|             arm/dyncom/arm_dyncom.h | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,238 +0,0 @@ | ||||
| // Copyright 2006 The Android Open Source Project
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| // Note: this list of opcodes must match the list used to initialize
 | ||||
| // the opflags[] array in opcode.cpp.
 | ||||
| enum Opcode { | ||||
|     OP_INVALID, | ||||
|     OP_UNDEFINED, | ||||
|     OP_ADC, | ||||
|     OP_ADD, | ||||
|     OP_AND, | ||||
|     OP_B, | ||||
|     OP_BL, | ||||
|     OP_BIC, | ||||
|     OP_BKPT, | ||||
|     OP_BLX, | ||||
|     OP_BX, | ||||
|     OP_CDP, | ||||
|     OP_CLREX, | ||||
|     OP_CLZ, | ||||
|     OP_CMN, | ||||
|     OP_CMP, | ||||
|     OP_EOR, | ||||
|     OP_LDC, | ||||
|     OP_LDM, | ||||
|     OP_LDR, | ||||
|     OP_LDRB, | ||||
|     OP_LDRBT, | ||||
|     OP_LDREX, | ||||
|     OP_LDREXB, | ||||
|     OP_LDREXD, | ||||
|     OP_LDREXH, | ||||
|     OP_LDRH, | ||||
|     OP_LDRSB, | ||||
|     OP_LDRSH, | ||||
|     OP_LDRT, | ||||
|     OP_MCR, | ||||
|     OP_MLA, | ||||
|     OP_MOV, | ||||
|     OP_MRC, | ||||
|     OP_MRS, | ||||
|     OP_MSR, | ||||
|     OP_MUL, | ||||
|     OP_MVN, | ||||
|     OP_NOP, | ||||
|     OP_ORR, | ||||
|     OP_PKH, | ||||
|     OP_PLD, | ||||
|     OP_QADD16, | ||||
|     OP_QADD8, | ||||
|     OP_QASX, | ||||
|     OP_QSAX, | ||||
|     OP_QSUB16, | ||||
|     OP_QSUB8, | ||||
|     OP_REV, | ||||
|     OP_REV16, | ||||
|     OP_REVSH, | ||||
|     OP_RSB, | ||||
|     OP_RSC, | ||||
|     OP_SADD16, | ||||
|     OP_SADD8, | ||||
|     OP_SASX, | ||||
|     OP_SBC, | ||||
|     OP_SEL, | ||||
|     OP_SEV, | ||||
|     OP_SHADD16, | ||||
|     OP_SHADD8, | ||||
|     OP_SHASX, | ||||
|     OP_SHSAX, | ||||
|     OP_SHSUB16, | ||||
|     OP_SHSUB8, | ||||
|     OP_SMLAD, | ||||
|     OP_SMLAL, | ||||
|     OP_SMLALD, | ||||
|     OP_SMLSD, | ||||
|     OP_SMLSLD, | ||||
|     OP_SMMLA, | ||||
|     OP_SMMLS, | ||||
|     OP_SMMUL, | ||||
|     OP_SMUAD, | ||||
|     OP_SMULL, | ||||
|     OP_SMUSD, | ||||
|     OP_SSAT, | ||||
|     OP_SSAT16, | ||||
|     OP_SSAX, | ||||
|     OP_SSUB16, | ||||
|     OP_SSUB8, | ||||
|     OP_STC, | ||||
|     OP_STM, | ||||
|     OP_STR, | ||||
|     OP_STRB, | ||||
|     OP_STRBT, | ||||
|     OP_STREX, | ||||
|     OP_STREXB, | ||||
|     OP_STREXD, | ||||
|     OP_STREXH, | ||||
|     OP_STRH, | ||||
|     OP_STRT, | ||||
|     OP_SUB, | ||||
|     OP_SWI, | ||||
|     OP_SWP, | ||||
|     OP_SWPB, | ||||
|     OP_SXTAB, | ||||
|     OP_SXTAB16, | ||||
|     OP_SXTAH, | ||||
|     OP_SXTB, | ||||
|     OP_SXTB16, | ||||
|     OP_SXTH, | ||||
|     OP_TEQ, | ||||
|     OP_TST, | ||||
|     OP_UADD16, | ||||
|     OP_UADD8, | ||||
|     OP_UASX, | ||||
|     OP_UHADD16, | ||||
|     OP_UHADD8, | ||||
|     OP_UHASX, | ||||
|     OP_UHSAX, | ||||
|     OP_UHSUB16, | ||||
|     OP_UHSUB8, | ||||
|     OP_UMLAL, | ||||
|     OP_UMULL, | ||||
|     OP_UQADD16, | ||||
|     OP_UQADD8, | ||||
|     OP_UQASX, | ||||
|     OP_UQSAX, | ||||
|     OP_UQSUB16, | ||||
|     OP_UQSUB8, | ||||
|     OP_USAD8, | ||||
|     OP_USADA8, | ||||
|     OP_USAT, | ||||
|     OP_USAT16, | ||||
|     OP_USAX, | ||||
|     OP_USUB16, | ||||
|     OP_USUB8, | ||||
|     OP_UXTAB, | ||||
|     OP_UXTAB16, | ||||
|     OP_UXTAH, | ||||
|     OP_UXTB, | ||||
|     OP_UXTB16, | ||||
|     OP_UXTH, | ||||
|     OP_WFE, | ||||
|     OP_WFI, | ||||
|     OP_YIELD, | ||||
| 
 | ||||
|     // Define thumb opcodes
 | ||||
|     OP_THUMB_UNDEFINED, | ||||
|     OP_THUMB_ADC, | ||||
|     OP_THUMB_ADD, | ||||
|     OP_THUMB_AND, | ||||
|     OP_THUMB_ASR, | ||||
|     OP_THUMB_B, | ||||
|     OP_THUMB_BIC, | ||||
|     OP_THUMB_BKPT, | ||||
|     OP_THUMB_BL, | ||||
|     OP_THUMB_BLX, | ||||
|     OP_THUMB_BX, | ||||
|     OP_THUMB_CMN, | ||||
|     OP_THUMB_CMP, | ||||
|     OP_THUMB_EOR, | ||||
|     OP_THUMB_LDMIA, | ||||
|     OP_THUMB_LDR, | ||||
|     OP_THUMB_LDRB, | ||||
|     OP_THUMB_LDRH, | ||||
|     OP_THUMB_LDRSB, | ||||
|     OP_THUMB_LDRSH, | ||||
|     OP_THUMB_LSL, | ||||
|     OP_THUMB_LSR, | ||||
|     OP_THUMB_MOV, | ||||
|     OP_THUMB_MUL, | ||||
|     OP_THUMB_MVN, | ||||
|     OP_THUMB_NEG, | ||||
|     OP_THUMB_ORR, | ||||
|     OP_THUMB_POP, | ||||
|     OP_THUMB_PUSH, | ||||
|     OP_THUMB_ROR, | ||||
|     OP_THUMB_SBC, | ||||
|     OP_THUMB_STMIA, | ||||
|     OP_THUMB_STR, | ||||
|     OP_THUMB_STRB, | ||||
|     OP_THUMB_STRH, | ||||
|     OP_THUMB_SUB, | ||||
|     OP_THUMB_SWI, | ||||
|     OP_THUMB_TST, | ||||
| 
 | ||||
|     OP_END // must be last
 | ||||
| }; | ||||
| 
 | ||||
| class ARM_Disasm { | ||||
| public: | ||||
|     static std::string Disassemble(u32 addr, u32 insn); | ||||
|     static Opcode Decode(u32 insn); | ||||
| 
 | ||||
| private: | ||||
|     static Opcode Decode00(u32 insn); | ||||
|     static Opcode Decode01(u32 insn); | ||||
|     static Opcode Decode10(u32 insn); | ||||
|     static Opcode Decode11(u32 insn); | ||||
|     static Opcode DecodeSyncPrimitive(u32 insn); | ||||
|     static Opcode DecodeParallelAddSub(u32 insn); | ||||
|     static Opcode DecodePackingSaturationReversal(u32 insn); | ||||
|     static Opcode DecodeMUL(u32 insn); | ||||
|     static Opcode DecodeMSRImmAndHints(u32 insn); | ||||
|     static Opcode DecodeMediaMulDiv(u32 insn); | ||||
|     static Opcode DecodeMedia(u32 insn); | ||||
|     static Opcode DecodeLDRH(u32 insn); | ||||
|     static Opcode DecodeALU(u32 insn); | ||||
| 
 | ||||
|     static std::string DisassembleALU(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleBX(u32 insn); | ||||
|     static std::string DisassembleBKPT(u32 insn); | ||||
|     static std::string DisassembleCLZ(u32 insn); | ||||
|     static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleMemblock(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleMem(u32 insn); | ||||
|     static std::string DisassembleMemHalf(u32 insn); | ||||
|     static std::string DisassembleMCR(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleMLA(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleUMLAL(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleMUL(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleMRS(u32 insn); | ||||
|     static std::string DisassembleMSR(u32 insn); | ||||
|     static std::string DisassembleNoOperands(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); | ||||
|     static std::string DisassemblePKH(u32 insn); | ||||
|     static std::string DisassemblePLD(u32 insn); | ||||
|     static std::string DisassembleREV(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleREX(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleSAT(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleSEL(u32 insn); | ||||
|     static std::string DisassembleSWI(u32 insn); | ||||
|     static std::string DisassembleSWP(Opcode opcode, u32 insn); | ||||
|     static std::string DisassembleXT(Opcode opcode, u32 insn); | ||||
| }; | ||||
| @ -1,31 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "common/file_util.h" | ||||
| #include "common/symbols.h" | ||||
| #include "core/arm/disassembler/load_symbol_map.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Loads a symbol map file for use with the disassembler | ||||
|  * @param filename String filename path of symbol map file | ||||
|  */ | ||||
| void LoadSymbolMap(std::string filename) { | ||||
|     std::ifstream infile(filename); | ||||
| 
 | ||||
|     std::string address_str, function_name, line; | ||||
|     u32 size; | ||||
| 
 | ||||
|     while (std::getline(infile, line)) { | ||||
|         std::istringstream iss(line); | ||||
|         if (!(iss >> address_str >> size >> function_name)) { | ||||
|             break; // Error parsing
 | ||||
|         } | ||||
|         u32 address = std::stoul(address_str, nullptr, 16); | ||||
| 
 | ||||
|         Symbols::Add(address, function_name, size, 2); | ||||
|     } | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| /*
 | ||||
|  * Loads a symbol map file for use with the disassembler | ||||
|  * @param filename String filename path of symbol map file | ||||
|  */ | ||||
| void LoadSymbolMap(std::string filename); | ||||
| @ -415,7 +415,7 @@ const InstructionSetEncodingItem arm_exclusion_code[] = { | ||||
| }; | ||||
| // clang-format on
 | ||||
| 
 | ||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | ||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx) { | ||||
|     int n = 0; | ||||
|     int base = 0; | ||||
|     int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
| 
 | ||||
| enum class ARMDecodeStatus { SUCCESS, FAILURE }; | ||||
| 
 | ||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); | ||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx); | ||||
| 
 | ||||
| struct InstructionSetEncodingItem { | ||||
|     const char* name; | ||||
|  | ||||
| @ -5,11 +5,11 @@ | ||||
| #define CITRA_IGNORE_EXIT(x) | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cinttypes> | ||||
| #include <cstdio> | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "core/arm/disassembler/arm_disasm.h" | ||||
| #include "core/arm/dyncom/arm_dyncom_dec.h" | ||||
| #include "core/arm/dyncom/arm_dyncom_interpreter.h" | ||||
| #include "core/arm/dyncom/arm_dyncom_run.h" | ||||
| @ -808,8 +808,8 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); | ||||
| 
 | ||||
| static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, | ||||
|                                                     ARM_INST_PTR& inst_base) { | ||||
|     unsigned int inst_size = 4; | ||||
|     unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | ||||
|     u32 inst_size = 4; | ||||
|     u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | ||||
| 
 | ||||
|     // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
 | ||||
|     // instruction
 | ||||
| @ -827,11 +827,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons | ||||
| 
 | ||||
|     int idx; | ||||
|     if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { | ||||
|         std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); | ||||
|         LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, | ||||
|                   disasm.c_str(), inst); | ||||
|         LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, | ||||
|                   cpu->Reg[15]); | ||||
|         LOG_ERROR(Core_ARM11, "Decode failure.\tPC: [0x%08" PRIX32 "]\tInstruction: %08" PRIX32, | ||||
|                   phys_addr, inst); | ||||
|         LOG_ERROR(Core_ARM11, "cpsr=0x%" PRIX32 ", cpu->TFlag=%d, r15=0x%08" PRIX32, cpu->Cpsr, | ||||
|                   cpu->TFlag, cpu->Reg[15]); | ||||
|         CITRA_IGNORE_EXIT(-1); | ||||
|     } | ||||
|     inst_base = arm_instruction_trans[idx](inst, idx); | ||||
|  | ||||
| @ -2,12 +2,12 @@ | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cinttypes> | ||||
| #include <map> | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/symbols.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/function_wrappers.h" | ||||
| @ -524,13 +524,7 @@ static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 ent | ||||
|                                u32 stack_top, s32 processor_id) { | ||||
|     using Kernel::Thread; | ||||
| 
 | ||||
|     std::string name; | ||||
|     if (Symbols::HasSymbol(entry_point)) { | ||||
|         TSymbol symbol = Symbols::GetSymbol(entry_point); | ||||
|         name = symbol.name; | ||||
|     } else { | ||||
|         name = Common::StringFromFormat("unknown-%08x", entry_point); | ||||
|     } | ||||
|     std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point); | ||||
| 
 | ||||
|     if (priority > THREADPRIO_LOWEST) { | ||||
|         return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, | ||||
|  | ||||
| @ -8,7 +8,6 @@ | ||||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/symbols.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/resource_limit.h" | ||||
| #include "core/loader/elf.h" | ||||
| @ -210,7 +209,6 @@ public: | ||||
|         return (u32)(header->e_flags); | ||||
|     } | ||||
|     SharedPtr<CodeSet> LoadInto(u32 vaddr); | ||||
|     bool LoadSymbols(); | ||||
| 
 | ||||
|     int GetNumSegments() const { | ||||
|         return (int)(header->e_phnum); | ||||
| @ -258,8 +256,6 @@ ElfReader::ElfReader(void* ptr) { | ||||
|     sections = (Elf32_Shdr*)(base + header->e_shoff); | ||||
| 
 | ||||
|     entryPoint = header->e_entry; | ||||
| 
 | ||||
|     LoadSymbols(); | ||||
| } | ||||
| 
 | ||||
| const char* ElfReader::GetSectionName(int section) const { | ||||
| @ -362,34 +358,6 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| bool ElfReader::LoadSymbols() { | ||||
|     bool hasSymbols = false; | ||||
|     SectionID sec = GetSectionByName(".symtab"); | ||||
|     if (sec != -1) { | ||||
|         int stringSection = sections[sec].sh_link; | ||||
|         const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); | ||||
| 
 | ||||
|         // We have a symbol table!
 | ||||
|         const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); | ||||
|         unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); | ||||
|         for (unsigned sym = 0; sym < numSymbols; sym++) { | ||||
|             int size = symtab[sym].st_size; | ||||
|             if (size == 0) | ||||
|                 continue; | ||||
| 
 | ||||
|             int type = symtab[sym].st_info & 0xF; | ||||
| 
 | ||||
|             const char* name = stringBase + symtab[sym].st_name; | ||||
| 
 | ||||
|             Symbols::Add(symtab[sym].st_value, name, size, type); | ||||
| 
 | ||||
|             hasSymbols = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return hasSymbols; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Loader namespace
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei