mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 14:44:34 +00:00
Add support for offline symbol resolving by setting the "TRACY_SYMBOL_OFFLINE_RESOLVE=1" env var
- Add a tool "tracy-edit" that allows loading a tracy capture, patching symbols and recompress the result - Add offline symbol resolvers for linux (using addr2line) and windows (using dbghelper)
This commit is contained in:
parent
906f73cab3
commit
f4f75eac64
@ -93,6 +93,14 @@ extern "C" const char* ___tracy_demangle( const char* mangled )
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
// when "TRACY_SYMBOL_OFFLINE_RESOLVE" is set to "1", instead of fully resolving symbols at runtime,
|
||||
// simply resolve the offset and image name (which will be enough the resolving to be done offline)
|
||||
bool getDoOfflineSymbolResolve()
|
||||
{
|
||||
const char* symbolOfflineResolve = GetEnvVar( "TRACY_SYMBOL_OFFLINE_RESOLVE" );
|
||||
return (symbolOfflineResolve && symbolOfflineResolve[0] == '1');
|
||||
}
|
||||
|
||||
#if TRACY_HAS_CALLSTACK == 1
|
||||
|
||||
enum { MaxCbTrace = 64 };
|
||||
@ -135,19 +143,24 @@ struct KernelDriver
|
||||
|
||||
KernelDriver* s_krnlCache = nullptr;
|
||||
size_t s_krnlCacheCnt;
|
||||
|
||||
bool s_doOfflineSymbolResolve = false;
|
||||
|
||||
void InitCallstackCritical()
|
||||
{
|
||||
___tracy_RtlWalkFrameChain = (___tracy_t_RtlWalkFrameChain)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlWalkFrameChain" );
|
||||
}
|
||||
|
||||
void InitCallstack()
|
||||
void dbgHelpInit()
|
||||
{
|
||||
_SymAddrIncludeInlineTrace = (t_SymAddrIncludeInlineTrace)GetProcAddress( GetModuleHandleA( "dbghelp.dll" ), "SymAddrIncludeInlineTrace" );
|
||||
_SymQueryInlineTrace = (t_SymQueryInlineTrace)GetProcAddress( GetModuleHandleA( "dbghelp.dll" ), "SymQueryInlineTrace" );
|
||||
_SymFromInlineContext = (t_SymFromInlineContext)GetProcAddress( GetModuleHandleA( "dbghelp.dll" ), "SymFromInlineContext" );
|
||||
_SymGetLineFromInlineContext = (t_SymGetLineFromInlineContext)GetProcAddress( GetModuleHandleA( "dbghelp.dll" ), "SymGetLineFromInlineContext" );
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_SymAddrIncludeInlineTrace = (t_SymAddrIncludeInlineTrace)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymAddrIncludeInlineTrace");
|
||||
_SymQueryInlineTrace = (t_SymQueryInlineTrace)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymQueryInlineTrace");
|
||||
_SymFromInlineContext = (t_SymFromInlineContext)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymFromInlineContext");
|
||||
_SymGetLineFromInlineContext = (t_SymGetLineFromInlineContext)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymGetLineFromInlineContext");
|
||||
|
||||
#ifdef TRACY_DBGHELP_LOCK
|
||||
DBGHELP_INIT;
|
||||
@ -157,6 +170,65 @@ void InitCallstack()
|
||||
SymInitialize( GetCurrentProcess(), nullptr, true );
|
||||
SymSetOptions( SYMOPT_LOAD_LINES );
|
||||
|
||||
#ifdef TRACY_DBGHELP_LOCK
|
||||
DBGHELP_UNLOCK;
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD64 dbgHelpLoadSymbolsForModule(PCSTR imageName, DWORD64 baseOfDll, DWORD bllSize)
|
||||
{
|
||||
if( !s_doOfflineSymbolResolve )
|
||||
{
|
||||
return SymLoadModuleEx( GetCurrentProcess(), nullptr, imageName, nullptr, baseOfDll, bllSize, nullptr, 0 );
|
||||
}
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
ModuleCache* dbgHelpLoadSymbolsForModuleAndCache(PCSTR imageName, DWORD imageNameLength, DWORD64 baseOfDll, DWORD dllSize)
|
||||
{
|
||||
dbgHelpLoadSymbolsForModule( imageName, baseOfDll, dllSize );
|
||||
|
||||
ModuleCache* cachedModule = s_modCache->push_next();
|
||||
cachedModule->start = baseOfDll;
|
||||
cachedModule->end = baseOfDll + dllSize;
|
||||
|
||||
// when doing offline symbol resolution, we must store the full path of the dll for the resolving to work
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
cachedModule->name = (char*)tracy_malloc_fast(imageNameLength + 2);
|
||||
memcpy(cachedModule->name, imageName, imageNameLength);
|
||||
cachedModule->name[imageNameLength + 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ptr = imageName + imageNameLength;
|
||||
while (ptr > imageName && *ptr != '\\' && *ptr != '/') ptr--;
|
||||
if (ptr > imageName) ptr++;
|
||||
const auto namelen = imageName + imageNameLength - ptr;
|
||||
cachedModule->name = (char*)tracy_malloc_fast(namelen + 3);
|
||||
cachedModule->name[0] = '[';
|
||||
memcpy(cachedModule->name + 1, ptr, namelen);
|
||||
cachedModule->name[namelen + 1] = ']';
|
||||
cachedModule->name[namelen + 2] = '\0';
|
||||
}
|
||||
|
||||
return cachedModule;
|
||||
}
|
||||
|
||||
void InitCallstack()
|
||||
{
|
||||
s_doOfflineSymbolResolve = getDoOfflineSymbolResolve();
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
TracyDebug("TRACY: enabling offline symbol resolving!\n");
|
||||
}
|
||||
|
||||
dbgHelpInit();
|
||||
|
||||
#ifdef TRACY_DBGHELP_LOCK
|
||||
DBGHELP_LOCK;
|
||||
#endif
|
||||
|
||||
// use TRACY_NO_DBHELP_INIT_LOAD=1 to disable preloading of driver
|
||||
// and process module symbol loading at startup time - they will be loaded on demand later
|
||||
// Sometimes this process can take a very long time and prevent resolving callstack frames
|
||||
@ -204,7 +276,7 @@ void InitCallstack()
|
||||
path = full;
|
||||
}
|
||||
|
||||
SymLoadModuleEx( GetCurrentProcess(), nullptr, path, nullptr, (DWORD64)dev[i], 0, nullptr, 0 );
|
||||
dbgHelpLoadSymbolsForModule( path, (DWORD64)dev[i], 0 );
|
||||
|
||||
const auto psz = strlen( path );
|
||||
auto pptr = (char*)tracy_malloc_fast( psz+1 );
|
||||
@ -235,25 +307,12 @@ void InitCallstack()
|
||||
{
|
||||
const auto base = uint64_t( info.lpBaseOfDll );
|
||||
char name[1024];
|
||||
const auto res = GetModuleFileNameA( mod[i], name, 1021 );
|
||||
if( res > 0 )
|
||||
const auto nameLength = GetModuleFileNameA( mod[i], name, 1021 );
|
||||
if( nameLength > 0 )
|
||||
{
|
||||
// This may be a new module loaded since our call to SymInitialize.
|
||||
// Just in case, force DbgHelp to load its pdb !
|
||||
SymLoadModuleEx(proc, NULL, name, NULL, (DWORD64)info.lpBaseOfDll, info.SizeOfImage, NULL, 0);
|
||||
|
||||
auto ptr = name + res;
|
||||
while( ptr > name && *ptr != '\\' && *ptr != '/' ) ptr--;
|
||||
if( ptr > name ) ptr++;
|
||||
const auto namelen = name + res - ptr;
|
||||
auto cache = s_modCache->push_next();
|
||||
cache->start = base;
|
||||
cache->end = base + info.SizeOfImage;
|
||||
cache->name = (char*)tracy_malloc_fast( namelen+3 );
|
||||
cache->name[0] = '[';
|
||||
memcpy( cache->name+1, ptr, namelen );
|
||||
cache->name[namelen+1] = ']';
|
||||
cache->name[namelen+2] = '\0';
|
||||
dbgHelpLoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,6 +329,11 @@ void EndCallstack()
|
||||
|
||||
const char* DecodeCallstackPtrFast( uint64_t ptr )
|
||||
{
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
return "[unresolved]";
|
||||
}
|
||||
|
||||
static char ret[MaxNameSize];
|
||||
const auto proc = GetCurrentProcess();
|
||||
|
||||
@ -305,7 +369,13 @@ const char* GetKernelModulePath( uint64_t addr )
|
||||
return it->path;
|
||||
}
|
||||
|
||||
static const char* GetModuleNameAndPrepareSymbols( uint64_t addr )
|
||||
struct ModuleNameAndBaseAddress
|
||||
{
|
||||
const char* name;
|
||||
uint64_t baseAddr;
|
||||
};
|
||||
|
||||
ModuleNameAndBaseAddress GetModuleNameAndPrepareSymbols( uint64_t addr )
|
||||
{
|
||||
if( ( addr >> 63 ) != 0 )
|
||||
{
|
||||
@ -314,17 +384,17 @@ static const char* GetModuleNameAndPrepareSymbols( uint64_t addr )
|
||||
auto it = std::lower_bound( s_krnlCache, s_krnlCache + s_krnlCacheCnt, addr, []( const KernelDriver& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } );
|
||||
if( it != s_krnlCache + s_krnlCacheCnt )
|
||||
{
|
||||
return it->mod;
|
||||
return ModuleNameAndBaseAddress{ it->mod, it->addr };
|
||||
}
|
||||
}
|
||||
return "<kernel>";
|
||||
return ModuleNameAndBaseAddress{ "<kernel>", addr };
|
||||
}
|
||||
|
||||
for( auto& v : *s_modCache )
|
||||
{
|
||||
if( addr >= v.start && addr < v.end )
|
||||
{
|
||||
return v.name;
|
||||
return ModuleNameAndBaseAddress{ v.name, v.start };
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,35 +415,33 @@ static const char* GetModuleNameAndPrepareSymbols( uint64_t addr )
|
||||
if( addr >= base && addr < base + info.SizeOfImage )
|
||||
{
|
||||
char name[1024];
|
||||
const auto res = GetModuleFileNameA( mod[i], name, 1021 );
|
||||
if( res > 0 )
|
||||
const auto nameLength = GetModuleFileNameA( mod[i], name, 1021 );
|
||||
if( nameLength > 0 )
|
||||
{
|
||||
// since this is the first time we encounter this module, load its symbols (needed for modules loaded after SymInitialize)
|
||||
SymLoadModuleEx(proc, NULL, name, NULL, (DWORD64)info.lpBaseOfDll, info.SizeOfImage, NULL, 0);
|
||||
auto ptr = name + res;
|
||||
while( ptr > name && *ptr != '\\' && *ptr != '/' ) ptr--;
|
||||
if( ptr > name ) ptr++;
|
||||
const auto namelen = name + res - ptr;
|
||||
auto cache = s_modCache->push_next();
|
||||
cache->start = base;
|
||||
cache->end = base + info.SizeOfImage;
|
||||
cache->name = (char*)tracy_malloc_fast( namelen+3 );
|
||||
cache->name[0] = '[';
|
||||
memcpy( cache->name+1, ptr, namelen );
|
||||
cache->name[namelen+1] = ']';
|
||||
cache->name[namelen+2] = '\0';
|
||||
return cache->name;
|
||||
ModuleCache* cachedModule = dbgHelpLoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );
|
||||
return ModuleNameAndBaseAddress{ cachedModule->name, cachedModule->start };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "[unknown]";
|
||||
|
||||
return ModuleNameAndBaseAddress{ "[unknown]", 0x0 };
|
||||
}
|
||||
|
||||
CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||
{
|
||||
CallstackSymbolData sym;
|
||||
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
sym.file = "[unknown]";
|
||||
sym.line = 0;
|
||||
sym.needFree = false;
|
||||
return sym;
|
||||
}
|
||||
|
||||
IMAGEHLP_LINE64 line;
|
||||
DWORD displacement = 0;
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
@ -401,16 +469,29 @@ CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||
|
||||
CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||
{
|
||||
InitRpmalloc();
|
||||
|
||||
const ModuleNameAndBaseAddress moduleNameAndAddress = GetModuleNameAndPrepareSymbols( ptr );
|
||||
|
||||
if( s_doOfflineSymbolResolve )
|
||||
{
|
||||
cb_data[0].symAddr = ptr - moduleNameAndAddress.baseAddr;
|
||||
cb_data[0].symLen = 0;
|
||||
|
||||
cb_data[0].name = CopyStringFast("[unresolved]");
|
||||
cb_data[0].file = CopyStringFast("[unknown]");
|
||||
cb_data[0].line = 0;
|
||||
|
||||
return { cb_data, 1, moduleNameAndAddress.name };
|
||||
}
|
||||
|
||||
int write;
|
||||
const auto proc = GetCurrentProcess();
|
||||
InitRpmalloc();
|
||||
|
||||
#ifdef TRACY_DBGHELP_LOCK
|
||||
DBGHELP_LOCK;
|
||||
#endif
|
||||
|
||||
const auto moduleName = GetModuleNameAndPrepareSymbols(ptr);
|
||||
|
||||
#if !defined TRACY_NO_CALLSTACK_INLINES
|
||||
BOOL doInline = FALSE;
|
||||
DWORD ctx = 0;
|
||||
@ -459,7 +540,7 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||
cb_data[write].line = line.LineNumber;
|
||||
}
|
||||
|
||||
cb_data[write].name = symValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleName );
|
||||
cb_data[write].name = symValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleNameAndAddress.name );
|
||||
cb_data[write].file = CopyStringFast( filename );
|
||||
if( symValid )
|
||||
{
|
||||
@ -492,7 +573,7 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||
cb.line = line.LineNumber;
|
||||
}
|
||||
|
||||
cb.name = symInlineValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleName );
|
||||
cb.name = symInlineValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleNameAndAddress.name );
|
||||
cb.file = CopyStringFast( filename );
|
||||
if( symInlineValid )
|
||||
{
|
||||
@ -513,7 +594,7 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||
DBGHELP_UNLOCK;
|
||||
#endif
|
||||
|
||||
return { cb_data, uint8_t( cb_num ), moduleName };
|
||||
return { cb_data, uint8_t( cb_num ), moduleNameAndAddress.name };
|
||||
}
|
||||
|
||||
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
||||
@ -696,7 +777,16 @@ void InitCallstackCritical()
|
||||
|
||||
void InitCallstack()
|
||||
{
|
||||
cb_bts = backtrace_create_state( nullptr, 0, nullptr, nullptr );
|
||||
if( getDoOfflineSymbolResolve() )
|
||||
{
|
||||
cb_bts = nullptr; // disable use of libbacktrace calls
|
||||
TracyDebug("TRACY: enabling offline symbol resolving!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
cb_bts = backtrace_create_state( nullptr, 0, nullptr, nullptr );
|
||||
}
|
||||
|
||||
#ifndef TRACY_DEMANGLE
|
||||
___tracy_init_demangle_buffer();
|
||||
#endif
|
||||
@ -835,7 +925,15 @@ static void SymbolAddressErrorCb( void* data, const char* /*msg*/, int /*errnum*
|
||||
CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||
{
|
||||
CallstackSymbolData sym;
|
||||
backtrace_pcinfo( cb_bts, ptr, SymbolAddressDataCb, SymbolAddressErrorCb, &sym );
|
||||
if( cb_bts )
|
||||
{
|
||||
backtrace_pcinfo( cb_bts, ptr, SymbolAddressDataCb, SymbolAddressErrorCb, &sym );
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolAddressErrorCb(&sym, nullptr, 0);
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
@ -938,20 +1036,42 @@ void SymInfoError( void* /*data*/, const char* /*msg*/, int /*errnum*/ )
|
||||
cb_data[cb_num-1].symAddr = 0;
|
||||
}
|
||||
|
||||
void getSymbolForOfflineResolve(void* address, Dl_info& dlinfo, CallstackEntry& cbEntry)
|
||||
{
|
||||
// tagged with a string that we can identify as an unresolved symbol
|
||||
cbEntry.name = CopyStringFast( "[unresolved]" );
|
||||
// set .so relative offset so it can be resolved offline
|
||||
cbEntry.symAddr = (uint64_t)address - (uint64_t)(dlinfo.dli_fbase);
|
||||
cbEntry.symLen = 0x0;
|
||||
cbEntry.file = CopyStringFast( "[unknown]" );
|
||||
cbEntry.line = 0;
|
||||
}
|
||||
|
||||
CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||
{
|
||||
InitRpmalloc();
|
||||
if( ptr >> 63 == 0 )
|
||||
{
|
||||
cb_num = 0;
|
||||
backtrace_pcinfo( cb_bts, ptr, CallstackDataCb, CallstackErrorCb, nullptr );
|
||||
assert( cb_num > 0 );
|
||||
|
||||
backtrace_syminfo( cb_bts, ptr, SymInfoCallback, SymInfoError, nullptr );
|
||||
|
||||
const char* symloc = nullptr;
|
||||
Dl_info dlinfo;
|
||||
if( dladdr( (void*)ptr, &dlinfo ) ) symloc = dlinfo.dli_fname;
|
||||
if( dladdr( (void*)ptr, &dlinfo ) )
|
||||
{
|
||||
symloc = dlinfo.dli_fname;
|
||||
}
|
||||
|
||||
if(cb_bts)
|
||||
{
|
||||
cb_num = 0;
|
||||
backtrace_pcinfo( cb_bts, ptr, CallstackDataCb, CallstackErrorCb, nullptr );
|
||||
assert( cb_num > 0 );
|
||||
|
||||
backtrace_syminfo( cb_bts, ptr, SymInfoCallback, SymInfoError, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
cb_num = 1;
|
||||
getSymbolForOfflineResolve( (void*)ptr, dlinfo, cb_data[0] );
|
||||
}
|
||||
|
||||
return { cb_data, uint8_t( cb_num ), symloc ? symloc : "[unknown]" };
|
||||
}
|
||||
|
@ -553,11 +553,12 @@ Worker::Worker( const char* name, const char* program, const std::vector<ImportE
|
||||
}
|
||||
}
|
||||
|
||||
Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
|
||||
Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allowStringModification)
|
||||
: m_hasData( true )
|
||||
, m_stream( nullptr )
|
||||
, m_buffer( nullptr )
|
||||
, m_inconsistentSamples( false )
|
||||
, m_allowStringModification(allowStringModification)
|
||||
{
|
||||
auto loadStart = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@ -707,7 +708,12 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
|
||||
|
||||
f.Read( sz );
|
||||
m_data.stringMap.reserve( sz );
|
||||
m_data.stringData.reserve_exact( sz, m_slab );
|
||||
|
||||
if( !m_allowStringModification )
|
||||
{
|
||||
m_data.stringData.reserve_exact( sz, m_slab );
|
||||
}
|
||||
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
uint64_t ptr, ssz;
|
||||
@ -716,7 +722,16 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
|
||||
f.Read( dst, ssz );
|
||||
dst[ssz] = '\0';
|
||||
m_data.stringMap.emplace( charutil::StringKey { dst, size_t( ssz ) }, i );
|
||||
m_data.stringData[i] = ( dst );
|
||||
|
||||
if( m_allowStringModification )
|
||||
{
|
||||
m_data.stringData.push_back( dst );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data.stringData[i] = ( dst );
|
||||
}
|
||||
|
||||
pointerMap.emplace( ptr, dst );
|
||||
}
|
||||
|
||||
@ -2411,6 +2426,19 @@ const char* Worker::GetString( const StringIdx& idx ) const
|
||||
return m_data.stringData[idx.Idx()];
|
||||
}
|
||||
|
||||
uint32_t Worker::AddNewString(const char* newString)
|
||||
{
|
||||
assert(m_allowStringModification);
|
||||
uint64_t sz = strlen(newString);
|
||||
auto ptr = m_slab.Alloc<char>( sz+1 );
|
||||
memcpy( ptr, newString, sz );
|
||||
ptr[sz] = '\0';
|
||||
uint32_t idx = m_data.stringData.size();
|
||||
m_data.stringMap.emplace( charutil::StringKey { ptr, sz }, idx );
|
||||
m_data.stringData.push_back( ptr );
|
||||
return idx;
|
||||
}
|
||||
|
||||
static const char* BadExternalThreadNames[] = {
|
||||
"ntdll.dll",
|
||||
"???",
|
||||
|
@ -446,7 +446,7 @@ public:
|
||||
|
||||
Worker( const char* addr, uint16_t port );
|
||||
Worker( const char* name, const char* program, const std::vector<ImportEventTimeline>& timeline, const std::vector<ImportEventMessages>& messages, const std::vector<ImportEventPlots>& plots, const std::unordered_map<uint64_t, std::string>& threadNames );
|
||||
Worker( FileRead& f, EventType::Type eventMask = EventType::All, bool bgTasks = true );
|
||||
Worker( FileRead& f, EventType::Type eventMask = EventType::All, bool bgTasks = true, bool allowStringModification = false);
|
||||
~Worker();
|
||||
|
||||
const std::string& GetAddr() const { return m_addr; }
|
||||
@ -549,6 +549,8 @@ public:
|
||||
StringIdx GetLocationForAddress( uint64_t address, uint32_t& line ) const;
|
||||
const uint64_t* GetInlineSymbolList( uint64_t sym, uint32_t len );
|
||||
|
||||
unordered_flat_map<CallstackFrameId, CallstackFrameData*, CallstackFrameIdHash, CallstackFrameIdCompare>& GetCallstackFrameMap() { return m_data.callstackFrameMap; }
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
const VarArray<CallstackFrameId>& GetParentCallstack( uint32_t idx ) const { return *m_data.parentCallstackPayload[idx]; }
|
||||
const CallstackFrameData* GetParentCallstackFrame( const CallstackFrameId& ptr ) const;
|
||||
@ -665,6 +667,8 @@ public:
|
||||
|
||||
void CacheSourceFiles();
|
||||
|
||||
uint32_t AddNewString(const char* newString);
|
||||
|
||||
private:
|
||||
void Network();
|
||||
void Exec();
|
||||
@ -984,6 +988,7 @@ private:
|
||||
bool m_combineSamples;
|
||||
bool m_identifySamples = false;
|
||||
bool m_inconsistentSamples;
|
||||
bool m_allowStringModification = false;
|
||||
|
||||
short_ptr<GpuCtxData> m_gpuCtxMap[256];
|
||||
uint32_t m_pendingCallstackId = 0;
|
||||
|
16
tracy-edit/build/unix/Makefile
Normal file
16
tracy-edit/build/unix/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
all: release
|
||||
|
||||
debug:
|
||||
@+make -f debug.mk all
|
||||
|
||||
release:
|
||||
@+make -f release.mk all
|
||||
|
||||
clean:
|
||||
@+make -f build.mk clean
|
||||
|
||||
db: clean
|
||||
@bear -- $(MAKE) -f debug.mk all
|
||||
@mv -f compile_commands.json ../../../
|
||||
|
||||
.PHONY: all clean debug release db
|
13
tracy-edit/build/unix/build.mk
Normal file
13
tracy-edit/build/unix/build.mk
Normal file
@ -0,0 +1,13 @@
|
||||
CFLAGS +=
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++17
|
||||
DEFINES += -DTRACY_NO_STATISTICS
|
||||
INCLUDES := -I../../../capstone/include/capstone
|
||||
LIBS += -lcapstone -lpthread
|
||||
LDFLAGS := -L../../../capstone
|
||||
PROJECT := tracy-edit
|
||||
IMAGE := $(PROJECT)-$(BUILD)
|
||||
|
||||
FILTER :=
|
||||
include ../../../common/src-from-vcxproj.mk
|
||||
|
||||
include ../../../common/unix.mk
|
6
tracy-edit/build/unix/debug.mk
Normal file
6
tracy-edit/build/unix/debug.mk
Normal file
@ -0,0 +1,6 @@
|
||||
CFLAGS := -g3 -Wall
|
||||
DEFINES := -DDEBUG
|
||||
BUILD := debug
|
||||
|
||||
include ../../../common/unix-debug.mk
|
||||
include build.mk
|
9
tracy-edit/build/unix/release.mk
Normal file
9
tracy-edit/build/unix/release.mk
Normal file
@ -0,0 +1,9 @@
|
||||
CFLAGS := -O3
|
||||
ifndef TRACY_NO_LTO
|
||||
CFLAGS += -flto
|
||||
endif
|
||||
DEFINES := -DNDEBUG
|
||||
BUILD := release
|
||||
|
||||
include ../../../common/unix-release.mk
|
||||
include build.mk
|
25
tracy-edit/build/win32/tracy-edit.sln
Normal file
25
tracy-edit/build/win32/tracy-edit.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30907.101
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tracy-edit", "tracy-edit.vcxproj", "{447D58BF-94CD-4469-BB90-549C05D03E00}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{447D58BF-94CD-4469-BB90-549C05D03E00}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{447D58BF-94CD-4469-BB90-549C05D03E00}.Debug|x64.Build.0 = Debug|x64
|
||||
{447D58BF-94CD-4469-BB90-549C05D03E00}.Release|x64.ActiveCfg = Release|x64
|
||||
{447D58BF-94CD-4469-BB90-549C05D03E00}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3E51386C-43EA-44AC-9F24-AFAFE4D63ADE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
210
tracy-edit/build/win32/tracy-edit.vcxproj
Normal file
210
tracy-edit/build/win32/tracy-edit.vcxproj
Normal file
@ -0,0 +1,210 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{447D58BF-94CD-4469-BB90-549C05D03E00}</ProjectGuid>
|
||||
<RootNamespace>tracy-edit</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<VcpkgTriplet>x64-windows-static</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnableManifest>true</VcpkgEnableManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<PreprocessorDefinitions>TRACY_NO_STATISTICS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\include;$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\include\capstone;$(VcpkgManifestRoot)\vcpkg_installed\$(VcpkgTriplet)\$(VcpkgTriplet)\include\capstone;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\capstone</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;capstone.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\debug\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<PreprocessorDefinitions>TRACY_NO_STATISTICS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\include;$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\include\capstone;$(VcpkgManifestRoot)\vcpkg_installed\$(VcpkgTriplet)\$(VcpkgTriplet)\include\capstone;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\capstone</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>ws2_32.lib;capstone.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\vcpkg_installed\$(VcpkgTriplet)\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\public\common\TracySocket.cpp" />
|
||||
<ClCompile Include="..\..\..\public\common\TracyStackFrames.cpp" />
|
||||
<ClCompile Include="..\..\..\public\common\TracySystem.cpp" />
|
||||
<ClCompile Include="..\..\..\public\common\tracy_lz4.cpp" />
|
||||
<ClCompile Include="..\..\..\public\common\tracy_lz4hc.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyMemory.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyMmap.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyTaskDispatch.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyTextureCompression.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyThreadCompress.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyWorker.cpp" />
|
||||
<ClCompile Include="..\..\..\zstd\common\debug.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\entropy_common.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\error_private.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\fse_decompress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\pool.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\threading.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\xxhash.c" />
|
||||
<ClCompile Include="..\..\..\zstd\common\zstd_common.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\fse_compress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\hist.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\huf_compress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstdmt_compress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_literals.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_sequences.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_superblock.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_double_fast.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_fast.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_lazy.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_ldm.c" />
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_opt.c" />
|
||||
<ClCompile Include="..\..\..\zstd\decompress\huf_decompress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_ddict.c" />
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_decompress.c" />
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_decompress_block.c" />
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\cover.c" />
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\divsufsort.c" />
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\fastcover.c" />
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\zdict.c" />
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolver.cpp" />
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolverAddr2Line.cpp" />
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolverDbgHelper.cpp" />
|
||||
<ClCompile Include="..\..\src\tracy-edit.cpp" />
|
||||
<ClCompile Include="..\..\..\getopt\getopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\public\common\TracyAlign.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyAlloc.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyApi.h" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyColor.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyForceInline.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyMutex.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyProtocol.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyQueue.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracySocket.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyStackFrames.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracySystem.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyUwp.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\TracyYield.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\tracy_lz4.hpp" />
|
||||
<ClInclude Include="..\..\..\public\common\tracy_lz4hc.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyCharUtil.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyEvent.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyFileRead.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyFileWrite.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyMemory.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyMmap.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyPopcnt.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracySlab.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyTaskDispatch.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyTextureCompression.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyThreadCompress.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyVector.hpp" />
|
||||
<ClInclude Include="..\..\..\server\TracyWorker.hpp" />
|
||||
<ClInclude Include="..\..\..\zstd\common\bitstream.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\compiler.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\cpu.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\debug.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\error_private.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\fse.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\huf.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\mem.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\pool.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\portability_macros.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\threading.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\xxhash.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_deps.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_internal.h" />
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_trace.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\clevels.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\hist.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstdmt_compress.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_internal.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_literals.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_sequences.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_superblock.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_cwksp.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_double_fast.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_fast.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_lazy.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_ldm.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_ldm_geartab.h" />
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_opt.h" />
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_ddict.h" />
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_decompress_block.h" />
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_decompress_internal.h" />
|
||||
<ClInclude Include="..\..\..\zstd\dictBuilder\cover.h" />
|
||||
<ClInclude Include="..\..\..\zstd\dictBuilder\divsufsort.h" />
|
||||
<ClInclude Include="..\..\..\zstd\zdict.h" />
|
||||
<ClInclude Include="..\..\..\zstd\zstd.h" />
|
||||
<ClInclude Include="..\..\..\zstd\zstd_errors.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\zstd\decompress\huf_decompress_amd64.S" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
366
tracy-edit/build/win32/tracy-edit.vcxproj.filters
Normal file
366
tracy-edit/build/win32/tracy-edit.vcxproj.filters
Normal file
@ -0,0 +1,366 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="src">
|
||||
<UniqueIdentifier>{729c80ee-4d26-4a5e-8f1f-6c075783eb56}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="server">
|
||||
<UniqueIdentifier>{cf23ef7b-7694-4154-830b-00cf053350ea}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="common">
|
||||
<UniqueIdentifier>{e39d3623-47cd-4752-8da9-3ea324f964c1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="zstd">
|
||||
<UniqueIdentifier>{9ec18988-3ab7-4c05-a9d0-46c0a68037de}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="zstd\common">
|
||||
<UniqueIdentifier>{5ee9ba63-2914-4027-997e-e743a294bba6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="zstd\compress">
|
||||
<UniqueIdentifier>{a166d032-7be0-4d07-9f85-a8199cc1ec7c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="zstd\decompress">
|
||||
<UniqueIdentifier>{438fff23-197c-4b6f-91f0-74f8b3878571}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="zstd\dictBuilder">
|
||||
<UniqueIdentifier>{e5c7021a-e0e4-45c2-b461-e806bc036d5f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\server\TracyMemory.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyWorker.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\tracy-edit.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyThreadCompress.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyTaskDispatch.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyMmap.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyTextureCompression.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\debug.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\entropy_common.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\error_private.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\fse_decompress.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\pool.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\threading.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\xxhash.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\common\zstd_common.c">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\fse_compress.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\hist.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\huf_compress.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_literals.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_sequences.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_compress_superblock.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_double_fast.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_fast.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_lazy.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_ldm.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstd_opt.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\compress\zstdmt_compress.c">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\decompress\huf_decompress.c">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_ddict.c">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_decompress.c">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\decompress\zstd_decompress_block.c">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\cover.c">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\divsufsort.c">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\fastcover.c">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\zstd\dictBuilder\zdict.c">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\public\common\tracy_lz4.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\public\common\tracy_lz4hc.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\public\common\TracySocket.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\public\common\TracyStackFrames.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\public\common\TracySystem.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolver.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolverAddr2Line.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\OfflineSymbolResolverDbgHelper.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\getopt\getopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\server\TracyCharUtil.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyEvent.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyFileWrite.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyMemory.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyPopcnt.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracySlab.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyVector.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyWorker.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyThreadCompress.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyTaskDispatch.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyFileRead.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyMmap.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\server\TracyTextureCompression.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\zstd.h">
|
||||
<Filter>zstd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\zstd_errors.h">
|
||||
<Filter>zstd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\bitstream.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\compiler.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\cpu.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\debug.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\error_private.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\fse.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\huf.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\mem.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\pool.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\threading.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\xxhash.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_deps.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_internal.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\zstd_trace.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\hist.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_internal.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_literals.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_sequences.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_compress_superblock.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_cwksp.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_double_fast.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_fast.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_lazy.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_ldm.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_ldm_geartab.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstd_opt.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\zstdmt_compress.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_ddict.h">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_decompress_block.h">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\decompress\zstd_decompress_internal.h">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\zdict.h">
|
||||
<Filter>zstd</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\dictBuilder\cover.h">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\dictBuilder\divsufsort.h">
|
||||
<Filter>zstd\dictBuilder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\common\portability_macros.h">
|
||||
<Filter>zstd\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\zstd\compress\clevels.h">
|
||||
<Filter>zstd\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\tracy_lz4.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\tracy_lz4hc.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyAlign.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyAlloc.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyApi.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyColor.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyForceInline.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyMutex.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyProtocol.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyQueue.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracySocket.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyStackFrames.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracySystem.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyUwp.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\common\TracyYield.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\zstd\decompress\huf_decompress_amd64.S">
|
||||
<Filter>zstd\decompress</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
123
tracy-edit/src/OfflineSymbolResolver.cpp
Normal file
123
tracy-edit/src/OfflineSymbolResolver.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../server/TracyWorker.hpp"
|
||||
#include "../../zstd/zstd.h"
|
||||
|
||||
#include "OfflineSymbolResolver.h"
|
||||
|
||||
// TODO: use string hash map to reduce duplication or use some worker string internal hashing
|
||||
tracy::StringIdx AddSymbolString(tracy::Worker& worker, const char* str)
|
||||
{
|
||||
uint32_t newStringIdx = worker.AddNewString( str );
|
||||
return tracy::StringIdx( newStringIdx );
|
||||
}
|
||||
|
||||
bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker, bool verbose)
|
||||
{
|
||||
if( !resolver )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t callstackFrameCount = worker.GetCallstackFrameCount();
|
||||
std::string relativeSoNameMatch = "[unresolved]";
|
||||
|
||||
std::cout << "Found '" << callstackFrameCount << "' callstack frames. Batching into image groups..." << std::endl;
|
||||
|
||||
// batch the symbol queries by .so so we issue the least amount of requests
|
||||
using FrameEntriesPerImageIdx = std::unordered_map<uint32_t, FrameEntryList>;
|
||||
FrameEntriesPerImageIdx entriesPerImageIdx;
|
||||
|
||||
auto& callstackFrameMap = worker.GetCallstackFrameMap();
|
||||
for( auto it = callstackFrameMap.begin(); it != callstackFrameMap.end(); ++it )
|
||||
{
|
||||
tracy::CallstackFrameData* frameDataPtr = it->second;
|
||||
if( !frameDataPtr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tracy::CallstackFrameData& frameData = *frameDataPtr;
|
||||
const char* imageName = worker.GetString( frameData.imageName );
|
||||
|
||||
const uint32_t imageNameIdx = frameData.imageName.Idx();
|
||||
FrameEntryList& entries = entriesPerImageIdx[imageNameIdx];
|
||||
|
||||
for( uint8_t f = 0; f < frameData.size; f++ )
|
||||
{
|
||||
tracy::CallstackFrame& frame = frameData.data[f];
|
||||
|
||||
// TODO: use a better way to identify symbols that are unresolved
|
||||
const char* nameStr = worker.GetString(frame.name);
|
||||
if( strncmp( nameStr, relativeSoNameMatch.c_str(), relativeSoNameMatch.length() ) == 0 )
|
||||
{
|
||||
// when doing offline resolving we pass the offset from the start of the shared library in the "symAddr"
|
||||
const uint64_t decodedOffset = frame.symAddr;
|
||||
entries.push_back( {&frame, decodedOffset} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Batched into '" << entriesPerImageIdx.size() << "' unique image groups" << std::endl;
|
||||
|
||||
// FIXME: the resolving of symbols here can be slow and could be done in parallel per "image"
|
||||
// - be careful with string allocation though as that would be not safe to do in parallel
|
||||
for( FrameEntriesPerImageIdx::iterator imageIt = entriesPerImageIdx.begin(),
|
||||
imageItEnd = entriesPerImageIdx.end(); imageIt != imageItEnd; ++imageIt )
|
||||
{
|
||||
tracy::StringIdx imageIdx( imageIt->first );
|
||||
const char* imageName = worker.GetString( imageIdx );
|
||||
|
||||
FrameEntryList& entries = imageIt->second;
|
||||
|
||||
std::cout << "Resolving " << entries.size() << " symbols for image: '" << imageName << "'" << std::endl;
|
||||
|
||||
if(!entries.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SymbolEntryList resolvedEntries;
|
||||
ResolveSymbols( resolver, imageName, entries, resolvedEntries );
|
||||
|
||||
if( resolvedEntries.size() != entries.size() )
|
||||
{
|
||||
std::cerr << "ERROR: failed to resolve all entries! (got: " << resolvedEntries.size() << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// finally patch the string with the resolved symbol data
|
||||
for (size_t i = 0; i < resolvedEntries.size(); ++i)
|
||||
{
|
||||
FrameEntry& frameEntry = entries[i];
|
||||
const SymbolEntry& symbolEntry = resolvedEntries[i];
|
||||
|
||||
tracy::CallstackFrame& frame = *frameEntry.frame;
|
||||
if(!symbolEntry.name.length())
|
||||
continue;
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
const char* nameStr = worker.GetString(frame.name);
|
||||
std::cout << "patching '" << nameStr << "' of '" << imageName << "' -> '" << symbolEntry.name << "'" << std::endl;
|
||||
}
|
||||
|
||||
frame.name = AddSymbolString(worker, symbolEntry.name.c_str());
|
||||
const char* newName = worker.GetString(frame.name);
|
||||
|
||||
if(symbolEntry.file.length())
|
||||
{
|
||||
frame.file = AddSymbolString(worker, symbolEntry.file.c_str());
|
||||
frame.line = symbolEntry.line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
41
tracy-edit/src/OfflineSymbolResolver.h
Normal file
41
tracy-edit/src/OfflineSymbolResolver.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __SYMBOLRESOLVER_HPP__
|
||||
#define __SYMBOLRESOLVER_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
struct CallstackFrame;
|
||||
class Worker;
|
||||
}
|
||||
|
||||
class SymbolResolver;
|
||||
|
||||
SymbolResolver* CreateResolver();
|
||||
void DestroySymbolResolver(SymbolResolver* resolver);
|
||||
|
||||
struct FrameEntry
|
||||
{
|
||||
tracy::CallstackFrame* frame = nullptr;
|
||||
uint64_t symbolOffset = 0;
|
||||
};
|
||||
|
||||
using FrameEntryList = std::vector<FrameEntry>;
|
||||
|
||||
struct SymbolEntry
|
||||
{
|
||||
std::string name;
|
||||
std::string file;
|
||||
int line = 0;
|
||||
};
|
||||
|
||||
using SymbolEntryList = std::vector<SymbolEntry>;
|
||||
|
||||
bool ResolveSymbols(SymbolResolver* resolver, const char* imageName,
|
||||
const FrameEntryList& inputEntryList,
|
||||
SymbolEntryList& resolvedEntries);
|
||||
|
||||
bool PatchSymbols(SymbolResolver* resolver, tracy::Worker& worker, bool verbose = false);
|
||||
|
||||
#endif // __SYMBOLRESOLVER_HPP__
|
124
tracy-edit/src/OfflineSymbolResolverAddr2Line.cpp
Normal file
124
tracy-edit/src/OfflineSymbolResolverAddr2Line.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#ifdef __linux
|
||||
|
||||
#include "OfflineSymbolResolver.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
|
||||
std::string ExecShellCommand(const char* cmd)
|
||||
{
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
||||
if (!pipe)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
||||
{
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class SymbolResolver
|
||||
{
|
||||
public:
|
||||
SymbolResolver(const std::string& addr2linePath)
|
||||
: m_addr2LinePath(addr2linePath)
|
||||
{}
|
||||
|
||||
bool ResolveSymbols(const char* imageName, const FrameEntryList& inputEntryList,
|
||||
SymbolEntryList& resolvedEntries)
|
||||
{
|
||||
// generate a single addr2line cmd line for all addresses in one invocation
|
||||
std::stringstream ss;
|
||||
ss << m_addr2LinePath << " -C -f -e " << imageName << " -a ";
|
||||
for (const FrameEntry& entry : inputEntryList)
|
||||
{
|
||||
ss << " 0x" << std::hex << entry.symbolOffset;
|
||||
}
|
||||
|
||||
std::string resultStr = ExecShellCommand(ss.str().c_str());
|
||||
std::stringstream result(resultStr);
|
||||
//printf("executing: '%s' got '%s'\n", ss.str().c_str(), result.str().c_str());
|
||||
|
||||
// The output is 2 lines per entry with the following contents:
|
||||
// hex_address_of_symbol
|
||||
// symbol_name
|
||||
// file:line
|
||||
|
||||
for (size_t i = 0; i < inputEntryList.size(); ++i)
|
||||
{
|
||||
const FrameEntry& inputEntry = inputEntryList[i];
|
||||
|
||||
SymbolEntry newEntry;
|
||||
|
||||
std::string addr;
|
||||
std::getline(result, addr);
|
||||
std::getline(result, newEntry.name);
|
||||
if (newEntry.name == "??")
|
||||
{
|
||||
newEntry.name = "[unknown] + " + std::to_string(inputEntry.symbolOffset);
|
||||
}
|
||||
|
||||
std::string fileLine;
|
||||
std::getline(result, fileLine);
|
||||
if (fileLine != "??:?")
|
||||
{
|
||||
size_t pos = fileLine.find_last_of(':');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
newEntry.file = fileLine.substr(0, pos);
|
||||
std::string lineStr = fileLine.substr(pos + 1);
|
||||
char* after = nullptr;
|
||||
newEntry.line = strtol(lineStr.c_str(), &after, 10);
|
||||
}
|
||||
}
|
||||
|
||||
resolvedEntries.push_back(std::move(newEntry));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_addr2LinePath;
|
||||
};
|
||||
|
||||
SymbolResolver* CreateResolver()
|
||||
{
|
||||
std::stringstream result(ExecShellCommand("which addr2line"));
|
||||
std::string addr2LinePath;
|
||||
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 char* imageName,
|
||||
const FrameEntryList& inputEntryList, SymbolEntryList& resolvedEntries)
|
||||
{
|
||||
if (resolver)
|
||||
{
|
||||
return resolver->ResolveSymbols(imageName, inputEntryList, resolvedEntries);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // #ifdef __linux
|
142
tracy-edit/src/OfflineSymbolResolverDbgHelper.cpp
Normal file
142
tracy-edit/src/OfflineSymbolResolverDbgHelper.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
#include "OfflineSymbolResolver.h"
|
||||
|
||||
class SymbolResolver
|
||||
{
|
||||
public:
|
||||
SymbolResolver()
|
||||
{
|
||||
m_procHandle = GetCurrentProcess();
|
||||
|
||||
if (!SymInitialize(m_procHandle, NULL, FALSE))
|
||||
{
|
||||
std::cerr << "SymInitialize() failed with: " << GetLastErrorString() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
const DWORD symopts = SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES;
|
||||
SymSetOptions( symopts );
|
||||
}
|
||||
}
|
||||
|
||||
~SymbolResolver()
|
||||
{
|
||||
SymCleanup( m_procHandle );
|
||||
}
|
||||
|
||||
bool ResolveSymbolsForModule(const char* fileName, const FrameEntryList& inputEntryList,
|
||||
SymbolEntryList& resolvedEntries)
|
||||
{
|
||||
ULONG64 moduleBase = SymLoadModuleEx( m_procHandle, NULL, fileName, NULL, 0, 0, NULL, 0 );
|
||||
if (!moduleBase)
|
||||
{
|
||||
std::cerr << "SymLoadModuleEx() failed for module " << fileName
|
||||
<< ": " << GetLastErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < inputEntryList.size(); ++i)
|
||||
{
|
||||
uint64_t offset = inputEntryList[i].symbolOffset;
|
||||
DWORD64 address = moduleBase + offset;
|
||||
|
||||
SYMBOL_INFO* symbolInfo = (SYMBOL_INFO*)s_symbolResolutionBuffer;
|
||||
symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
symbolInfo->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
SymbolEntry newEntry;
|
||||
|
||||
if ( SymFromAddr( m_procHandle, address, NULL, symbolInfo ) )
|
||||
{
|
||||
newEntry.name = symbolInfo->Name;
|
||||
//std::cout << "Resolved symbol to: '" << newEntry.name << "'" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
newEntry.name = "[unknown] + " + std::to_string(offset);
|
||||
}
|
||||
|
||||
IMAGEHLP_LINE lineInfo = { 0 };
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
DWORD displaceMent = 0;
|
||||
if ( SymGetLineFromAddr64( m_procHandle, address, &displaceMent, &lineInfo ) )
|
||||
{
|
||||
newEntry.file = lineInfo.FileName;
|
||||
newEntry.line = int(lineInfo.LineNumber);
|
||||
///std::cout << "\tline_file: " lineInfo.FileName << ":" << int(lineInfo.LineNumber) << std::endl;
|
||||
}
|
||||
|
||||
resolvedEntries.push_back(std::move(newEntry));
|
||||
}
|
||||
|
||||
SymUnloadModule64(m_procHandle, moduleBase);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_t symbolResolutionBufferSize = sizeof(SYMBOL_INFO) + MAX_SYM_NAME;
|
||||
static char s_symbolResolutionBuffer[symbolResolutionBufferSize];
|
||||
|
||||
std::string GetLastErrorString()
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if (error == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
LPSTR messageBuffer = nullptr;
|
||||
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||
size_t size = FormatMessageA( dwFlags, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)&messageBuffer, 0, NULL );
|
||||
|
||||
std::string message(messageBuffer, size);
|
||||
LocalFree(messageBuffer);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
HANDLE m_procHandle = nullptr;
|
||||
};
|
||||
|
||||
char SymbolResolver::s_symbolResolutionBuffer[symbolResolutionBufferSize];
|
||||
|
||||
|
||||
SymbolResolver* CreateResolver()
|
||||
{
|
||||
SymbolResolver* resolver = new SymbolResolver();
|
||||
return resolver;
|
||||
}
|
||||
|
||||
void DestroySymbolResolver(SymbolResolver* resolver)
|
||||
{
|
||||
delete resolver;
|
||||
}
|
||||
|
||||
bool ResolveSymbols(SymbolResolver* resolver, const char* imageName,
|
||||
const FrameEntryList& inputEntryList,
|
||||
SymbolEntryList& resolvedEntries)
|
||||
{
|
||||
if( resolver )
|
||||
{
|
||||
return resolver->ResolveSymbolsForModule( imageName, inputEntryList, resolvedEntries );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // #ifdef _WIN32
|
181
tracy-edit/src/tracy-edit.cpp
Normal file
181
tracy-edit/src/tracy-edit.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../server/TracyFileRead.hpp"
|
||||
#include "../../server/TracyFileWrite.hpp"
|
||||
#include "../../server/TracyWorker.hpp"
|
||||
#include "../../getopt/getopt.h"
|
||||
|
||||
#include "OfflineSymbolResolver.h"
|
||||
|
||||
struct Args
|
||||
{
|
||||
const char* inputTracyPath = nullptr;
|
||||
const char* outputTracyPath = nullptr;
|
||||
bool verbose = false;
|
||||
bool resolveSymbols = false;
|
||||
tracy::FileWrite::Compression compressionType = tracy::FileWrite::Compression::Zstd;
|
||||
int compressionLevel = 5;
|
||||
};
|
||||
|
||||
void PrintUsageAndExit()
|
||||
{
|
||||
std::cerr << "Modify a tracy file" << std::endl;
|
||||
std::cerr << "Usage:" << std::endl;
|
||||
std::cerr << " extract [OPTION...] <input trace file> <output tracy file>" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " -h, --help Print usage" << std::endl;
|
||||
std::cerr << " -v, --verbose Enable verbose logging" << std::endl;
|
||||
std::cerr << " -r, --resolveSymbols Resolve symbols and patch callstack frames" << std::endl;
|
||||
std::cerr << " -c, --compression arg Compress output with the given compression algo" << std::endl;
|
||||
std::cerr << " -l, --compressesionLevel arg Level of compression" << std::endl;
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
static const char* compressionTypeStr[]
|
||||
{
|
||||
"Fast",
|
||||
"Slow",
|
||||
"Extreme",
|
||||
"Zstd"
|
||||
};
|
||||
static_assert( uint32_t(tracy::FileWrite::Compression::Zstd)+1 == sizeof(compressionTypeStr)/sizeof(compressionTypeStr[0]));
|
||||
tracy::FileWrite::Compression getCompressionFromString(const char* str)
|
||||
{
|
||||
for( uint32_t i = 0; i < sizeof(compressionTypeStr)/sizeof(compressionTypeStr[0]); ++i )
|
||||
{
|
||||
if( strcmp( compressionTypeStr[i], str ) == 0 )
|
||||
{
|
||||
return tracy::FileWrite::Compression( i );
|
||||
}
|
||||
}
|
||||
return tracy::FileWrite::Compression::Zstd;
|
||||
}
|
||||
|
||||
Args ParseArgs( int argc, char** argv )
|
||||
{
|
||||
if ( argc < 3 )
|
||||
{
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
|
||||
Args args;
|
||||
|
||||
struct option long_opts[] =
|
||||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "resolveSymbols", no_argument, NULL, 'r' },
|
||||
{ "compression", required_argument, NULL, 'c' },
|
||||
{ "compressesionLevel", required_argument, NULL, 'l' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int c;
|
||||
while ( (c = getopt_long( argc, argv, "hvrc:l:", long_opts, NULL )) != -1 )
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h':
|
||||
PrintUsageAndExit();
|
||||
break;
|
||||
case 'v':
|
||||
args.verbose = true;
|
||||
break;
|
||||
case 'r':
|
||||
args.resolveSymbols = true;
|
||||
break;
|
||||
case 'c':
|
||||
args.compressionType = getCompressionFromString( optarg );
|
||||
break;
|
||||
case 'l':
|
||||
args.compressionLevel = atoi( optarg );
|
||||
break;
|
||||
default:
|
||||
PrintUsageAndExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != optind + 2)
|
||||
{
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
|
||||
args.inputTracyPath = argv[optind + 0];
|
||||
args.outputTracyPath = argv[optind + 1];
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if( !AttachConsole( ATTACH_PARENT_PROCESS ) )
|
||||
{
|
||||
AllocConsole();
|
||||
SetConsoleMode( GetStdHandle( STD_OUTPUT_HANDLE ), 0x07 );
|
||||
}
|
||||
#endif // #ifdef _WIN32
|
||||
|
||||
Args args = ParseArgs( argc, argv );
|
||||
|
||||
// load input tracy file
|
||||
auto f = std::unique_ptr<tracy::FileRead>(tracy::FileRead::Open( args.inputTracyPath ));
|
||||
if (!f)
|
||||
{
|
||||
std::cerr << "Could not open file: " << args.inputTracyPath;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Reading ..." << std::endl;
|
||||
|
||||
const bool allowBgThreads = false;
|
||||
bool allowStringModification = true;
|
||||
tracy::Worker worker( *f, tracy::EventType::All, allowBgThreads, allowStringModification );
|
||||
|
||||
std::cout << "Loaded." << std::endl;
|
||||
|
||||
// attempt to resolve symbols only if requested
|
||||
if(args.resolveSymbols)
|
||||
{
|
||||
std::cout << "Resolving and patching symbols..." << std::endl;
|
||||
|
||||
SymbolResolver* resolver = CreateResolver();
|
||||
if(!resolver)
|
||||
{
|
||||
std::cerr << "Failed to create symbol resolver - skipping resolving" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
PatchSymbols(resolver, worker);
|
||||
DestroySymbolResolver(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
// save out capture file with new compression options
|
||||
std::cout << "Saving (using '" << compressionTypeStr[uint32_t(args.compressionType)]
|
||||
<< "', level: " << args.compressionLevel << ") ..." << std::endl;
|
||||
|
||||
auto w = std::unique_ptr<tracy::FileWrite>(
|
||||
tracy::FileWrite::Open( args.outputTracyPath, args.compressionType, args.compressionLevel) );
|
||||
if( !w )
|
||||
{
|
||||
std::cerr << "Cannot open output file: '" << args.outputTracyPath << "'" << std::endl;
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
worker.Write( *w, false );
|
||||
|
||||
std::cout << "Cleanup..." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user