-
-
Save liuyi12138/0d22fb8a25772484d6f1641b71829fda to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <dlfcn.h> | |
#include <mach-o/dyld-interposing.h> | |
void dyld_func_lookup(const char *name, void **address); | |
void *dlopen_from(const char *file, int mode, void *caller) __attribute__((weak)); | |
void dlopen_post_hook(const char *file, int mode, void *caller, void *result); | |
void *interposed_dlopen(const char *file, int mode) { | |
void *caller = __builtin_extract_return_addr(__builtin_return_address(0)); | |
void *result; | |
if (Big_Sur) { | |
/* Big Sur literally gives us a function to do what we want. */ | |
result = dlopen_from(file, mode, caller); | |
} else if (Catalina || Mojave) { | |
/* libdyld.dylib sets a "dyld3::ScopedTimer" before and after calling | |
* `__dyld_dlopen_internal`, but we don't have access to the timer and it's | |
* probably just for profiling anyway. | |
*/ | |
void *(*dlopen_internal)(const char *, int, void *); | |
dyld_func_lookup("__dyld_dlopen_internal", (void **)&dlopen_internal); | |
result = dlopen_internal(file, mode, caller); | |
/* Unlike with High Sierra below, I'm not as confident that | |
* `__dyld_dlopen_internal` will always do what we want, so we call the | |
* real `dlopen` function as a backup strategy. | |
*/ | |
if (result == NULL) { | |
result = dlopen(file, mode); | |
} | |
} else if (High_Sierra) { | |
/* Unlike the normal `dlopen` function, `__dyld_dlopen` uses the | |
* caller's *caller's* address rather than that of the caller itself. Note | |
* that this means that this hook must be compiled with | |
* `-fno-omit-frame-pointer`. | |
* | |
* The actual `dlopen` function also has some code to switch to dyld3 if | |
* the app uses dyld3, but according to what I could find on the internet, | |
* dyld3 is only enabled for system apps, and only from 2018 on. | |
*/ | |
void *(*dlopen_internal)(const char *, int); | |
dyld_func_lookup("__dyld_dlopen", (void **)&dlopen_internal) | |
result = dlopen_internal(file, mode); | |
} | |
dlopen_post_hook(file, mode, caller, result); | |
return result; | |
} | |
DYLD_INTERPOSE(interposed_dlopen, dlopen) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment