From 225481ac5e3727739a516cd9826dd7549835f2e1 Mon Sep 17 00:00:00 2001 From: Amber Brault Date: Thu, 24 Oct 2024 15:27:45 -0400 Subject: [PATCH] Core: Store object name separately for symbols --- Source/Core/Common/SymbolDB.h | 1 + Source/Core/Core/Boot/Boot.cpp | 4 +- Source/Core/Core/Boot/Boot.h | 3 +- Source/Core/Core/Boot/DolReader.h | 3 +- Source/Core/Core/Boot/ElfReader.cpp | 5 ++- Source/Core/Core/Boot/ElfReader.h | 3 +- Source/Core/Core/Debugger/RSO.cpp | 7 ++- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 45 ++++++++++++++++--- Source/Core/Core/PowerPC/PPCSymbolDB.h | 2 +- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 25 ++++++++--- 10 files changed, 77 insertions(+), 21 deletions(-) diff --git a/Source/Core/Common/SymbolDB.h b/Source/Core/Common/SymbolDB.h index 024255ef18ba..255994b3c228 100644 --- a/Source/Core/Common/SymbolDB.h +++ b/Source/Core/Common/SymbolDB.h @@ -44,6 +44,7 @@ struct Symbol std::string name; std::string function_name; // stripped function name + std::string object_name; // name of object/source file symbol belongs to std::vector callers; // addresses of functions that call this function std::vector calls; // addresses of functions that are called by this function u32 hash = 0; // use for HLE function finding diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 322a4f5be291..5fbef37d428d 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -605,7 +605,9 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard, ppc_state.pc = executable.reader->GetEntryPoint(); - if (executable.reader->LoadSymbols(guard, system.GetPPCSymbolDB())) + std::string filename = PathToFileName(executable.path); + + if (executable.reader->LoadSymbols(guard, system.GetPPCSymbolDB(), filename)) { Host_PPCSymbolsChanged(); HLE::PatchFunctions(system); diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index ca27e4696308..100f1cfdfd5e 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -215,7 +215,8 @@ class BootExecutableReader virtual bool IsValid() const = 0; virtual bool IsWii() const = 0; virtual bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const = 0; - virtual bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const = 0; + virtual bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db, + const std::string& filename) const = 0; protected: std::vector m_bytes; diff --git a/Source/Core/Core/Boot/DolReader.h b/Source/Core/Core/Boot/DolReader.h index 0c04d67b5d00..1ff37e352e0c 100644 --- a/Source/Core/Core/Boot/DolReader.h +++ b/Source/Core/Core/Boot/DolReader.h @@ -27,7 +27,8 @@ class DolReader final : public BootExecutableReader bool IsAncast() const { return m_is_ancast; } u32 GetEntryPoint() const override { return m_dolheader.entryPoint; } bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const override; - bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const override + bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db, + const std::string& filename) const override { return false; } diff --git a/Source/Core/Core/Boot/ElfReader.cpp b/Source/Core/Core/Boot/ElfReader.cpp index 2fc428399a41..f667387ab3cd 100644 --- a/Source/Core/Core/Boot/ElfReader.cpp +++ b/Source/Core/Core/Boot/ElfReader.cpp @@ -180,7 +180,8 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const return -1; } -bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const +bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db, + const std::string& filename) const { bool hasSymbols = false; SectionID sec = GetSectionByName(".symtab"); @@ -218,7 +219,7 @@ bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_ default: continue; } - ppc_symbol_db.AddKnownSymbol(guard, value, size, name, symtype); + ppc_symbol_db.AddKnownSymbol(guard, value, size, name, filename, symtype); hasSymbols = true; } } diff --git a/Source/Core/Core/Boot/ElfReader.h b/Source/Core/Core/Boot/ElfReader.h index 4213bd10903d..8ca84b54bb38 100644 --- a/Source/Core/Core/Boot/ElfReader.h +++ b/Source/Core/Core/Boot/ElfReader.h @@ -36,7 +36,8 @@ class ElfReader final : public BootExecutableReader u32 GetEntryPoint() const override { return entryPoint; } u32 GetFlags() const { return (u32)(header->e_flags); } bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const override; - bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const override; + bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db, + const std::string& filename) const override; // TODO: actually check for validity. bool IsValid() const override { return true; } bool IsWii() const override; diff --git a/Source/Core/Core/Debugger/RSO.cpp b/Source/Core/Core/Debugger/RSO.cpp index 71070f21a93d..f793096967d8 100644 --- a/Source/Core/Core/Debugger/RSO.cpp +++ b/Source/Core/Core/Debugger/RSO.cpp @@ -375,6 +375,7 @@ void RSOView::LoadAll(const Core::CPUThreadGuard& guard, u32 address) void RSOView::Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) const { + const std::string rso_name = GetName(); for (const RSOExport& rso_export : GetExports()) { u32 address = GetExportAddress(rso_export); @@ -389,15 +390,17 @@ void RSOView::Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) c { // Function symbol symbol->Rename(export_name); + symbol->object_name = rso_name; } else { // Data symbol - symbol_db->AddKnownSymbol(guard, address, 0, export_name, Common::Symbol::Type::Data); + symbol_db->AddKnownSymbol(guard, address, 0, export_name, rso_name, + Common::Symbol::Type::Data); } } } - DEBUG_LOG_FMT(SYMBOLS, "RSO({}): {} symbols applied", GetName(), GetExportsCount()); + DEBUG_LOG_FMT(SYMBOLS, "RSO({}): {} symbols applied", rso_name, GetExportsCount()); } u32 RSOView::GetNextEntry() const diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index cccf98a62986..6cd192ab0e2c 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -49,7 +49,8 @@ Common::Symbol* PPCSymbolDB::AddFunction(const Core::CPUThreadGuard& guard, u32 } void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAddr, u32 size, - const std::string& name, Common::Symbol::Type type) + const std::string& name, const std::string& object_name, + Common::Symbol::Type type) { auto iter = m_functions.find(startAddr); if (iter != m_functions.end()) @@ -57,6 +58,7 @@ void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAdd // already got it, let's just update name, checksum & size to be sure. Common::Symbol* tempfunc = &iter->second; tempfunc->Rename(name); + tempfunc->object_name = object_name; tempfunc->hash = HashSignatureDB::ComputeCodeChecksum(guard, startAddr, startAddr + size - 4); tempfunc->type = type; tempfunc->size = size; @@ -65,6 +67,7 @@ void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAdd { // new symbol. run analyze. auto& new_symbol = m_functions.emplace(startAddr, name).first->second; + new_symbol.object_name = object_name; new_symbol.type = type; new_symbol.address = startAddr; @@ -399,6 +402,26 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string& if (name[strlen(name) - 1] == '\r') name[strlen(name) - 1] = 0; + // Split the current name string into separate parts, and get the object name + // if it exists. + std::vector parts = SplitString(name, '\t'); + size_t num_parts = parts.size(); + + std::string object_filename_string = ""; + std::string name_string = std::string(StripWhitespace(parts[0])); + + if (num_parts > 1) + { + std::vector info_parts = SplitString(parts[1], ' '); + size_t num_info_parts = info_parts.size(); + + // If the last part contains a ., it has to be the object name + if (info_parts[num_info_parts - 1].find('.') != std::string::npos) + { + object_filename_string = info_parts[num_info_parts - 1]; + } + } + // Check if this is a valid entry. if (strlen(name) > 0) { @@ -435,7 +458,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string& if (good) { ++good_count; - AddKnownSymbol(guard, vaddress, size, name, type); + AddKnownSymbol(guard, vaddress, size, name_string, object_filename_string, type); } else { @@ -473,8 +496,13 @@ bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const for (const auto& symbol : function_symbols) { // Write symbol address, size, virtual address, alignment, name - f.WriteString(fmt::format("{0:08x} {1:08x} {2:08x} {3} {4}\n", symbol->address, symbol->size, - symbol->address, 0, symbol->name)); + std::string line = fmt::format(" {0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, + symbol->size, symbol->address, 0, symbol->name); + // Also write the object name if it exists + if (!symbol->object_name.empty()) + line += fmt::format(" \t{0}", symbol->object_name); + line += "\n"; + f.WriteString(line); } // Write .data section @@ -482,8 +510,13 @@ bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const for (const auto& symbol : data_symbols) { // Write symbol address, size, virtual address, alignment, name - f.WriteString(fmt::format("{0:08x} {1:08x} {2:08x} {3} {4}\n", symbol->address, symbol->size, - symbol->address, 0, symbol->name)); + std::string line = fmt::format(" {0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, + symbol->size, symbol->address, 0, symbol->name); + // Also write the object name if it exists + if (!symbol->object_name.empty()) + line += fmt::format(" \t{0}", symbol->object_name); + line += "\n"; + f.WriteString(line); } return true; diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.h b/Source/Core/Core/PowerPC/PPCSymbolDB.h index 13abc4489e20..de3e2103272b 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.h +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.h @@ -23,7 +23,7 @@ class PPCSymbolDB : public Common::SymbolDB Common::Symbol* AddFunction(const Core::CPUThreadGuard& guard, u32 start_addr) override; void AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAddr, u32 size, - const std::string& name, + const std::string& name, const std::string& object_name, Common::Symbol::Type type = Common::Symbol::Type::Function); Common::Symbol* GetSymbolFromAddr(u32 addr) override; diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index 681f14286cf0..0baa6aa8b4fc 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -374,6 +374,12 @@ void CodeWidget::UpdateSymbols() { QString name = QString::fromStdString(symbol.second.name); + // If the symbol has an object name, add it to the entry name. + if (!symbol.second.object_name.empty()) + { + name += QString::fromStdString(fmt::format(" ({})", symbol.second.object_name)); + } + auto* item = new QListWidgetItem(name); if (name == selection) item->setSelected(true); @@ -403,11 +409,13 @@ void CodeWidget::UpdateFunctionCalls(const Common::Symbol* symbol) if (call_symbol) { - const QString name = - QString::fromStdString(fmt::format("> {} ({:08x})", call_symbol->name, addr)); + QString name; - if (!name.contains(filter, Qt::CaseInsensitive)) - continue; + if (!call_symbol->object_name.empty()) + name = QString::fromStdString( + fmt::format("< {} ({}, {:08x})", call_symbol->name, call_symbol->object_name, addr)); + else + name = QString::fromStdString(fmt::format("< {} ({:08x})", call_symbol->name, addr)); auto* item = new QListWidgetItem(name); item->setData(Qt::UserRole, addr); @@ -428,8 +436,13 @@ void CodeWidget::UpdateFunctionCallers(const Common::Symbol* symbol) if (caller_symbol) { - const QString name = - QString::fromStdString(fmt::format("< {} ({:08x})", caller_symbol->name, addr)); + QString name; + + if (!caller_symbol->object_name.empty()) + name = QString::fromStdString(fmt::format("< {} ({}, {:08x})", caller_symbol->name, + caller_symbol->object_name, addr)); + else + name = QString::fromStdString(fmt::format("< {} ({:08x})", caller_symbol->name, addr)); if (!name.contains(filter, Qt::CaseInsensitive)) continue;