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"),