Skip to content

Commit

Permalink
Fix a segfault when _dyld_shared_cache_contains_path is not available
Browse files Browse the repository at this point in the history
The _dyld_shared_cache_contains_path is only available in macOS 11.0 or
later. As we are compiling in a new system that's newer than 11.0 but
setting the deployment target to an older version, it's possible that
the _dyld_shared_cache_contains_path is not available in the target
platform and in that case we will segfault when calling it. It's also
possible that when compiling memray in an old system
_dyld_shared_cache_contains_path is not even prototyped in the headers.

To handle this, we change to fetch the function via a dlopen/dlsym
approach that will be generic in all macOS versions at the cost of an
extra call to dlopen the first time we interpose symbols.

Signed-off-by: Pablo Galindo <[email protected]>
  • Loading branch information
pablogsal committed May 30, 2024
1 parent 0e3673d commit 7337dae
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
1 change: 1 addition & 0 deletions news/615.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a crash in old macOS versions (<11.0) due to the inavailability of some linker cache APIs.
18 changes: 17 additions & 1 deletion src/memray/_memray/macho_shenanigans.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,23 @@ patch_symbols_in_shared_object(
unsigned int section_type = section->flags & SECTION_TYPE;
LOG(DEBUG) << "Considering section " << i << " (" << section->segname << ":"
<< section->sectname << ")";
if (_dyld_shared_cache_contains_path(image_name) && strcmp(section->segname, SEG_TEXT) == 0)

// dlopen with null and check for _dyld_shared_cache_contains_path but do it only
// once with std::once_flag
static std::function<bool(const char*)> dyld_shared_cache_contains_path;
static std::once_flag _dyld_shared_cache_check_flag;
std::call_once(_dyld_shared_cache_check_flag, [&]() {
void* handle = dlopen(nullptr, RTLD_LAZY);
dyld_shared_cache_contains_path = (bool(*)(const char *))(
dlsym(handle, "_dyld_shared_cache_contains_path")
);
dlclose(handle);
});


if (dyld_shared_cache_contains_path &&
_dyld_shared_cache_contains_path(image_name) &&
strcmp(section->segname, SEG_TEXT) == 0)
{
// Shared libraries that are part of the shared cache will have the symbols we are
// looking for in the __stubs/__auth_stubs PLT section pointing to a GOT that we cannot
Expand Down

0 comments on commit 7337dae

Please sign in to comment.