Add option to reset callstack frame symbols to the unresolved state

The new `-R` option of tracy-update sets every callstack frame back to `[unresolved]` / `[unknown]`. Since failed lookups leave frames untouched and the image-relative offset in `symAddr` survives patching, this makes it possible to chain several resolution passes over the same capture, each with different `-p` path substitutions (e.g. one pass per symbol directory).
This commit is contained in:
Clément Grégoire
2026-06-05 09:02:17 +02:00
parent 2b11785b05
commit 55d5436fb9
3 changed files with 41 additions and 2 deletions

View File

@@ -47,6 +47,33 @@ tracy::StringIdx AddSymbolString( tracy::Worker& worker, const std::string& str
return tracy::StringIdx( location.idx );
}
void ResetSymbols( tracy::Worker& worker )
{
std::cout << "Resetting callstack frame symbols to the unresolved state..." << std::endl;
const tracy::StringIdx unresolvedName = AddSymbolString( worker, "[unresolved]" );
const tracy::StringIdx unknownFile = AddSymbolString( worker, "[unknown]" );
uint64_t frameCount = 0;
auto& callstackFrameMap = worker.GetCallstackFrameMap();
for( auto it = callstackFrameMap.begin(); it != callstackFrameMap.end(); ++it )
{
if( !it->second ) continue;
tracy::CallstackFrameData& frameData = *it->second;
for( uint8_t f = 0; f < frameData.size; f++ )
{
tracy::CallstackFrame& frame = frameData.data[f];
frame.name = unresolvedName;
frame.file = unknownFile;
frame.line = 0;
++frameCount;
}
}
std::cout << "Reset " << frameCount << " callstack frames." << std::endl;
}
bool PatchSymbolsWithRegex( tracy::Worker& worker, const PathSubstitutionList& pathSubstitutionlist,
const std::string& addr2lineToolPath, const std::string& addr2lineArgs, bool verbose )
{

View File

@@ -51,6 +51,12 @@ bool ResolveSymbolsDbgHelp( const std::string& imagePath, const FrameEntryList&
SymbolEntryList& resolvedEntries );
#endif
// Resets all callstack frame symbols back to the unresolved state ("[unresolved]" / "[unknown]"),
// so a subsequent PatchSymbols pass re-resolves every frame. This is useful to chain several
// resolution passes with different path substitutions. Only meaningful for traces captured with
// TRACY_SYMBOL_OFFLINE_RESOLVE, where each frame's symAddr holds the image-relative offset.
void ResetSymbols( tracy::Worker& worker );
void PatchSymbols( tracy::Worker& worker, const std::vector<std::string>& pathSubstitutionsStrings,
const std::string& addr2lineToolPath = std::string(),
const std::string& addr2lineArgs = std::string(), bool verbose = false );

View File

@@ -38,6 +38,7 @@ void Usage()
printf( " c: context switches, s: sampling data, C: symbol code, S: source cache\n" );
printf( " -c: scan for source files missing in cache and add if found\n" );
printf( " -r: resolve symbols and patch callstack frames\n");
printf( " -R: reset all callstack frame symbols to unresolved (e.g. to re-run resolution)\n");
printf( " -p: substitute symbol resolution path with an alternative: \"REGEX_MATCH;REPLACEMENT\"\n");
printf( " -a: path to a custom addr2line-compatible tool to use for symbol resolution\n");
printf( " -A: extra arguments passed verbatim to the symbol resolution tool,\n");
@@ -65,13 +66,14 @@ int main( int argc, char** argv )
bool buildDict = false;
bool cacheSource = false;
bool resolveSymbols = false;
bool resetSymbols = false;
std::vector<std::string> pathSubstitutions;
std::string addr2lineToolPath;
std::string addr2lineArgs;
bool verboseSymbols = false;
int c;
while( ( c = getopt( argc, argv, "4hez:ds:crp:a:A:vj:" ) ) != -1 )
while( ( c = getopt( argc, argv, "4hez:ds:crRp:a:A:vj:" ) ) != -1 )
{
switch( c )
{
@@ -144,6 +146,9 @@ int main( int argc, char** argv )
case 'r':
resolveSymbols = true;
break;
case 'R':
resetSymbols = true;
break;
case 'p':
pathSubstitutions.push_back(optarg);
break;
@@ -187,7 +192,7 @@ int main( int argc, char** argv )
{
const auto t0 = std::chrono::high_resolution_clock::now();
const bool allowBgThreads = false;
const bool allowStringModification = resolveSymbols;
const bool allowStringModification = resolveSymbols || resetSymbols;
tracy::Worker worker( *f, (tracy::EventType::Type)events, allowBgThreads, allowStringModification );
#ifndef TRACY_NO_STATISTICS
@@ -197,6 +202,7 @@ int main( int argc, char** argv )
const auto t1 = std::chrono::high_resolution_clock::now();
if( cacheSource ) worker.CacheSourceFiles();
if( resetSymbols ) ResetSymbols( worker );
if( resolveSymbols ) PatchSymbols( worker, pathSubstitutions, addr2lineToolPath, addr2lineArgs, verboseSymbols );
auto w = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output, clev, zstdLevel, streams ) );