From 4bf9a8cecc02b462b5e0ceec3a9ded45d33ce323 Mon Sep 17 00:00:00 2001 From: trodrigues Date: Fri, 3 May 2024 16:05:59 -0500 Subject: [PATCH] Instead of calling dladdr inside the dl_iterate_phdr callback, do it outside to avoid deadlocks with other loader code --- public/client/TracyCallstack.cpp | 58 ++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/public/client/TracyCallstack.cpp b/public/client/TracyCallstack.cpp index 10b23e6e..b55a385c 100644 --- a/public/client/TracyCallstack.cpp +++ b/public/client/TracyCallstack.cpp @@ -135,7 +135,8 @@ public: private: tracy::FastVector m_images; - bool m_updated; + bool m_updated = false; + bool m_haveMainImageName = false; static int Callback( struct dl_phdr_info* info, size_t size, void* data ) { @@ -153,26 +154,13 @@ private: image->m_startAddress = startAddress; image->m_endAddress = endAddress; - const char* imageName = nullptr; - // the base executable name isn't provided when iterating with dl_iterate_phdr, get it with dladdr() + // the base executable name isn't provided when iterating with dl_iterate_phdr, + // we will have to patch the executable image name outside this callback if( info->dlpi_name && info->dlpi_name[0] != '\0' ) { - imageName = info->dlpi_name; - } - else - { - Dl_info dlInfo; - if( dladdr( (void *)info->dlpi_addr, &dlInfo ) ) - { - imageName = dlInfo.dli_fname; - } - } - - if( imageName ) - { - size_t sz = strlen( imageName ) + 1; + size_t sz = strlen( info->dlpi_name ) + 1; image->m_name = (char*)tracy_malloc( sz ); - memcpy( image->m_name, imageName, sz ); + memcpy( image->m_name, info->dlpi_name, sz ); } else { @@ -198,9 +186,42 @@ private: { std::sort( m_images.begin(), m_images.end(), []( const ImageEntry& lhs, const ImageEntry& rhs ) { return lhs.m_startAddress > rhs.m_startAddress; } ); + + // patch the main executable image name here, as calling dl_* functions inside the dl_iterate_phdr callback might cause deadlocks + UpdateMainImageName(); } } + void UpdateMainImageName() + { + if( m_haveMainImageName ) + { + return; + } + + for( ImageEntry& entry : m_images ) + { + if( entry.m_name == nullptr ) + { + Dl_info dlInfo; + if( dladdr( (void *)entry.m_startAddress, &dlInfo ) ) + { + if( dlInfo.dli_fname ) + { + size_t sz = strlen( dlInfo.dli_fname ) + 1; + entry.m_name = (char*)tracy_malloc( sz ); + memcpy( entry.m_name, dlInfo.dli_fname, sz ); + } + } + + // we only expect one entry to be null for the main executable entry + break; + } + } + + m_haveMainImageName = true; + } + const ImageEntry* GetImageForAddressImpl( void* address ) const { auto it = std::lower_bound( m_images.begin(), m_images.end(), address, @@ -221,6 +242,7 @@ private: } m_images.clear(); + m_haveMainImageName = false; } }; #endif //#ifdef TRACY_USE_IMAGE_CACHE