From 5745b489a2d726302eeaeff206f5b4d749f00932 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Thu, 25 Jun 2026 22:09:45 +0300 Subject: [PATCH] callstack: Calculate end address from highest LOAD header Headers aren't guaranteed to be sorted in final address order. For example, from readelf -lW of a .so built with clang: Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000230 0x000230 R 0x8 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x5e8274 0x5e8274 R 0x1000 LOAD 0x5e8280 0x00000000005e9280 0x00000000005e9280 0x51e990 0x51e990 R E 0x1000 LOAD 0xb06c10 0x0000000000b08c10 0x0000000000b08c10 0x031628 0x0323f0 RW 0x1000 LOAD 0xb38240 0x0000000000b3b240 0x0000000000b3b240 0x009aa8 0x011c40 RW 0x1000 DYNAMIC 0xb32270 0x0000000000b34270 0x0000000000b34270 0x000410 0x000410 RW 0x8 GNU_RELRO 0xb06c10 0x0000000000b08c10 0x0000000000b08c10 0x031628 0x0323f0 R 0x1 GNU_EH_FRAME 0x4e8360 0x00000000004e8360 0x00000000004e8360 0x029cf4 0x029cf4 R 0x4 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0 NOTE 0x000270 0x0000000000000270 0x0000000000000270 0x000024 0x000024 R 0x4 --- public/client/TracyCallstack.cpp | 15 ++++++++++++--- public/libbacktrace/elf.cpp | 14 +++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/public/client/TracyCallstack.cpp b/public/client/TracyCallstack.cpp index 9095d847..59c4182f 100644 --- a/public/client/TracyCallstack.cpp +++ b/public/client/TracyCallstack.cpp @@ -237,9 +237,18 @@ private: if( cache->ContainsImage( startAddress ) ) return 0; const uint32_t headerCount = info->dlpi_phnum; - assert( headerCount > 0); - const auto endAddress = static_cast( info->dlpi_addr + - info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz); + assert( headerCount > 0 ); + + // headers aren't guaranteed to be in address order; find the max + uint64_t endAddress = startAddress; + for( uint32_t i=0; idlpi_phdr[i]; + if( phdr.p_type != PT_LOAD ) continue; + + const auto phdrEnd = static_cast( info->dlpi_addr + phdr.p_vaddr + phdr.p_memsz ); + endAddress = std::max( phdrEnd, endAddress ); + } ImageEntry image{}; image.m_startAddress = startAddress; diff --git a/public/libbacktrace/elf.cpp b/public/libbacktrace/elf.cpp index 5f45b4e6..6d54ecff 100644 --- a/public/libbacktrace/elf.cpp +++ b/public/libbacktrace/elf.cpp @@ -7410,9 +7410,17 @@ phdr_callback_mock (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, ptr->dlpi_addr = info->dlpi_addr; // calculate the end address as well, so we can quickly determine if a PC is within the range of this image - ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr) + (info->dlpi_phnum ? uintptr_t( - info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + - info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz) : 0); + // headers aren't guaranteed to be in address order; find the max + ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr); + for (uint32_t i = 0; i < info->dlpi_phnum; i++) + { + const auto &phdr = info->dlpi_phdr[i]; + if (phdr.p_type != PT_LOAD) + continue; + + const auto phdr_end = uintptr_t(info->dlpi_addr + phdr.p_vaddr + phdr.p_memsz); + ptr->dlpi_end_addr = std::max(phdr_end, ptr->dlpi_end_addr); + } return 0; }