mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
Merge pull request #5287 from sepalani/rso
Generate Symbols From RSO Modules added
This commit is contained in:
commit
4517231a1a
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
642
Source/Core/Core/Debugger/RSO.cpp
Normal file
642
Source/Core/Core/Debugger/RSO.cpp
Normal 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;
|
||||
}
|
282
Source/Core/Core/Debugger/RSO.h
Normal file
282
Source/Core/Core/Debugger/RSO.h
Normal 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;
|
||||
};
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user