diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 7d17cde612..82ab438e87 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -31,6 +31,7 @@ set(SRCS
Debugger/Debugger_SymbolMap.cpp
Debugger/Dump.cpp
Debugger/PPCDebugInterface.cpp
+ Debugger/RSO.cpp
DSP/DSPAssembler.cpp
DSP/DSPDisassembler.cpp
DSP/DSPAccelerator.cpp
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 23e6c0df6e..50f452c4a3 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -51,6 +51,7 @@
+
@@ -312,6 +313,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 26ecb08d06..e61dae56fa 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -209,6 +209,9 @@
Debugger
+
+ Debugger
+
DSPCore\Interpreter
@@ -928,6 +931,9 @@
Debugger
+
+ Debugger
+
DSPCore\Interpreter
diff --git a/Source/Core/Core/Debugger/RSO.cpp b/Source/Core/Core/Debugger/RSO.cpp
new file mode 100644
index 0000000000..bfab731032
--- /dev/null
+++ b/Source/Core/Core/Debugger/RSO.cpp
@@ -0,0 +1,642 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Core/Debugger/RSO.h"
+
+#include
+
+#include "Common/CommonFuncs.h"
+#include "Common/Logging/Log.h"
+#include "Core/PowerPC/PPCSymbolDB.h"
+#include "Core/PowerPC/PowerPC.h"
+
+void RSOHeaderView::Load(u32 address)
+{
+ m_address = address;
+ m_header.entry.next_entry = PowerPC::HostRead_U32(address);
+ m_header.entry.prev_entry = PowerPC::HostRead_U32(address + 0x04);
+ m_header.entry.section_count = PowerPC::HostRead_U32(address + 0x08);
+ m_header.entry.section_table_offset = PowerPC::HostRead_U32(address + 0xC);
+ m_header.entry.name_offset = PowerPC::HostRead_U32(address + 0x10);
+ m_header.entry.name_size = PowerPC::HostRead_U32(address + 0x14);
+ m_header.entry.version = PowerPC::HostRead_U32(address + 0x18);
+ m_header.entry.bss_size = PowerPC::HostRead_U32(address + 0x1C);
+ m_header.section_info.prolog_section_index = PowerPC::HostRead_U8(address + 0x20);
+ m_header.section_info.epilog_section_index = PowerPC::HostRead_U8(address + 0x21);
+ m_header.section_info.unresolved_section_index = PowerPC::HostRead_U8(address + 0x22);
+ m_header.section_info.bss_section_index = PowerPC::HostRead_U8(address + 0x23);
+ m_header.section_info.prolog_offset = PowerPC::HostRead_U32(address + 0x24);
+ m_header.section_info.epilog_offset = PowerPC::HostRead_U32(address + 0x28);
+ m_header.section_info.unresolved_offset = PowerPC::HostRead_U32(address + 0x2C);
+ m_header.relocation_tables.internals_offset = PowerPC::HostRead_U32(address + 0x30);
+ m_header.relocation_tables.internals_size = PowerPC::HostRead_U32(address + 0x34);
+ m_header.relocation_tables.externals_offset = PowerPC::HostRead_U32(address + 0x38);
+ m_header.relocation_tables.externals_size = PowerPC::HostRead_U32(address + 0x3C);
+ m_header.symbol_tables.exports_offset = PowerPC::HostRead_U32(address + 0x40);
+ m_header.symbol_tables.exports_size = PowerPC::HostRead_U32(address + 0x44);
+ m_header.symbol_tables.exports_name_table = PowerPC::HostRead_U32(address + 0x48);
+ m_header.symbol_tables.imports_offset = PowerPC::HostRead_U32(address + 0x4C);
+ m_header.symbol_tables.imports_size = PowerPC::HostRead_U32(address + 0x50);
+ m_header.symbol_tables.imports_name_table = PowerPC::HostRead_U32(address + 0x54);
+
+ // Prevent an invalid name going wild
+ if (m_header.entry.name_size < 0x100)
+ m_name = PowerPC::HostGetString(m_header.entry.name_offset, m_header.entry.name_size);
+ else
+ m_name = PowerPC::HostGetString(m_header.entry.name_offset, 0x100);
+}
+
+u32 RSOHeaderView::GetNextEntry() const
+{
+ return m_header.entry.next_entry;
+}
+
+u32 RSOHeaderView::GetPrevEntry() const
+{
+ return m_header.entry.prev_entry;
+}
+
+u32 RSOHeaderView::GetSectionCount() const
+{
+ return m_header.entry.section_count;
+}
+
+u32 RSOHeaderView::GetSectionTableOffset() const
+{
+ return m_header.entry.section_table_offset;
+}
+
+const std::string& RSOHeaderView::GetName() const
+{
+ return m_name;
+}
+
+u32 RSOHeaderView::GetVersion() const
+{
+ return m_header.entry.version;
+}
+
+u32 RSOHeaderView::GetBssSectionSize() const
+{
+ return m_header.entry.bss_size;
+}
+
+u32 RSOHeaderView::GetPrologSectionIndex() const
+{
+ return m_header.section_info.prolog_section_index;
+}
+
+u32 RSOHeaderView::GetEpilogSectionIndex() const
+{
+ return m_header.section_info.epilog_section_index;
+}
+
+u32 RSOHeaderView::GetUnresolvedSectionIndex() const
+{
+ return m_header.section_info.unresolved_section_index;
+}
+
+u32 RSOHeaderView::GetBssSectionIndex() const
+{
+ return m_header.section_info.bss_section_index;
+}
+
+u32 RSOHeaderView::GetPrologSectionOffset() const
+{
+ return m_header.section_info.prolog_offset;
+}
+
+u32 RSOHeaderView::GetEpilogSectionOffset() const
+{
+ return m_header.section_info.epilog_offset;
+}
+
+u32 RSOHeaderView::GetUnresolvedSectionOffset() const
+{
+ return m_header.section_info.unresolved_offset;
+}
+
+u32 RSOHeaderView::GetInternalsOffset() const
+{
+ return m_header.relocation_tables.internals_offset;
+}
+
+u32 RSOHeaderView::GetInternalsSize() const
+{
+ return m_header.relocation_tables.internals_size;
+}
+
+u32 RSOHeaderView::GetExternalsOffset() const
+{
+ return m_header.relocation_tables.externals_offset;
+}
+
+u32 RSOHeaderView::GetExternalsSize() const
+{
+ return m_header.relocation_tables.externals_size;
+}
+
+u32 RSOHeaderView::GetExportsOffset() const
+{
+ return m_header.symbol_tables.exports_offset;
+}
+
+u32 RSOHeaderView::GetExportsSize() const
+{
+ return m_header.symbol_tables.exports_size;
+}
+
+u32 RSOHeaderView::GetExportsNameTable() const
+{
+ return m_header.symbol_tables.exports_name_table;
+}
+
+u32 RSOHeaderView::GetImportsOffset() const
+{
+ return m_header.symbol_tables.imports_offset;
+}
+
+u32 RSOHeaderView::GetImportsSize() const
+{
+ return m_header.symbol_tables.imports_size;
+}
+
+u32 RSOHeaderView::GetImportsNameTable() const
+{
+ return m_header.symbol_tables.imports_name_table;
+}
+
+void RSOSectionsView::Load(u32 address, std::size_t count)
+{
+ m_address = address;
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ RSOSection section;
+ section.offset = PowerPC::HostRead_U32(address);
+ section.size = PowerPC::HostRead_U32(address + 4);
+ m_sections.emplace_back(std::move(section));
+ address += sizeof(RSOSection);
+ }
+}
+
+size_t RSOSectionsView::Count() const
+{
+ return m_sections.size();
+}
+
+const RSOSection& RSOSectionsView::GetSection(std::size_t index) const
+{
+ return m_sections.at(index);
+}
+
+const std::vector& RSOSectionsView::GetSections() const
+{
+ return m_sections;
+}
+
+void RSOImportsView::Load(u32 address, std::size_t count)
+{
+ m_address = address;
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ RSOImport rso_import;
+ rso_import.name_offset = PowerPC::HostRead_U32(address);
+ rso_import.code_offset = PowerPC::HostRead_U32(address + 4);
+ rso_import.entry_offset = PowerPC::HostRead_U32(address + 8);
+ m_imports.emplace_back(std::move(rso_import));
+ address += sizeof(RSOImport);
+ }
+}
+
+std::size_t RSOImportsView::Count() const
+{
+ return m_imports.size();
+}
+
+const RSOImport& RSOImportsView::GetImport(std::size_t index) const
+{
+ return m_imports.at(index);
+}
+
+const std::vector& RSOImportsView::GetImports() const
+{
+ return m_imports;
+}
+
+void RSOExportsView::Load(u32 address, std::size_t count)
+{
+ m_address = address;
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ RSOExport rso_export;
+ rso_export.name_offset = PowerPC::HostRead_U32(address);
+ rso_export.code_offset = PowerPC::HostRead_U32(address + 4);
+ rso_export.section_index = PowerPC::HostRead_U32(address + 8);
+ rso_export.hash = PowerPC::HostRead_U32(address + 12);
+ m_exports.emplace_back(std::move(rso_export));
+ address += sizeof(RSOExport);
+ }
+}
+
+std::size_t RSOExportsView::Count() const
+{
+ return m_exports.size();
+}
+
+const RSOExport& RSOExportsView::GetExport(std::size_t index) const
+{
+ return m_exports.at(index);
+}
+
+const std::vector& RSOExportsView::GetExports() const
+{
+ return m_exports;
+}
+
+void RSOInternalsView::Load(u32 address, std::size_t count)
+{
+ m_address = address;
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ RSOInternalsEntry entry;
+ entry.r_offset = PowerPC::HostRead_U32(address);
+ entry.r_info = PowerPC::HostRead_U32(address + 4);
+ entry.r_addend = PowerPC::HostRead_U32(address + 8);
+ m_entries.emplace_back(std::move(entry));
+ address += sizeof(RSOInternalsEntry);
+ }
+}
+
+std::size_t RSOInternalsView::Count() const
+{
+ return m_entries.size();
+}
+
+const RSOInternalsEntry& RSOInternalsView::GetEntry(std::size_t index) const
+{
+ return m_entries.at(index);
+}
+
+const std::vector& RSOInternalsView::GetEntries() const
+{
+ return m_entries;
+}
+
+void RSOExternalsView::Load(u32 address, std::size_t count)
+{
+ m_address = address;
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ RSOExternalsEntry entry;
+ entry.r_offset = PowerPC::HostRead_U32(address);
+ entry.r_info = PowerPC::HostRead_U32(address + 4);
+ entry.r_addend = PowerPC::HostRead_U32(address + 8);
+ m_entries.emplace_back(std::move(entry));
+ address += sizeof(RSOExternalsEntry);
+ }
+}
+
+std::size_t RSOExternalsView::Count() const
+{
+ return m_entries.size();
+}
+
+const RSOExternalsEntry& RSOExternalsView::GetEntry(std::size_t index) const
+{
+ return m_entries.at(index);
+}
+
+const std::vector& RSOExternalsView::GetEntries() const
+{
+ return m_entries;
+}
+
+void RSOView::LoadHeader(u32 address)
+{
+ m_address = address;
+ m_header.Load(address);
+}
+
+void RSOView::LoadSections()
+{
+ m_sections.Load(m_header.GetSectionTableOffset(), m_header.GetSectionCount());
+}
+
+void RSOView::LoadImports()
+{
+ std::size_t size = m_header.GetImportsSize();
+ if (size % sizeof(RSOImport) != 0)
+ WARN_LOG(OSHLE, "RSO Imports Table has an incoherent size (%08zx)", size);
+ m_imports.Load(m_header.GetImportsOffset(), size / sizeof(RSOImport));
+}
+
+void RSOView::LoadExports()
+{
+ std::size_t size = m_header.GetExportsSize();
+ if (size % sizeof(RSOExport) != 0)
+ WARN_LOG(OSHLE, "RSO Exports Table has an incoherent size (%08zx)", size);
+ m_exports.Load(m_header.GetExportsOffset(), size / sizeof(RSOExport));
+}
+
+void RSOView::LoadInternals()
+{
+ std::size_t size = m_header.GetInternalsSize();
+ if (size % sizeof(RSOInternalsEntry) != 0)
+ WARN_LOG(OSHLE, "RSO Internals Relocation Table has an incoherent size (%08zx)", size);
+ m_imports.Load(m_header.GetInternalsOffset(), size / sizeof(RSOInternalsEntry));
+}
+
+void RSOView::LoadExternals()
+{
+ std::size_t size = m_header.GetExternalsSize();
+ if (size % sizeof(RSOExternalsEntry) != 0)
+ WARN_LOG(OSHLE, "RSO Externals Relocation Table has an incoherent size (%08zx)", size);
+ m_imports.Load(m_header.GetExternalsOffset(), size / sizeof(RSOExternalsEntry));
+}
+
+void RSOView::LoadAll(u32 address)
+{
+ LoadHeader(address);
+ LoadSections();
+ LoadImports();
+ LoadExports();
+ LoadInternals();
+ LoadExternals();
+}
+
+void RSOView::Apply(PPCSymbolDB* symbol_db) const
+{
+ std::size_t count = 0;
+ for (const RSOExport& rso_export : GetExports())
+ {
+ u32 address = GetExportAddress(rso_export);
+ if (address != 0)
+ {
+ Symbol* symbol = symbol_db->AddFunction(address);
+ if (!symbol)
+ symbol = symbol_db->GetSymbolFromAddr(address);
+ if (symbol)
+ {
+ symbol->name = GetExportName(rso_export);
+ count += 1;
+ }
+ }
+ }
+ DEBUG_LOG(OSHLE, "RSO(%s): %zu/%zu symbols applied", GetName().c_str(), count, GetExportsCount());
+}
+
+u32 RSOView::GetNextEntry() const
+{
+ return m_header.GetNextEntry();
+}
+
+u32 RSOView::GetPrevEntry() const
+{
+ return m_header.GetPrevEntry();
+}
+
+u32 RSOView::GetVersion() const
+{
+ return m_header.GetVersion();
+}
+
+u32 RSOView::GetAddress() const
+{
+ return m_address;
+}
+
+std::size_t RSOView::GetSectionCount() const
+{
+ return m_sections.Count();
+}
+
+const RSOSection& RSOView::GetSection(std::size_t index) const
+{
+ return m_sections.GetSection(index);
+}
+
+const std::vector& RSOView::GetSections() const
+{
+ return m_sections.GetSections();
+}
+
+std::size_t RSOView::GetImportsCount() const
+{
+ return m_imports.Count();
+}
+
+const RSOImport& RSOView::GetImport(std::size_t index) const
+{
+ return m_imports.GetImport(index);
+}
+
+std::string RSOView::GetImportName(const RSOImport& rso_import) const
+{
+ return PowerPC::HostGetString(m_header.GetImportsNameTable() + rso_import.name_offset);
+}
+
+const std::vector& RSOView::GetImports() const
+{
+ return m_imports.GetImports();
+}
+
+std::size_t RSOView::GetExportsCount() const
+{
+ return m_exports.Count();
+}
+
+const RSOExport& RSOView::GetExport(std::size_t index) const
+{
+ return m_exports.GetExport(index);
+}
+
+std::string RSOView::GetExportName(const RSOExport& rso_export) const
+{
+ return PowerPC::HostGetString(m_header.GetExportsNameTable() + rso_export.name_offset);
+}
+
+u32 RSOView::GetExportAddress(const RSOExport& rso_export) const
+{
+ u32 address = 0;
+
+ if (rso_export.section_index < GetSectionCount())
+ address = GetSection(rso_export.section_index).offset + rso_export.code_offset;
+
+ return address;
+}
+
+const std::vector& RSOView::GetExports() const
+{
+ return m_exports.GetExports();
+}
+
+std::size_t RSOView::GetInternalsCount() const
+{
+ return m_internals.Count();
+}
+
+const RSOInternalsEntry& RSOView::GetInternalsEntry(std::size_t index) const
+{
+ return m_internals.GetEntry(index);
+}
+
+const std::vector& RSOView::GetInternals() const
+{
+ return m_internals.GetEntries();
+}
+
+std::size_t RSOView::GetExternalsCount() const
+{
+ return m_externals.Count();
+}
+
+const RSOExternalsEntry& RSOView::GetExternalsEntry(std::size_t index) const
+{
+ return m_externals.GetEntry(index);
+}
+
+const std::vector& RSOView::GetExternals() const
+{
+ return m_externals.GetEntries();
+}
+
+const std::string& RSOView::GetName() const
+{
+ return m_header.GetName();
+}
+
+std::string RSOView::GetName(const RSOImport& rso_import) const
+{
+ return GetImportName(rso_import);
+}
+
+std::string RSOView::GetName(const RSOExport& rso_export) const
+{
+ return GetExportName(rso_export);
+}
+
+u32 RSOView::GetProlog() const
+{
+ u32 section_index = m_header.GetPrologSectionIndex();
+ if (section_index == 0)
+ WARN_LOG(OSHLE, "RSO doesn't have a prolog function");
+ else if (section_index >= m_sections.Count())
+ WARN_LOG(OSHLE, "RSO prolog section index out of bound");
+ else
+ return GetSection(section_index).offset + m_header.GetPrologSectionOffset();
+ return 0;
+}
+
+u32 RSOView::GetEpilog() const
+{
+ u32 section_index = m_header.GetEpilogSectionIndex();
+ if (section_index == 0)
+ WARN_LOG(OSHLE, "RSO doesn't have an epilog function");
+ else if (section_index >= m_sections.Count())
+ WARN_LOG(OSHLE, "RSO epilog section index out of bound");
+ else
+ return GetSection(section_index).offset + m_header.GetEpilogSectionOffset();
+ return 0;
+}
+
+u32 RSOView::GetUnresolved() const
+{
+ u32 section_index = m_header.GetUnresolvedSectionIndex();
+ if (section_index == 0)
+ WARN_LOG(OSHLE, "RSO doesn't have a unresolved function");
+ else if (section_index >= m_sections.Count())
+ WARN_LOG(OSHLE, "RSO unresolved section index out of bound");
+ else
+ return GetSection(section_index).offset + m_header.GetUnresolvedSectionOffset();
+ return 0;
+}
+
+bool RSOChainView::Load(u32 address)
+{
+ // Load node
+ RSOView node;
+ node.LoadHeader(address);
+ DEBUG_LOG(OSHLE, "RSOChain node name: %s", node.GetName().c_str());
+ m_chain.emplace_front(std::move(node));
+
+ if (LoadNextChain(m_chain.front()) && LoadPrevChain(m_chain.front()))
+ {
+ for (RSOView& view : m_chain)
+ {
+ view.LoadSections();
+ view.LoadExports();
+ view.LoadImports();
+ view.LoadExternals();
+ view.LoadInternals();
+ }
+ return true;
+ }
+ return false;
+}
+
+void RSOChainView::Apply(PPCSymbolDB* symbol_db) const
+{
+ for (const RSOView& rso_view : m_chain)
+ rso_view.Apply(symbol_db);
+}
+
+void RSOChainView::Clear()
+{
+ m_chain.clear();
+}
+
+const std::list& RSOChainView::GetChain() const
+{
+ return m_chain;
+}
+
+bool RSOChainView::LoadNextChain(const RSOView& view)
+{
+ u32 prev_address = view.GetAddress();
+ u32 next_address = view.GetNextEntry();
+
+ while (next_address != 0)
+ {
+ RSOView next_node;
+ next_node.LoadHeader(next_address);
+
+ if (prev_address != next_node.GetPrevEntry())
+ {
+ ERROR_LOG(OSHLE, "RSOChain has an incoherent previous link %08x != %08x in %s", prev_address,
+ next_node.GetPrevEntry(), next_node.GetName().c_str());
+ return false;
+ }
+
+ prev_address = next_address;
+ next_address = next_node.GetNextEntry();
+ m_chain.emplace_back(std::move(next_node));
+ }
+
+ return true;
+}
+
+bool RSOChainView::LoadPrevChain(const RSOView& view)
+{
+ u32 prev_address = view.GetPrevEntry();
+ u32 next_address = view.GetAddress();
+
+ while (prev_address != 0)
+ {
+ RSOView prev_node;
+ prev_node.LoadHeader(prev_address);
+
+ if (next_address != prev_node.GetNextEntry())
+ {
+ ERROR_LOG(OSHLE, "RSOChain has an incoherent next link %08x != %08x in %s", next_address,
+ prev_node.GetNextEntry(), prev_node.GetName().c_str());
+ return false;
+ }
+
+ next_address = prev_address;
+ prev_address = prev_node.GetPrevEntry();
+ m_chain.emplace_front(std::move(prev_node));
+ }
+
+ return true;
+}
diff --git a/Source/Core/Core/Debugger/RSO.h b/Source/Core/Core/Debugger/RSO.h
new file mode 100644
index 0000000000..4b9bebacf0
--- /dev/null
+++ b/Source/Core/Core/Debugger/RSO.h
@@ -0,0 +1,282 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "Common/CommonTypes.h"
+
+class PPCSymbolDB;
+
+struct RSOEntry
+{
+ u32 next_entry;
+ u32 prev_entry;
+ u32 section_count;
+ u32 section_table_offset;
+ u32 name_offset;
+ u32 name_size;
+ u32 version;
+ u32 bss_size;
+};
+
+struct RSOSectionInfo
+{
+ u8 prolog_section_index;
+ u8 epilog_section_index;
+ u8 unresolved_section_index;
+ u8 bss_section_index;
+ u32 prolog_offset;
+ u32 epilog_offset;
+ u32 unresolved_offset;
+};
+
+struct RSORelocationTables
+{
+ u32 internals_offset;
+ u32 internals_size;
+ u32 externals_offset;
+ u32 externals_size;
+};
+
+struct RSOSymbolTables
+{
+ u32 exports_offset;
+ u32 exports_size;
+ u32 exports_name_table;
+ u32 imports_offset;
+ u32 imports_size;
+ u32 imports_name_table;
+};
+
+struct RSOHeader
+{
+ RSOEntry entry;
+ RSOSectionInfo section_info;
+ RSORelocationTables relocation_tables;
+ RSOSymbolTables symbol_tables;
+};
+
+struct RSOSection
+{
+ u32 offset;
+ u32 size;
+};
+
+struct RSOImport
+{
+ u32 name_offset;
+ u32 code_offset;
+ u32 entry_offset;
+};
+
+struct RSOExport
+{
+ u32 name_offset;
+ u32 code_offset;
+ u32 section_index;
+ u32 hash;
+};
+
+enum class RSORelocationTableType
+{
+ Internals,
+ Externals
+};
+
+template
+struct RSORelocationTableEntry
+{
+ u32 r_offset;
+ u32 r_info;
+ u32 r_addend;
+};
+
+using RSOInternalsEntry = RSORelocationTableEntry;
+using RSOExternalsEntry = RSORelocationTableEntry;
+
+class RSOHeaderView
+{
+public:
+ void Load(u32 address);
+
+ u32 GetNextEntry() const;
+ u32 GetPrevEntry() const;
+ u32 GetSectionCount() const;
+ u32 GetSectionTableOffset() const;
+ const std::string& GetName() const;
+ u32 GetVersion() const;
+ u32 GetBssSectionSize() const;
+ u32 GetPrologSectionIndex() const;
+ u32 GetEpilogSectionIndex() const;
+ u32 GetUnresolvedSectionIndex() const;
+ u32 GetBssSectionIndex() const;
+ u32 GetPrologSectionOffset() const;
+ u32 GetEpilogSectionOffset() const;
+ u32 GetUnresolvedSectionOffset() const;
+ u32 GetInternalsOffset() const;
+ u32 GetInternalsSize() const;
+ u32 GetExternalsOffset() const;
+ u32 GetExternalsSize() const;
+ u32 GetExportsOffset() const;
+ u32 GetExportsSize() const;
+ u32 GetExportsNameTable() const;
+ u32 GetImportsOffset() const;
+ u32 GetImportsSize() const;
+ u32 GetImportsNameTable() const;
+
+private:
+ RSOHeader m_header;
+ std::string m_name;
+ u32 m_address = 0;
+};
+
+class RSOSectionsView
+{
+public:
+ void Load(u32 address, std::size_t count = 1);
+ std::size_t Count() const;
+
+ const RSOSection& GetSection(std::size_t index) const;
+ const std::vector& GetSections() const;
+
+private:
+ std::vector m_sections;
+ u32 m_address = 0;
+};
+
+class RSOImportsView
+{
+public:
+ void Load(u32 address, std::size_t count = 1);
+ std::size_t Count() const;
+
+ const RSOImport& GetImport(std::size_t index) const;
+ const std::vector& GetImports() const;
+
+private:
+ std::vector m_imports;
+ u32 m_address = 0;
+};
+
+class RSOExportsView
+{
+public:
+ void Load(u32 address, std::size_t count = 1);
+ std::size_t Count() const;
+
+ const RSOExport& GetExport(std::size_t index) const;
+ const std::vector& GetExports() const;
+
+private:
+ std::vector m_exports;
+ u32 m_address = 0;
+};
+
+class RSOInternalsView
+{
+public:
+ void Load(u32 address, std::size_t count = 1);
+ std::size_t Count() const;
+
+ const RSOInternalsEntry& GetEntry(std::size_t index) const;
+ const std::vector& GetEntries() const;
+
+private:
+ std::vector m_entries;
+ u32 m_address = 0;
+};
+
+class RSOExternalsView
+{
+public:
+ void Load(u32 address, std::size_t count = 1);
+ std::size_t Count() const;
+
+ const RSOExternalsEntry& GetEntry(std::size_t index) const;
+ const std::vector& GetEntries() const;
+
+private:
+ std::vector m_entries;
+ u32 m_address = 0;
+};
+
+class RSOView
+{
+public:
+ void LoadHeader(u32 address);
+ void LoadSections();
+ void LoadImports();
+ void LoadExports();
+ void LoadInternals();
+ void LoadExternals();
+ void LoadAll(u32 address);
+
+ void Apply(PPCSymbolDB* symbol_db) const;
+
+ u32 GetNextEntry() const;
+ u32 GetPrevEntry() const;
+ u32 GetVersion() const;
+ u32 GetAddress() const;
+
+ std::size_t GetSectionCount() const;
+ const RSOSection& GetSection(std::size_t index) const;
+ const std::vector& GetSections() const;
+
+ std::size_t GetImportsCount() const;
+ const RSOImport& GetImport(std::size_t index) const;
+ std::string GetImportName(const RSOImport& rso_import) const;
+ const std::vector& GetImports() const;
+
+ std::size_t GetExportsCount() const;
+ const RSOExport& GetExport(std::size_t index) const;
+ std::string GetExportName(const RSOExport& rso_export) const;
+ u32 GetExportAddress(const RSOExport& rso_export) const;
+ const std::vector& GetExports() const;
+
+ std::size_t GetInternalsCount() const;
+ const RSOInternalsEntry& GetInternalsEntry(std::size_t index) const;
+ const std::vector& GetInternals() const;
+
+ std::size_t GetExternalsCount() const;
+ const RSOExternalsEntry& GetExternalsEntry(std::size_t index) const;
+ const std::vector& GetExternals() const;
+
+ const std::string& GetName() const;
+ std::string GetName(const RSOImport& rso_import) const;
+ std::string GetName(const RSOExport& rso_export) const;
+
+ u32 GetProlog() const;
+ u32 GetEpilog() const;
+ u32 GetUnresolved() const;
+
+private:
+ RSOHeaderView m_header;
+ RSOSectionsView m_sections;
+ RSOImportsView m_imports;
+ RSOExportsView m_exports;
+ RSOInternalsView m_internals;
+ RSOExternalsView m_externals;
+ u32 m_address = 0;
+};
+
+class RSOChainView
+{
+public:
+ bool Load(u32 address);
+ void Apply(PPCSymbolDB* symbol_db) const;
+ void Clear();
+ const std::list& GetChain() const;
+
+private:
+ bool LoadNextChain(const RSOView& view);
+ bool LoadPrevChain(const RSOView& view);
+
+ std::list m_chain;
+};
diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
index df287220df..f271c8a979 100644
--- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
+++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
@@ -3,8 +3,10 @@
// Refer to the license.txt file included.
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -29,6 +31,7 @@
#include "Core/Boot/Boot.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
+#include "Core/Debugger/RSO.h"
#include "Core/HLE/HLE.h"
#include "Core/Host.h"
#include "Core/PowerPC/JitInterface.h"
@@ -202,6 +205,35 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
NotifyMapLoaded();
break;
}
+ case IDM_SCAN_RSO:
+ {
+ wxTextEntryDialog dialog(this, _("Enter the RSO module address:"));
+ if (dialog.ShowModal() == wxID_OK)
+ {
+ unsigned long address;
+ if (dialog.GetValue().ToULong(&address, 0) && address <= std::numeric_limits::max())
+ {
+ RSOChainView rso_chain;
+ if (rso_chain.Load(static_cast(address)))
+ {
+ rso_chain.Apply(&g_symbolDB);
+ // Update GUI
+ NotifyMapLoaded();
+ }
+ else
+ {
+ Parent->StatusBarMessage("Failed to load RSO module at %s",
+ dialog.GetValue().ToStdString().c_str());
+ }
+ }
+ else
+ {
+ Parent->StatusBarMessage("Invalid RSO module address: %s",
+ dialog.GetValue().ToStdString().c_str());
+ }
+ }
+ break;
+ }
case IDM_LOAD_MAP_FILE:
if (!map_exists)
{
diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp
index e3f268f426..1d20777e07 100644
--- a/Source/Core/DolphinWX/FrameTools.cpp
+++ b/Source/Core/DolphinWX/FrameTools.cpp
@@ -232,6 +232,7 @@ void CFrame::BindDebuggerMenuBarUpdateEvents()
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_CLEAR_SYMBOLS);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_SCAN_FUNCTIONS);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_SCAN_SIGNATURES);
+ Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_SCAN_RSO);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_LOAD_MAP_FILE);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_SAVEMAPFILE);
Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreInitialized, IDM_LOAD_MAP_FILE_AS);
diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h
index 8465d091c3..ebbc2123d7 100644
--- a/Source/Core/DolphinWX/Globals.h
+++ b/Source/Core/DolphinWX/Globals.h
@@ -217,6 +217,7 @@ enum
IDM_CLEAR_SYMBOLS,
IDM_SCAN_FUNCTIONS,
IDM_SCAN_SIGNATURES,
+ IDM_SCAN_RSO,
IDM_LOAD_MAP_FILE,
IDM_LOAD_MAP_FILE_AS,
IDM_LOAD_BAD_MAP_FILE,
diff --git a/Source/Core/DolphinWX/MainMenuBar.cpp b/Source/Core/DolphinWX/MainMenuBar.cpp
index 3dc8736d14..765a9dca14 100644
--- a/Source/Core/DolphinWX/MainMenuBar.cpp
+++ b/Source/Core/DolphinWX/MainMenuBar.cpp
@@ -423,6 +423,8 @@ wxMenu* MainMenuBar::CreateSymbolsMenu() const
IDM_SCAN_SIGNATURES, _("&Signature Database"),
_("Recognise standard functions from Sys/totaldb.dsy, and use generic zz_ "
"names for other functions."));
+ generate_symbols_menu->Append(IDM_SCAN_RSO, _("&RSO Modules"),
+ _("Find functions based on RSO modules (experimental)..."));
symbols_menu->AppendSubMenu(generate_symbols_menu, _("&Generate Symbols From"));
symbols_menu->AppendSeparator();
symbols_menu->Append(IDM_LOAD_MAP_FILE, _("&Load Symbol Map"),