Skip to content

Commit 903cde5

Browse files
committed
Replace windows caches with ImageCache
- Introduce both s_imageCache and s_krnlCache on all platforms, even if unused (will be reused later to unify platforms handling) - This means that what userland images that used to be unsorted are now sorted
1 parent e1e9fb6 commit 903cde5

File tree

1 file changed

+89
-86
lines changed

1 file changed

+89
-86
lines changed

‎public/client/TracyCallstack.cpp‎

Lines changed: 89 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,40 @@ class ImageCacheDlIteratePhdr : public ImageCache
294294
m_haveMainImageName = false;
295295
}
296296
};
297+
using UserlandImageCache = ImageCacheDlIteratePhdr;
298+
#else
299+
using UserlandImageCache = ImageCache;
297300
#endif //#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
298301

302+
static UserlandImageCache* s_imageCache;
303+
static ImageCache* s_krnlCache;
304+
305+
void CreateImageCaches()
306+
{
307+
assert( s_imageCache == nullptr && s_krnlCache == nullptr );
308+
s_imageCache = new ( tracy_malloc( sizeof( UserlandImageCache ) ) ) UserlandImageCache();
309+
s_krnlCache = new ( tracy_malloc( sizeof( ImageCache ) ) ) ImageCache();
310+
}
311+
312+
void DestroyImageCaches()
313+
{
314+
if( s_krnlCache != nullptr )
315+
{
316+
s_krnlCache->~ImageCache();
317+
tracy_free( s_krnlCache );
318+
s_krnlCache = nullptr;
319+
}
320+
321+
if( s_imageCache != nullptr )
322+
{
323+
s_imageCache->~UserlandImageCache();
324+
tracy_free( s_imageCache );
325+
s_imageCache = nullptr;
326+
}
327+
328+
}
329+
330+
299331
// when "TRACY_SYMBOL_OFFLINE_RESOLVE" is set, instead of fully resolving symbols at runtime,
300332
// simply resolve the offset and image name (which will be enough the resolving to be done offline)
301333
#ifdef TRACY_SYMBOL_OFFLINE_RESOLVE
@@ -337,26 +369,6 @@ extern "C"
337369
}
338370
}
339371

340-
struct ModuleCache
341-
{
342-
uint64_t start;
343-
uint64_t end;
344-
char* name;
345-
};
346-
347-
static FastVector<ModuleCache>* s_modCache;
348-
349-
350-
struct KernelDriver
351-
{
352-
uint64_t addr;
353-
const char* mod;
354-
const char* path;
355-
};
356-
357-
KernelDriver* s_krnlCache = nullptr;
358-
size_t s_krnlCacheCnt;
359-
360372
void InitCallstackCritical()
361373
{
362374
___tracy_RtlWalkFrameChainPtr = (___tracy_t_RtlWalkFrameChain)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlWalkFrameChain" );
@@ -390,35 +402,47 @@ DWORD64 DbgHelpLoadSymbolsForModule( const char* imageName, uint64_t baseOfDll,
390402
return SymLoadModuleEx( GetCurrentProcess(), nullptr, imageName, nullptr, baseOfDll, bllSize, nullptr, 0 );
391403
}
392404

393-
ModuleCache* LoadSymbolsForModuleAndCache( const char* imageName, uint32_t imageNameLength, uint64_t baseOfDll, uint32_t dllSize )
405+
char* FormatImageName( const char* imageName, uint32_t imageNameLength )
394406
{
395-
DbgHelpLoadSymbolsForModule( imageName, baseOfDll, dllSize );
396-
397-
ModuleCache* cachedModule = s_modCache->push_next();
398-
cachedModule->start = baseOfDll;
399-
cachedModule->end = baseOfDll + dllSize;
400-
401407
// when doing offline symbol resolution, we must store the full path of the dll for the resolving to work
402408
if( s_shouldResolveSymbolsOffline )
403-
{
404-
cachedModule->name = (char*)tracy_malloc_fast(imageNameLength + 1);
405-
memcpy(cachedModule->name, imageName, imageNameLength);
406-
cachedModule->name[imageNameLength] = '\0';
409+
{
410+
char* alloc = (char*)tracy_malloc_fast( imageNameLength + 1 );
411+
memcpy( alloc, imageName, imageNameLength );
412+
alloc[imageNameLength] = '\0';
413+
return alloc;
407414
}
408415
else
409416
{
410-
auto ptr = imageName + imageNameLength;
411-
while (ptr > imageName && *ptr != '\\' && *ptr != '/') ptr--;
412-
if (ptr > imageName) ptr++;
417+
const char* ptr = imageName + imageNameLength;
418+
while( ptr > imageName && *ptr != '\\' && *ptr != '/' ) ptr--;
419+
if( ptr > imageName ) ptr++;
413420
const auto namelen = imageName + imageNameLength - ptr;
414-
cachedModule->name = (char*)tracy_malloc_fast(namelen + 3);
415-
cachedModule->name[0] = '[';
416-
memcpy(cachedModule->name + 1, ptr, namelen);
417-
cachedModule->name[namelen + 1] = ']';
418-
cachedModule->name[namelen + 2] = '\0';
421+
422+
char* alloc = (char*)tracy_malloc_fast( namelen + 3 );
423+
alloc[0] = '[';
424+
memcpy( alloc + 1, ptr, namelen );
425+
alloc[namelen + 1] = ']';
426+
alloc[namelen + 2] = '\0';
427+
return alloc;
419428
}
429+
}
430+
431+
ImageEntry* CacheModuleInfo( const char* imagePath, uint32_t imageNameLength, uint64_t baseOfDll, uint32_t dllSize )
432+
{
433+
ImageEntry moduleEntry = {};
434+
moduleEntry.m_startAddress = baseOfDll;
435+
moduleEntry.m_endAddress = baseOfDll + dllSize;
436+
moduleEntry.m_path = CopyStringFast( imagePath, imageNameLength );
437+
moduleEntry.m_name = FormatImageName( imagePath, imageNameLength );
420438

421-
return cachedModule;
439+
return s_imageCache->AddEntry( moduleEntry );
440+
}
441+
442+
ImageEntry* LoadSymbolsForModuleAndCache( const char* imagePath, uint32_t imageNameLength, uint64_t baseOfDll, uint32_t dllSize )
443+
{
444+
DbgHelpLoadSymbolsForModule( imagePath, baseOfDll, dllSize );
445+
return CacheModuleInfo( imagePath, imageNameLength, baseOfDll, dllSize );
422446
}
423447

424448
void InitCallstack()
@@ -431,6 +455,8 @@ void InitCallstack()
431455
TracyDebug("TRACY: enabling offline symbol resolving!\n");
432456
}
433457

458+
CreateImageCaches();
459+
434460
DbgHelpInit();
435461

436462
#ifdef TRACY_DBGHELP_LOCK
@@ -457,8 +483,6 @@ void InitCallstack()
457483
const auto windirlen = strlen( windir );
458484

459485
const auto sz = needed / sizeof( LPVOID );
460-
s_krnlCache = (KernelDriver*)tracy_malloc( sizeof(KernelDriver) * sz );
461-
int cnt = 0;
462486
for( size_t i=0; i<sz; i++ )
463487
{
464488
char fn[MAX_PATH];
@@ -469,7 +493,12 @@ void InitCallstack()
469493
buf[0] = '<';
470494
memcpy( buf+1, fn, len );
471495
memcpy( buf+len+1, ">", 2 );
472-
s_krnlCache[cnt] = KernelDriver { (uint64_t)dev[i], buf };
496+
497+
ImageEntry kernelDriver{};
498+
kernelDriver.m_startAddress = (uint64_t)dev[i];
499+
kernelDriver.m_endAddress = 0;
500+
kernelDriver.m_name = buf;
501+
kernelDriver.m_path = nullptr;
473502

474503
const auto len = GetDeviceDriverFileNameA( dev[i], fn, sizeof( fn ) );
475504
if( len != 0 )
@@ -485,24 +514,16 @@ void InitCallstack()
485514
}
486515

487516
DbgHelpLoadSymbolsForModule( path, (DWORD64)dev[i], 0 );
488-
489-
const auto psz = strlen( path );
490-
auto pptr = (char*)tracy_malloc_fast( psz+1 );
491-
memcpy( pptr, path, psz );
492-
pptr[psz] = '\0';
493-
s_krnlCache[cnt].path = pptr;
517+
518+
kernelDriver.m_path = CopyString( path );
494519
}
495520

496-
cnt++;
521+
s_krnlCache->AddEntry(kernelDriver);
497522
}
498523
}
499-
s_krnlCacheCnt = cnt;
500-
std::sort( s_krnlCache, s_krnlCache + s_krnlCacheCnt, []( const KernelDriver& lhs, const KernelDriver& rhs ) { return lhs.addr > rhs.addr; } );
524+
s_krnlCache->Sort();
501525
}
502526

503-
s_modCache = (FastVector<ModuleCache>*)tracy_malloc( sizeof( FastVector<ModuleCache> ) );
504-
new(s_modCache) FastVector<ModuleCache>( 512 );
505-
506527
HANDLE proc = GetCurrentProcess();
507528
HMODULE mod[1024];
508529
if( initTimeModuleLoad && EnumProcessModules( proc, mod, sizeof( mod ), &needed ) != 0 )
@@ -532,6 +553,7 @@ void InitCallstack()
532553

533554
void EndCallstack()
534555
{
556+
DestroyImageCaches();
535557
}
536558

537559
const char* DecodeCallstackPtrFast( uint64_t ptr )
@@ -568,9 +590,9 @@ const char* GetKernelModulePath( uint64_t addr )
568590
{
569591
assert( addr >> 63 != 0 );
570592
if( !s_krnlCache ) return nullptr;
571-
auto it = std::lower_bound( s_krnlCache, s_krnlCache + s_krnlCacheCnt, addr, []( const KernelDriver& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } );
572-
if( it == s_krnlCache + s_krnlCacheCnt ) return nullptr;
573-
return it->path;
593+
const ImageEntry* imageEntry = s_krnlCache->GetImageForAddress( addr );
594+
if( imageEntry ) return imageEntry->m_path;
595+
return nullptr;
574596
}
575597

576598
struct ModuleNameAndBaseAddress
@@ -583,24 +605,13 @@ ModuleNameAndBaseAddress GetModuleNameAndPrepareSymbols( uint64_t addr )
583605
{
584606
if( ( addr >> 63 ) != 0 )
585607
{
586-
if( s_krnlCache )
587-
{
588-
auto it = std::lower_bound( s_krnlCache, s_krnlCache + s_krnlCacheCnt, addr, []( const KernelDriver& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } );
589-
if( it != s_krnlCache + s_krnlCacheCnt )
590-
{
591-
return ModuleNameAndBaseAddress{ it->mod, it->addr };
592-
}
593-
}
608+
const ImageEntry* entry = s_krnlCache->GetImageForAddress( addr );
609+
if( entry != nullptr ) return ModuleNameAndBaseAddress{ entry->m_name, entry->m_startAddress };
594610
return ModuleNameAndBaseAddress{ "<kernel>", addr };
595611
}
596612

597-
for( auto& v : *s_modCache )
598-
{
599-
if( addr >= v.start && addr < v.end )
600-
{
601-
return ModuleNameAndBaseAddress{ v.name, v.start };
602-
}
603-
}
613+
const ImageEntry* entry = s_imageCache->GetImageForAddress( addr );
614+
if( entry != nullptr ) return ModuleNameAndBaseAddress{ entry->m_name, entry->m_startAddress };
604615

605616
HANDLE proc = GetCurrentProcess();
606617
// Do not use FreeLibrary because we set the flag GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
@@ -622,8 +633,8 @@ ModuleNameAndBaseAddress GetModuleNameAndPrepareSymbols( uint64_t addr )
622633
if( nameLength > 0 )
623634
{
624635
// since this is the first time we encounter this module, load its symbols (needed for modules loaded after SymInitialize)
625-
ModuleCache* cachedModule = LoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );
626-
return ModuleNameAndBaseAddress{ cachedModule->name, cachedModule->start };
636+
ImageEntry* cachedModule = LoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );
637+
return ModuleNameAndBaseAddress{ cachedModule->m_name, cachedModule->m_startAddress };
627638
}
628639
}
629640
}
@@ -812,9 +823,6 @@ struct backtrace_state* cb_bts = nullptr;
812823
int cb_num;
813824
CallstackEntry cb_data[MaxCbTrace];
814825
int cb_fixup;
815-
#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
816-
static ImageCacheDlIteratePhdr* s_imageCache = nullptr;
817-
#endif //#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
818826

819827
#ifdef TRACY_DEBUGINFOD
820828
debuginfod_client* s_debuginfod;
@@ -1010,8 +1018,7 @@ void InitCallstack()
10101018
InitRpmalloc();
10111019

10121020
#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
1013-
s_imageCache = (ImageCacheDlIteratePhdr*)tracy_malloc( sizeof( ImageCacheDlIteratePhdr ) );
1014-
new(s_imageCache) ImageCacheDlIteratePhdr();
1021+
CreateImageCaches();
10151022
#endif //#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
10161023

10171024
#ifndef TRACY_SYMBOL_OFFLINE_RESOLVE
@@ -1107,11 +1114,7 @@ debuginfod_client* GetDebuginfodClient()
11071114
void EndCallstack()
11081115
{
11091116
#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
1110-
if( s_imageCache )
1111-
{
1112-
s_imageCache->~ImageCacheDlIteratePhdr();
1113-
tracy_free( s_imageCache );
1114-
}
1117+
DestroyImageCaches();
11151118
#endif //#ifdef TRACY_HAS_DL_ITERATE_PHDR_TO_REFRESH_IMAGE_CACHE
11161119
#ifndef TRACY_DEMANGLE
11171120
___tracy_free_demangle_buffer();
@@ -1312,7 +1315,7 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
13121315
if( image )
13131316
{
13141317
imageName = image->m_name;
1315-
imageBaseAddress = uint64_t(image->m_startAddress);
1318+
imageBaseAddress = uint64_t( image->m_startAddress );
13161319
}
13171320
#else
13181321
Dl_info dlinfo;

0 commit comments

Comments
 (0)