- Fix formatting

- delete CreateResolver/DestroySymbolResolver
This commit is contained in:
Tiago Rodrigues 2023-11-18 15:05:43 -05:00 committed by trodrigues
parent 687d681764
commit 5c0513931a
5 changed files with 73 additions and 119 deletions

View File

@ -11,7 +11,7 @@
#include "OfflineSymbolResolver.h" #include "OfflineSymbolResolver.h"
bool ApplyPathSubstitutions(std::string& path, const PathSubstitutionList& pathSubstituionlist) bool ApplyPathSubstitutions( std::string& path, const PathSubstitutionList& pathSubstituionlist )
{ {
for( const auto& substituion : pathSubstituionlist ) for( const auto& substituion : pathSubstituionlist )
{ {
@ -24,21 +24,15 @@ bool ApplyPathSubstitutions(std::string& path, const PathSubstitutionList& pathS
return false; return false;
} }
// TODO: use string hash map to reduce duplication or use some worker string internal hashing tracy::StringIdx AddSymbolString( tracy::Worker& worker, const std::string& str )
tracy::StringIdx AddSymbolString(tracy::Worker& worker, const char* str)
{ {
uint32_t newStringIdx = worker.AddNewString( str ); // TODO: use string hash map to reduce potential string duplication?
return tracy::StringIdx( newStringIdx ); tracy::StringLocation location = worker.StoreString( str.c_str(), str.length() );
return tracy::StringIdx( location.idx );
} }
bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker, bool PatchSymbols( tracy::Worker& worker, const PathSubstitutionList& pathSubstituionlist, bool verbose )
const PathSubstitutionList& pathSubstituionlist, bool verbose)
{ {
if( !resolver )
{
return false;
}
uint64_t callstackFrameCount = worker.GetCallstackFrameCount(); uint64_t callstackFrameCount = worker.GetCallstackFrameCount();
std::string relativeSoNameMatch = "[unresolved]"; std::string relativeSoNameMatch = "[unresolved]";
@ -89,21 +83,19 @@ bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker,
std::string imagePath = worker.GetString( imageIdx ); std::string imagePath = worker.GetString( imageIdx );
FrameEntryList& entries = imageIt->second; FrameEntryList& entries = imageIt->second;
if (!entries.size())
{ if( !entries.size() ) continue;
continue;
}
std::cout << "Resolving " << entries.size() << " symbols for image: '" std::cout << "Resolving " << entries.size() << " symbols for image: '"
<< imagePath << "'" << std::endl; << imagePath << "'" << std::endl;
const bool substituted = ApplyPathSubstitutions(imagePath, pathSubstituionlist); const bool substituted = ApplyPathSubstitutions( imagePath, pathSubstituionlist );
if (substituted) if( substituted )
{ {
std::cout << "\tPath substituted to: '" << imagePath << "'" << std::endl; std::cout << "\tPath substituted to: '" << imagePath << "'" << std::endl;
} }
SymbolEntryList resolvedEntries; SymbolEntryList resolvedEntries;
ResolveSymbols( resolver, imagePath, entries, resolvedEntries ); ResolveSymbols( imagePath, entries, resolvedEntries );
if( resolvedEntries.size() != entries.size() ) if( resolvedEntries.size() != entries.size() )
{ {
@ -119,10 +111,8 @@ bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker,
const SymbolEntry& symbolEntry = resolvedEntries[i]; const SymbolEntry& symbolEntry = resolvedEntries[i];
tracy::CallstackFrame& frame = *frameEntry.frame; tracy::CallstackFrame& frame = *frameEntry.frame;
if (!symbolEntry.name.length())
{ if( !symbolEntry.name.length() ) continue;
continue;
}
if( verbose ) if( verbose )
{ {
@ -131,12 +121,12 @@ bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker,
<< "' -> '" << symbolEntry.name << "'" << std::endl; << "' -> '" << symbolEntry.name << "'" << std::endl;
} }
frame.name = AddSymbolString( worker, symbolEntry.name.c_str() ); frame.name = AddSymbolString( worker, symbolEntry.name );
const char* newName = worker.GetString(frame.name); const char* newName = worker.GetString( frame.name );
if( symbolEntry.file.length() ) if( symbolEntry.file.length() )
{ {
frame.file = AddSymbolString( worker, symbolEntry.file.c_str() ); frame.file = AddSymbolString( worker, symbolEntry.file );
frame.line = symbolEntry.line; frame.line = symbolEntry.line;
} }
} }

View File

@ -11,11 +11,6 @@ namespace tracy
class Worker; class Worker;
} }
class SymbolResolver;
SymbolResolver* CreateResolver();
void DestroySymbolResolver(SymbolResolver* resolver);
struct FrameEntry struct FrameEntry
{ {
tracy::CallstackFrame* frame = nullptr; tracy::CallstackFrame* frame = nullptr;
@ -33,13 +28,11 @@ struct SymbolEntry
using SymbolEntryList = std::vector<SymbolEntry>; using SymbolEntryList = std::vector<SymbolEntry>;
bool ResolveSymbols(SymbolResolver* resolver, const std::string& imagePath, bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
const FrameEntryList& inputEntryList, SymbolEntryList& resolvedEntries );
SymbolEntryList& resolvedEntries);
using PathSubstitutionList = std::vector<std::pair<std::regex, std::string> >; using PathSubstitutionList = std::vector<std::pair<std::regex, std::string> >;
bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker, bool PatchSymbols( tracy::Worker& worker, const PathSubstitutionList& pathSubstituionlist, bool verbose = false );
const PathSubstitutionList& pathSubstituionlist, bool verbose = false);
#endif // __SYMBOLRESOLVER_HPP__ #endif // __SYMBOLRESOLVER_HPP__

View File

@ -10,16 +10,16 @@
#include <memory> #include <memory>
#include <stdio.h> #include <stdio.h>
std::string ExecShellCommand(const char* cmd) std::string ExecShellCommand( const char* cmd )
{ {
std::array<char, 128> buffer; std::array<char, 128> buffer;
std::string result; std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose); std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) if( !pipe )
{ {
return ""; return "";
} }
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) while( fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr )
{ {
result += buffer.data(); result += buffer.data();
} }
@ -29,13 +29,26 @@ std::string ExecShellCommand(const char* cmd)
class SymbolResolver class SymbolResolver
{ {
public: public:
SymbolResolver(const std::string& addr2linePath) SymbolResolver( const std::string& addr2linePath )
: m_addr2LinePath(addr2linePath)
{}
bool ResolveSymbols(const std::string& imagePath, const FrameEntryList& inputEntryList,
SymbolEntryList& resolvedEntries)
{ {
std::stringstream result(ExecShellCommand("which addr2line"));
std::getline(result, m_addr2LinePath);
if( !m_addr2LinePath.length() )
{
std::cerr << "'addr2line' was not found in the system, please installed it" << std::endl;
}
else
{
std::cout << "Using 'addr2line' found at: '" << m_addr2LinePath.c_str() << "'" << std::endl;
}
}
bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
SymbolEntryList& resolvedEntries )
{
if (!m_addr2LinePath.length()) return false;
// generate a single addr2line cmd line for all addresses in one invocation // generate a single addr2line cmd line for all addresses in one invocation
std::stringstream ss; std::stringstream ss;
ss << m_addr2LinePath << " -C -f -e " << imagePath << " -a "; ss << m_addr2LinePath << " -C -f -e " << imagePath << " -a ";
@ -91,34 +104,11 @@ private:
std::string m_addr2LinePath; std::string m_addr2LinePath;
}; };
SymbolResolver* CreateResolver() bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
SymbolEntryList& resolvedEntries )
{ {
std::stringstream result( ExecShellCommand("which addr2line") ); static SymbolResolver symbolResolver;
std::string addr2LinePath; return symbolResolver.ResolveSymbols( imagePath, inputEntryList, resolvedEntries );
std::getline( result, addr2LinePath );
if(!addr2LinePath.length())
{
std::cerr << "'addr2line' was not found in the system, please installed it" << std::endl;
return nullptr;
}
std::cout << "Using 'addr2line' found at: '" << addr2LinePath.c_str() << "'" << std::endl;
return new SymbolResolver{addr2LinePath};
} }
void DestroySymbolResolver(SymbolResolver* resolver) #endif // #ifndef _WIN32
{
delete resolver;
}
bool ResolveSymbols(SymbolResolver* resolver, const std::string& imagePath,
const FrameEntryList& inputEntryList, SymbolEntryList& resolvedEntries)
{
if (resolver)
{
return resolver->ResolveSymbols( imagePath, inputEntryList, resolvedEntries );
}
return false;
}
#endif // #ifndef _WIN32

View File

@ -23,14 +23,15 @@ public:
{ {
m_procHandle = GetCurrentProcess(); m_procHandle = GetCurrentProcess();
if (!SymInitialize(m_procHandle, NULL, FALSE)) if( !SymInitialize(m_procHandle, NULL, FALSE) )
{ {
std::cerr << "SymInitialize() failed with: " << GetLastErrorString() << std::endl; std::cerr << "SymInitialize() failed with: " << GetLastErrorString() << std::endl;
} }
else else
{ {
const DWORD symopts = SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; const DWORD symopts = SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES;
SymSetOptions( symopts ); SymSetOptions( symopts );
m_dbgHelpInitialized = true;
} }
} }
@ -39,18 +40,20 @@ public:
SymCleanup( m_procHandle ); SymCleanup( m_procHandle );
} }
bool ResolveSymbolsForModule(const std::string& imagePath, const FrameEntryList& inputEntryList, bool ResolveSymbolsForModule( const std::string& imagePath, const FrameEntryList& inputEntryList,
SymbolEntryList& resolvedEntries) SymbolEntryList& resolvedEntries )
{ {
ULONG64 moduleBase = SymLoadModuleEx( m_procHandle, NULL, imagePath.c_str(), NULL, 0, 0, NULL, 0); if( !m_dbgHelpInitialized ) return false;
if (!moduleBase)
ULONG64 moduleBase = SymLoadModuleEx( m_procHandle, NULL, imagePath.c_str(), NULL, 0, 0, NULL, 0 );
if( !moduleBase )
{ {
std::cerr << "SymLoadModuleEx() failed for module " << imagePath std::cerr << "SymLoadModuleEx() failed for module " << imagePath
<< ": " << GetLastErrorString() << std::endl; << ": " << GetLastErrorString() << std::endl;
return false; return false;
} }
for (size_t i = 0; i < inputEntryList.size(); ++i) for( size_t i = 0; i < inputEntryList.size(); ++i )
{ {
uint64_t offset = inputEntryList[i].symbolOffset; uint64_t offset = inputEntryList[i].symbolOffset;
DWORD64 address = moduleBase + offset; DWORD64 address = moduleBase + offset;
@ -61,7 +64,7 @@ public:
SymbolEntry newEntry; SymbolEntry newEntry;
if ( SymFromAddr( m_procHandle, address, NULL, symbolInfo ) ) if( SymFromAddr( m_procHandle, address, NULL, symbolInfo ) )
{ {
newEntry.name = symbolInfo->Name; newEntry.name = symbolInfo->Name;
//std::cout << "Resolved symbol to: '" << newEntry.name << "'" << std::endl; //std::cout << "Resolved symbol to: '" << newEntry.name << "'" << std::endl;
@ -84,7 +87,7 @@ public:
resolvedEntries.push_back(std::move(newEntry)); resolvedEntries.push_back(std::move(newEntry));
} }
SymUnloadModule64(m_procHandle, moduleBase); SymUnloadModule64( m_procHandle, moduleBase );
return true; return true;
} }
@ -111,32 +114,17 @@ private:
return message; return message;
} }
bool m_dbgHelpInitialized = false;
HANDLE m_procHandle = nullptr; HANDLE m_procHandle = nullptr;
}; };
char SymbolResolver::s_symbolResolutionBuffer[symbolResolutionBufferSize]; char SymbolResolver::s_symbolResolutionBuffer[symbolResolutionBufferSize];
bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
SymbolResolver* CreateResolver() SymbolEntryList& resolvedEntries )
{ {
SymbolResolver* resolver = new SymbolResolver(); static SymbolResolver resolver;
return resolver; return resolver.ResolveSymbolsForModule( imagePath, inputEntryList, resolvedEntries );
} }
void DestroySymbolResolver(SymbolResolver* resolver) #endif // #ifdef _WIN32
{
delete resolver;
}
bool ResolveSymbols(SymbolResolver* resolver, const std::string& imagePath,
const FrameEntryList& inputEntryList,
SymbolEntryList& resolvedEntries)
{
if( resolver )
{
return resolver->ResolveSymbolsForModule( imagePath, inputEntryList, resolvedEntries );
}
return false;
}
#endif // #ifdef _WIN32

View File

@ -177,15 +177,15 @@ int main( int argc, char** argv )
return 0; return 0;
} }
void PatchSymbols(tracy::Worker& worker, const Args& args) void PatchSymbols( tracy::Worker& worker, const Args& args )
{ {
std::cout << "Resolving and patching symbols..." << std::endl; std::cout << "Resolving and patching symbols..." << std::endl;
PathSubstitutionList pathSubstitutionList; PathSubstitutionList pathSubstitutionList;
for (const std::string& pathSubst : args.pathSubstitutions) for( const std::string& pathSubst : args.pathSubstitutions )
{ {
std::size_t pos = pathSubst.find(';'); std::size_t pos = pathSubst.find(';');
if (pos == std::string::npos) if( pos == std::string::npos )
{ {
std::cerr << "Ignoring invalid path substitution: '" << pathSubst std::cerr << "Ignoring invalid path substitution: '" << pathSubst
<< " '(please separate the regex of the string to replace with a ';')" << std::endl; << " '(please separate the regex of the string to replace with a ';')" << std::endl;
@ -194,11 +194,11 @@ void PatchSymbols(tracy::Worker& worker, const Args& args)
try try
{ {
std::regex reg(pathSubst.substr(0, pos)); std::regex reg( pathSubst.substr(0, pos) );
std::string replacementStr(pathSubst.substr(pos + 1)); std::string replacementStr( pathSubst.substr(pos + 1) );
pathSubstitutionList.push_back(std::pair(reg, replacementStr)); pathSubstitutionList.push_back( std::pair(reg, replacementStr) );
} }
catch (std::exception& e) catch( std::exception& e )
{ {
std::cerr << "Ignoring invalid path substitution: '" << pathSubst std::cerr << "Ignoring invalid path substitution: '" << pathSubst
<< "' (" << e.what() << ")" << std::endl; << "' (" << e.what() << ")" << std::endl;
@ -206,15 +206,8 @@ void PatchSymbols(tracy::Worker& worker, const Args& args)
} }
} }
SymbolResolver* resolver = CreateResolver(); if( !PatchSymbols( worker, pathSubstitutionList, args.verbose ) )
if (resolver)
{ {
PatchSymbols(resolver, worker, pathSubstitutionList, args.verbose); std::cerr << "Failed to patch symbols" << std::endl;
DestroySymbolResolver(resolver);
}
else
{
std::cerr << "Failed to create symbol resolver - skipping resolving" << std::endl;
} }
} }