mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 22:44:34 +00:00
- Fix formatting
- delete CreateResolver/DestroySymbolResolver
This commit is contained in:
parent
687d681764
commit
5c0513931a
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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__
|
@ -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)
|
|
||||||
{
|
|
||||||
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
|
#endif // #ifndef _WIN32
|
@ -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)
|
|
||||||
{
|
|
||||||
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
|
#endif // #ifdef _WIN32
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user