From 428032bc0803a36c7a9dac33b93e79b94772a69b Mon Sep 17 00:00:00 2001 From: Amber Brault Date: Fri, 18 Oct 2024 13:20:03 -0400 Subject: [PATCH] Core: Store object name separately for symbols --- Source/Core/Common/SymbolDB.h | 1 + Source/Core/Core/Boot/Boot.cpp | 8 ++- 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 | 3 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 52 ++++++++++++++++--- Source/Core/Core/PowerPC/PPCSymbolDB.h | 2 +- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 16 ++++-- 10 files changed, 77 insertions(+), 19 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 d84df0a8dbf7..35cbfb3c3e0c 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -377,8 +377,12 @@ bool CBoot::LoadMapFromFilename(const Core::CPUThreadGuard& guard, PPCSymbolDB& { std::string strMapFilename; bool found = FindMapFile(&strMapFilename, nullptr); + auto start = std::chrono::high_resolution_clock::now(); if (found && ppc_symbol_db.LoadMap(guard, strMapFilename)) { + auto finish = std::chrono::high_resolution_clock::now(); + auto microsecs = std::chrono::duration_cast(finish - start); + NOTICE_LOG_FMT(BOOT, "Loading map took {} us\n", microsecs.count()); Host_PPCSymbolsChanged(); return true; } @@ -596,7 +600,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..8b971463a143 100644 --- a/Source/Core/Core/Debugger/RSO.cpp +++ b/Source/Core/Core/Debugger/RSO.cpp @@ -393,7 +393,8 @@ void RSOView::Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) c else { // Data symbol - symbol_db->AddKnownSymbol(guard, address, 0, export_name, Common::Symbol::Type::Data); + symbol_db->AddKnownSymbol(guard, address, 0, export_name, GetName(), + Common::Symbol::Type::Data); } } } diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index cccf98a62986..7ecab24c879b 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -5,7 +5,9 @@ #include #include +#include #include +#include #include #include #include @@ -49,7 +51,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 +60,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 +69,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 +404,31 @@ 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::string processed_name = TabsToSpaces(0, name); // Remove tabs + std::vector parts = SplitString(processed_name, ' '); + size_t num_parts = parts.size(); + + std::string object_filename_string = ""; + std::string name_string = name; //Default to the full line + + if (num_parts > 0) + { + // If the first part does not contain a left bracket (not a demangled symbol), use the first + // part + if (!parts[0].contains('(')) + { + name_string = parts[0]; + } + + // If the last part contains a ., it has to be the object name + if (parts[num_parts - 1].contains('.')) + { + object_filename_string = parts[num_parts - 1]; + } + } + // Check if this is a valid entry. if (strlen(name) > 0) { @@ -435,7 +465,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 +503,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:08x} {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(" {0}", symbol->object_name); + line += "\n"; + f.WriteString(line); } // Write .data section @@ -482,8 +517,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:08x} {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(" {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..45d0b0443892 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 += fmt::format(" ({})", symbol.second.object_name); + } + auto* item = new QListWidgetItem(name); if (name == selection) item->setSelected(true); @@ -403,9 +409,9 @@ void CodeWidget::UpdateFunctionCalls(const Common::Symbol* symbol) if (call_symbol) { - const QString name = - QString::fromStdString(fmt::format("> {} ({:08x})", call_symbol->name, addr)); - + const QString name = QString::fromStdString(fmt::format("> {} ({}{:08x})", call_symbol->name, + !call_symbol->object_name.empty() ? fmt::format("{}, ", call_symbol->object_name) : "", + addr)); if (!name.contains(filter, Qt::CaseInsensitive)) continue; @@ -428,8 +434,8 @@ void CodeWidget::UpdateFunctionCallers(const Common::Symbol* symbol) if (caller_symbol) { - const QString name = - QString::fromStdString(fmt::format("< {} ({:08x})", caller_symbol->name, addr)); + const QString name = QString::fromStdString(fmt::format("< {} ({}{:08x})", caller_symbol->name, + !caller_symbol->object_name.empty() ? fmt::format("{}, ", caller_symbol->object_name) : "", addr)); if (!name.contains(filter, Qt::CaseInsensitive)) continue;