From e89d4343466b59b7da1508cc1e5480155120fecb Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 21 Oct 2024 02:51:18 +0100 Subject: [PATCH] Fix symbol resolution for malloc_type functions on macOS Sequoia This commit addresses an issue with symbol resolution for malloc_type functions on the latest macOS Sequoia. The problem arises due to changes in how these functions are named in the dynamic symbol table of the system libraries that are part of the linker cache like the ones that contain the C++ runtime. This fix ensures that Memray correctly intercepts and tracks allocations made by malloc_type functions, fixing tracking allocations in the C++ runtime and other system libraries on macOS Sequoia. Signed-off-by: Pablo Galindo --- src/memray/_memray/macho_shenanigans.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/memray/_memray/macho_shenanigans.cpp b/src/memray/_memray/macho_shenanigans.cpp index fc310eb831..d725b453d3 100644 --- a/src/memray/_memray/macho_shenanigans.cpp +++ b/src/memray/_memray/macho_shenanigans.cpp @@ -36,6 +36,19 @@ patch_symbol( } } +static inline const char* +get_canonical_name(const char* name) +{ + // In macOS 15 (Sequoia)+, the symbols in the shared cache have a prefix + // "_malloc_type" that we need to remove to match the symbols that we + // are looking for. + const char* prefix = "_malloc_type"; + if (strncmp(name, prefix, strlen(prefix)) != 0) { + return name; + } + return name + strlen(prefix); +} + static void patch_symbols_in_section( const section_t* section, @@ -49,8 +62,9 @@ patch_symbols_in_section( if (!symbol_name || !(symbol_name[0] == '_' || symbol_name[0] == '.') || !symbol_name[1]) { continue; } + const char* canonical_name = get_canonical_name(symbol_name); #define FOR_EACH_HOOKED_FUNCTION(hookname) \ - if (strcmp(MEMRAY_ORIG(hookname).d_symbol, symbol_name + 1) == 0) { \ + if (strcmp(MEMRAY_ORIG(hookname).d_symbol, canonical_name + 1) == 0) { \ LOG(DEBUG) << "Patching " << symbol_name << " symbol pointer at " << std::hex << std::showbase \ << *(symbol_addr_table + i) << " for relocation entry " << (symbol_addr_table + i); \ patch_symbol( \ @@ -225,9 +239,10 @@ patch_stubs( if (!symbol_name || !(symbol_name[0] == '_' || symbol_name[0] == '.') || !symbol_name[1]) { continue; } + const char* canonical_name = get_canonical_name(symbol_name); auto stub_addr = reinterpret_cast(symbol_addr_table + i * element_size); #define FOR_EACH_HOOKED_FUNCTION(hookname) \ - if (strcmp(MEMRAY_ORIG(hookname).d_symbol, symbol_name + 1) == 0) { \ + if (strcmp(MEMRAY_ORIG(hookname).d_symbol, canonical_name + 1) == 0) { \ LOG(DEBUG) << "Extracting symbol address for " << symbol_name << " from stub function at " \ << std::hex << std::showbase << stub_addr; \ void* symbol_addr = reinterpret_cast(lazy_pointer_from_stub(stub_addr)); \