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_graphics.cpp | ||||||
|             configuration/configure_input.cpp |             configuration/configure_input.cpp | ||||||
|             configuration/configure_system.cpp |             configuration/configure_system.cpp | ||||||
|             debugger/callstack.cpp |  | ||||||
|             debugger/disassembler.cpp |  | ||||||
|             debugger/graphics/graphics.cpp |             debugger/graphics/graphics.cpp | ||||||
|             debugger/graphics/graphics_breakpoint_observer.cpp |             debugger/graphics/graphics_breakpoint_observer.cpp | ||||||
|             debugger/graphics/graphics_breakpoints.cpp |             debugger/graphics/graphics_breakpoints.cpp | ||||||
| @ -43,8 +41,6 @@ set(HEADERS | |||||||
|             configuration/configure_graphics.h |             configuration/configure_graphics.h | ||||||
|             configuration/configure_input.h |             configuration/configure_input.h | ||||||
|             configuration/configure_system.h |             configuration/configure_system.h | ||||||
|             debugger/callstack.h |  | ||||||
|             debugger/disassembler.h |  | ||||||
|             debugger/graphics/graphics.h |             debugger/graphics/graphics.h | ||||||
|             debugger/graphics/graphics_breakpoint_observer.h |             debugger/graphics/graphics_breakpoint_observer.h | ||||||
|             debugger/graphics/graphics_breakpoints.h |             debugger/graphics/graphics_breakpoints.h | ||||||
| @ -74,8 +70,6 @@ set(UIS | |||||||
|             configuration/configure_graphics.ui |             configuration/configure_graphics.ui | ||||||
|             configuration/configure_input.ui |             configuration/configure_input.ui | ||||||
|             configuration/configure_system.ui |             configuration/configure_system.ui | ||||||
|             debugger/callstack.ui |  | ||||||
|             debugger/disassembler.ui |  | ||||||
|             debugger/registers.ui |             debugger/registers.ui | ||||||
|             hotkeys.ui |             hotkeys.ui | ||||||
|             main.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/bootmanager.h" | ||||||
| #include "citra_qt/configuration/config.h" | #include "citra_qt/configuration/config.h" | ||||||
| #include "citra_qt/configuration/configure_dialog.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.h" | ||||||
| #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | #include "citra_qt/debugger/graphics/graphics_breakpoints.h" | ||||||
| #include "citra_qt/debugger/graphics/graphics_cmdlists.h" | #include "citra_qt/debugger/graphics/graphics_cmdlists.h" | ||||||
| @ -40,7 +38,6 @@ | |||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/arm/disassembler/load_symbol_map.h" |  | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/file_sys/archive_source_sd_savedata.h" | #include "core/file_sys/archive_source_sd_savedata.h" | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| @ -130,15 +127,6 @@ void GMainWindow::InitializeDebugWidgets() { | |||||||
|     debug_menu->addAction(microProfileDialog->toggleViewAction()); |     debug_menu->addAction(microProfileDialog->toggleViewAction()); | ||||||
| #endif | #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); |     registersWidget = new RegistersWidget(this); | ||||||
|     addDockWidget(Qt::RightDockWidgetArea, registersWidget); |     addDockWidget(Qt::RightDockWidgetArea, registersWidget); | ||||||
|     registersWidget->hide(); |     registersWidget->hide(); | ||||||
| @ -148,11 +136,6 @@ void GMainWindow::InitializeDebugWidgets() { | |||||||
|     connect(this, &GMainWindow::EmulationStopping, registersWidget, |     connect(this, &GMainWindow::EmulationStopping, registersWidget, | ||||||
|             &RegistersWidget::OnEmulationStopping); |             &RegistersWidget::OnEmulationStopping); | ||||||
| 
 | 
 | ||||||
|     callstackWidget = new CallstackWidget(this); |  | ||||||
|     addDockWidget(Qt::RightDockWidgetArea, callstackWidget); |  | ||||||
|     callstackWidget->hide(); |  | ||||||
|     debug_menu->addAction(callstackWidget->toggleViewAction()); |  | ||||||
| 
 |  | ||||||
|     graphicsWidget = new GPUCommandStreamWidget(this); |     graphicsWidget = new GPUCommandStreamWidget(this); | ||||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); |     addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); | ||||||
|     graphicsWidget->hide(); |     graphicsWidget->hide(); | ||||||
| @ -269,8 +252,6 @@ void GMainWindow::ConnectWidgetEvents() { | |||||||
| void GMainWindow::ConnectMenuEvents() { | void GMainWindow::ConnectMenuEvents() { | ||||||
|     // File
 |     // File
 | ||||||
|     connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile); |     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, |     connect(ui.action_Select_Game_List_Root, &QAction::triggered, this, | ||||||
|             &GMainWindow::OnMenuSelectGameListRoot); |             &GMainWindow::OnMenuSelectGameListRoot); | ||||||
|     connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); |     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())); |     connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame())); | ||||||
|     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
 |     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
 | ||||||
|     // before the CPU continues
 |     // before the CPU continues
 | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), |  | ||||||
|             Qt::BlockingQueuedConnection); |  | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, |     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, | ||||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); |             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, |  | ||||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); |  | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget, |     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget, | ||||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); |             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), |  | ||||||
|             Qt::BlockingQueuedConnection); |  | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), |     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), | ||||||
|             Qt::BlockingQueuedConnection); |             Qt::BlockingQueuedConnection); | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), |  | ||||||
|             Qt::BlockingQueuedConnection); |  | ||||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), waitTreeWidget, SLOT(OnDebugModeLeft()), |     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), waitTreeWidget, SLOT(OnDebugModeLeft()), | ||||||
|             Qt::BlockingQueuedConnection); |             Qt::BlockingQueuedConnection); | ||||||
| 
 | 
 | ||||||
|     // Update the GUI
 |     // Update the GUI
 | ||||||
|     registersWidget->OnDebugModeEntered(); |     registersWidget->OnDebugModeEntered(); | ||||||
|     callstackWidget->OnDebugModeEntered(); |  | ||||||
|     if (ui.action_Single_Window_Mode->isChecked()) { |     if (ui.action_Single_Window_Mode->isChecked()) { | ||||||
|         game_list->hide(); |         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() { | void GMainWindow::OnMenuSelectGameListRoot() { | ||||||
|     QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); |     QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); | ||||||
|     if (!dir_path.isEmpty()) { |     if (!dir_path.isEmpty()) { | ||||||
|  | |||||||
| @ -10,9 +10,7 @@ | |||||||
| #include <QTimer> | #include <QTimer> | ||||||
| #include "ui_main.h" | #include "ui_main.h" | ||||||
| 
 | 
 | ||||||
| class CallstackWidget; |  | ||||||
| class Config; | class Config; | ||||||
| class DisassemblerWidget; |  | ||||||
| class EmuThread; | class EmuThread; | ||||||
| class GameList; | class GameList; | ||||||
| class GImageInfo; | class GImageInfo; | ||||||
| @ -118,7 +116,6 @@ private slots: | |||||||
|     void OnGameListLoadFile(QString game_path); |     void OnGameListLoadFile(QString game_path); | ||||||
|     void OnGameListOpenSaveFolder(u64 program_id); |     void OnGameListOpenSaveFolder(u64 program_id); | ||||||
|     void OnMenuLoadFile(); |     void OnMenuLoadFile(); | ||||||
|     void OnMenuLoadSymbolMap(); |  | ||||||
|     /// Called whenever a user selects the "File->Select Game List Root" menu item
 |     /// Called whenever a user selects the "File->Select Game List Root" menu item
 | ||||||
|     void OnMenuSelectGameListRoot(); |     void OnMenuSelectGameListRoot(); | ||||||
|     void OnMenuRecentFile(); |     void OnMenuRecentFile(); | ||||||
| @ -152,9 +149,7 @@ private: | |||||||
|     // Debugger panes
 |     // Debugger panes
 | ||||||
|     ProfilerWidget* profilerWidget; |     ProfilerWidget* profilerWidget; | ||||||
|     MicroProfileDialog* microProfileDialog; |     MicroProfileDialog* microProfileDialog; | ||||||
|     DisassemblerWidget* disasmWidget; |  | ||||||
|     RegistersWidget* registersWidget; |     RegistersWidget* registersWidget; | ||||||
|     CallstackWidget* callstackWidget; |  | ||||||
|     GPUCommandStreamWidget* graphicsWidget; |     GPUCommandStreamWidget* graphicsWidget; | ||||||
|     GPUCommandListWidget* graphicsCommandsWidget; |     GPUCommandListWidget* graphicsCommandsWidget; | ||||||
|     GraphicsBreakPointsWidget* graphicsBreakpointsWidget; |     GraphicsBreakPointsWidget* graphicsBreakpointsWidget; | ||||||
|  | |||||||
| @ -58,7 +58,6 @@ | |||||||
|      </property> |      </property> | ||||||
|     </widget> |     </widget> | ||||||
|     <addaction name="action_Load_File"/> |     <addaction name="action_Load_File"/> | ||||||
|     <addaction name="action_Load_Symbol_Map"/> |  | ||||||
|     <addaction name="separator"/> |     <addaction name="separator"/> | ||||||
|     <addaction name="action_Select_Game_List_Root"/> |     <addaction name="action_Select_Game_List_Root"/> | ||||||
|     <addaction name="menu_recent_files"/> |     <addaction name="menu_recent_files"/> | ||||||
|  | |||||||
| @ -38,7 +38,6 @@ set(SRCS | |||||||
|             param_package.cpp |             param_package.cpp | ||||||
|             scm_rev.cpp |             scm_rev.cpp | ||||||
|             string_util.cpp |             string_util.cpp | ||||||
|             symbols.cpp |  | ||||||
|             thread.cpp |             thread.cpp | ||||||
|             timer.cpp |             timer.cpp | ||||||
|             ) |             ) | ||||||
| @ -74,7 +73,6 @@ set(HEADERS | |||||||
|             scope_exit.h |             scope_exit.h | ||||||
|             string_util.h |             string_util.h | ||||||
|             swap.h |             swap.h | ||||||
|             symbols.h |  | ||||||
|             synchronized_wrapper.h |             synchronized_wrapper.h | ||||||
|             thread.h |             thread.h | ||||||
|             thread_queue_list.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 | set(SRCS | ||||||
|             arm/disassembler/arm_disasm.cpp |  | ||||||
|             arm/disassembler/load_symbol_map.cpp |  | ||||||
|             arm/dynarmic/arm_dynarmic.cpp |             arm/dynarmic/arm_dynarmic.cpp | ||||||
|             arm/dynarmic/arm_dynarmic_cp15.cpp |             arm/dynarmic/arm_dynarmic_cp15.cpp | ||||||
|             arm/dyncom/arm_dyncom.cpp |             arm/dyncom/arm_dyncom.cpp | ||||||
| @ -179,8 +177,6 @@ set(SRCS | |||||||
| 
 | 
 | ||||||
| set(HEADERS | set(HEADERS | ||||||
|             arm/arm_interface.h |             arm/arm_interface.h | ||||||
|             arm/disassembler/arm_disasm.h |  | ||||||
|             arm/disassembler/load_symbol_map.h |  | ||||||
|             arm/dynarmic/arm_dynarmic.h |             arm/dynarmic/arm_dynarmic.h | ||||||
|             arm/dynarmic/arm_dynarmic_cp15.h |             arm/dynarmic/arm_dynarmic_cp15.h | ||||||
|             arm/dyncom/arm_dyncom.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
 | // clang-format on
 | ||||||
| 
 | 
 | ||||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx) { | ||||||
|     int n = 0; |     int n = 0; | ||||||
|     int base = 0; |     int base = 0; | ||||||
|     int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); |     int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| enum class ARMDecodeStatus { SUCCESS, FAILURE }; | enum class ARMDecodeStatus { SUCCESS, FAILURE }; | ||||||
| 
 | 
 | ||||||
| ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); | ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx); | ||||||
| 
 | 
 | ||||||
| struct InstructionSetEncodingItem { | struct InstructionSetEncodingItem { | ||||||
|     const char* name; |     const char* name; | ||||||
|  | |||||||
| @ -5,11 +5,11 @@ | |||||||
| #define CITRA_IGNORE_EXIT(x) | #define CITRA_IGNORE_EXIT(x) | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
|  | #include <cinttypes> | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/microprofile.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_dec.h" | ||||||
| #include "core/arm/dyncom/arm_dyncom_interpreter.h" | #include "core/arm/dyncom/arm_dyncom_interpreter.h" | ||||||
| #include "core/arm/dyncom/arm_dyncom_run.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, | static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, | ||||||
|                                                     ARM_INST_PTR& inst_base) { |                                                     ARM_INST_PTR& inst_base) { | ||||||
|     unsigned int inst_size = 4; |     u32 inst_size = 4; | ||||||
|     unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); |     u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | ||||||
| 
 | 
 | ||||||
|     // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
 |     // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
 | ||||||
|     // instruction
 |     // instruction
 | ||||||
| @ -827,11 +827,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons | |||||||
| 
 | 
 | ||||||
|     int idx; |     int idx; | ||||||
|     if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { |     if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { | ||||||
|         std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); |         LOG_ERROR(Core_ARM11, "Decode failure.\tPC: [0x%08" PRIX32 "]\tInstruction: %08" PRIX32, | ||||||
|         LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, |                   phys_addr, inst); | ||||||
|                   disasm.c_str(), inst); |         LOG_ERROR(Core_ARM11, "cpsr=0x%" PRIX32 ", cpu->TFlag=%d, r15=0x%08" PRIX32, cpu->Cpsr, | ||||||
|         LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, |                   cpu->TFlag, cpu->Reg[15]); | ||||||
|                   cpu->Reg[15]); |  | ||||||
|         CITRA_IGNORE_EXIT(-1); |         CITRA_IGNORE_EXIT(-1); | ||||||
|     } |     } | ||||||
|     inst_base = arm_instruction_trans[idx](inst, idx); |     inst_base = arm_instruction_trans[idx](inst, idx); | ||||||
|  | |||||||
| @ -2,12 +2,12 @@ | |||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <cinttypes> | ||||||
| #include <map> | #include <map> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "common/symbols.h" |  | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/function_wrappers.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) { |                                u32 stack_top, s32 processor_id) { | ||||||
|     using Kernel::Thread; |     using Kernel::Thread; | ||||||
| 
 | 
 | ||||||
|     std::string name; |     std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point); | ||||||
|     if (Symbols::HasSymbol(entry_point)) { |  | ||||||
|         TSymbol symbol = Symbols::GetSymbol(entry_point); |  | ||||||
|         name = symbol.name; |  | ||||||
|     } else { |  | ||||||
|         name = Common::StringFromFormat("unknown-%08x", entry_point); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (priority > THREADPRIO_LOWEST) { |     if (priority > THREADPRIO_LOWEST) { | ||||||
|         return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, |         return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/symbols.h" |  | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/kernel/resource_limit.h" | #include "core/hle/kernel/resource_limit.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
| @ -210,7 +209,6 @@ public: | |||||||
|         return (u32)(header->e_flags); |         return (u32)(header->e_flags); | ||||||
|     } |     } | ||||||
|     SharedPtr<CodeSet> LoadInto(u32 vaddr); |     SharedPtr<CodeSet> LoadInto(u32 vaddr); | ||||||
|     bool LoadSymbols(); |  | ||||||
| 
 | 
 | ||||||
|     int GetNumSegments() const { |     int GetNumSegments() const { | ||||||
|         return (int)(header->e_phnum); |         return (int)(header->e_phnum); | ||||||
| @ -258,8 +256,6 @@ ElfReader::ElfReader(void* ptr) { | |||||||
|     sections = (Elf32_Shdr*)(base + header->e_shoff); |     sections = (Elf32_Shdr*)(base + header->e_shoff); | ||||||
| 
 | 
 | ||||||
|     entryPoint = header->e_entry; |     entryPoint = header->e_entry; | ||||||
| 
 |  | ||||||
|     LoadSymbols(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const char* ElfReader::GetSectionName(int section) const { | const char* ElfReader::GetSectionName(int section) const { | ||||||
| @ -362,34 +358,6 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const | |||||||
|     return -1; |     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
 | // Loader namespace
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei