I'm having trouble getting libfaketime to work with MacOS 12, possibly due to changes in how dyld works. I am using an M1 mac, but it doesn't seem to be related to the architecture.
Repro (from libfaketime repo root):
make
cat <<EOF > monterepro.c
#include <stdio.h>
#include <time.h>
#include <dlfcn.h>
static int (*next_clock_gettime) (clockid_t clk_id, struct timespec *tp);
int main()
{
// This will print 2021
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
printf(ctime(&now));
// clock_gettime was loaded from /usr/lib/system/libsystem_c.dylib
Dl_info dl_info;
dladdr((void *)clock_gettime, &dl_info);
printf("%s\n", dl_info.dli_fname);
// Libfaketime itself works -- the block below prints 2029
void* handle = dlopen("./src/libfaketime.1.dylib", RTLD_LAZY);
next_clock_gettime = dlsym(handle, "clock_gettime");
next_clock_gettime(CLOCK_REALTIME, &now);
printf(ctime(&now));
}
EOF
clang -o monterepro monterepro.c
DYLD_INSERT_LIBRARIES=./src/libfaketime.1.dylib DYLD_FORCE_FLAT_NAMESPACE=YES FAKETIME='@2029-08-14 21:59:54' ./monterepro
At the end of the output, you should see:
Thu Dec 9 xx:xx:xx 2021
/usr/lib/system/libsystem_c.dylib
Tue Aug 14 21:59:54 2029
It looks like not matter what I do, the clock functions are loaded from libsystem_c.dylib. Running with DYLD_PRINT_LIBRARIES=YES shows that libfaketime is indeed being loaded:
Hi @wolfcw
I'm having trouble getting libfaketime to work with MacOS 12, possibly due to changes in how dyld works. I am using an M1 mac, but it doesn't seem to be related to the architecture. Repro (from libfaketime repo root):
At the end of the output, you should see:
It looks like not matter what I do, the clock functions are loaded from libsystem_c.dylib. Running with
DYLD_PRINT_LIBRARIES=YES
shows that libfaketime is indeed being loaded:But
DYLD_PRINT_BINDINGS
suggests libfaketime is not taking precedence:This style of interposition still works with functions from other libraries, but doesn't seem to work with functions from libsystem.
For the record: I had success using this approach: http://toves.freeshell.org/interpose/. By copying this DYLD_INTERPOSE macro from https://opensource.apple.com/source/dyld/dyld-97.1/include/mach-o/dyld-interposing.h.auto.html, renaming
clock_gettime
inlibfaketime.c
tointerposed_clock_gettime
, applyingDYLD_INTERPOSE
to it and callingclock_gettime
directly instead of usingreal_clock_gettime
, I got it to work (as a POC):But it looks like this approach would require a large refactor, and I'm not sure how far it would be in terms of backwards-compatibility.