@@ -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-
360372void 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
424448void 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
533554void EndCallstack ()
534555{
556+ DestroyImageCaches ();
535557}
536558
537559const 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
576598struct 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;
812823int cb_num;
813824CallstackEntry cb_data[MaxCbTrace];
814825int 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
820828debuginfod_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()
11071114void 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