Generate Symbols From RSO Modules added

This commit is contained in:
Sepalani 2017-03-28 01:58:22 +01:00
parent e0c489d80c
commit 694b10da11
9 changed files with 969 additions and 0 deletions

View File

@ -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

View File

@ -51,6 +51,7 @@
<ClCompile Include="Debugger\Debugger_SymbolMap.cpp" />
<ClCompile Include="Debugger\Dump.cpp" />
<ClCompile Include="Debugger\PPCDebugInterface.cpp" />
<ClCompile Include="Debugger\RSO.cpp" />
<ClCompile Include="DSPEmulator.cpp" />
<ClCompile Include="DSP\DSPAssembler.cpp" />
<ClCompile Include="DSP\DSPDisassembler.cpp" />
@ -312,6 +313,7 @@
<ClInclude Include="Debugger\Dump.h" />
<ClInclude Include="Debugger\GCELF.h" />
<ClInclude Include="Debugger\PPCDebugInterface.h" />
<ClInclude Include="Debugger\RSO.h" />
<ClInclude Include="DSPEmulator.h" />
<ClInclude Include="DSP\DSPAssembler.h" />
<ClInclude Include="DSP\DSPDisassembler.h" />

View File

@ -209,6 +209,9 @@
<ClCompile Include="Debugger\PPCDebugInterface.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="Debugger\RSO.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="DSP\Interpreter\DSPIntArithmetic.cpp">
<Filter>DSPCore\Interpreter</Filter>
</ClCompile>
@ -928,6 +931,9 @@
<ClInclude Include="Debugger\PPCDebugInterface.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="Debugger\RSO.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="DSP\Interpreter\DSPIntCCUtil.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>

View File

@ -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 <utility>
#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<RSOSection>& 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<RSOImport>& 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<RSOExport>& 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<RSOInternalsEntry>& 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<RSOExternalsEntry>& 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<RSOSection>& 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<RSOImport>& 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<RSOExport>& 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<RSOInternalsEntry>& 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<RSOExternalsEntry>& 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<RSOView>& 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;
}

View File

@ -0,0 +1,282 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <cstddef>
#include <list>
#include <string>
#include <vector>
#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 <RSORelocationTableType Disambiguate>
struct RSORelocationTableEntry
{
u32 r_offset;
u32 r_info;
u32 r_addend;
};
using RSOInternalsEntry = RSORelocationTableEntry<RSORelocationTableType::Internals>;
using RSOExternalsEntry = RSORelocationTableEntry<RSORelocationTableType::Externals>;
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<RSOSection>& GetSections() const;
private:
std::vector<RSOSection> 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<RSOImport>& GetImports() const;
private:
std::vector<RSOImport> 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<RSOExport>& GetExports() const;
private:
std::vector<RSOExport> 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<RSOInternalsEntry>& GetEntries() const;
private:
std::vector<RSOInternalsEntry> 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<RSOExternalsEntry>& GetEntries() const;
private:
std::vector<RSOExternalsEntry> 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<RSOSection>& 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<RSOImport>& 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<RSOExport>& GetExports() const;
std::size_t GetInternalsCount() const;
const RSOInternalsEntry& GetInternalsEntry(std::size_t index) const;
const std::vector<RSOInternalsEntry>& GetInternals() const;
std::size_t GetExternalsCount() const;
const RSOExternalsEntry& GetExternalsEntry(std::size_t index) const;
const std::vector<RSOExternalsEntry>& 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<RSOView>& GetChain() const;
private:
bool LoadNextChain(const RSOView& view);
bool LoadPrevChain(const RSOView& view);
std::list<RSOView> m_chain;
};

View File

@ -3,8 +3,10 @@
// Refer to the license.txt file included.
#include <cstddef>
#include <cstdlib>
#include <fstream>
#include <istream>
#include <limits>
#include <sstream>
#include <string>
#include <utility>
@ -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<u32>::max())
{
RSOChainView rso_chain;
if (rso_chain.Load(static_cast<u32>(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)
{

View File

@ -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);

View File

@ -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,

View File

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