DYLD_LIBRARY_PATH和DYLD_INSERT_LIBRARIES无法正常工作

我创建一个.dylib文件并编译它:

#define _GNU_SOURCE #include  #include  static void* (*real_malloc)(size_t); void *malloc(size_t size) { void *p = NULL; fprintf(stderr, "malloc(%zd) = ", size); p = real_malloc(size); fprintf(stderr, "%p\n", p); return p; } void __attribute((constructor))init() { real_malloc = (decltype(real_malloc))dlsym(RTLD_NEXT, "malloc"); if (NULL == real_malloc) { fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); return; } } 

然后我创建一个调用malloc的测试程序。 我确保对malloc的调用没有进行优化。

接下来我运行以下内容:

DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest

它加载它但它根本不挂钩function..任何想法? 我在El Capitan升级之前尝试了这段代码并且它曾经工作过..我还让malloc抛出一个exception只是为了看它是否被调用。 不是。

我错过了什么?

结果是:

 sh-3.2# DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest clear dyld: loaded: /Users/Brandon/Desktop/./malloctest dyld: loaded: ./libTestHook.dylib dyld: loaded: /usr/lib/libc++.1.dylib dyld: loaded: /usr/lib/libSystem.B.dylib dyld: loaded: /usr/lib/libc++abi.dylib dyld: loaded: /usr/lib/system/libcache.dylib dyld: loaded: /usr/lib/system/libcommonCrypto.dylib dyld: loaded: /usr/lib/system/libcompiler_rt.dylib dyld: loaded: /usr/lib/system/libcopyfile.dylib dyld: loaded: /usr/lib/system/libcorecrypto.dylib dyld: loaded: /usr/lib/system/libdispatch.dylib dyld: loaded: /usr/lib/system/libdyld.dylib dyld: loaded: /usr/lib/system/libkeymgr.dylib dyld: loaded: /usr/lib/system/liblaunch.dylib dyld: loaded: /usr/lib/system/libmacho.dylib dyld: loaded: /usr/lib/system/libquarantine.dylib dyld: loaded: /usr/lib/system/libremovefile.dylib dyld: loaded: /usr/lib/system/libsystem_asl.dylib dyld: loaded: /usr/lib/system/libsystem_blocks.dylib dyld: loaded: /usr/lib/system/libsystem_c.dylib dyld: loaded: /usr/lib/system/libsystem_configuration.dylib dyld: loaded: /usr/lib/system/libsystem_coreservices.dylib dyld: loaded: /usr/lib/system/libsystem_coretls.dylib dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib dyld: loaded: /usr/lib/system/libsystem_info.dylib dyld: loaded: /usr/lib/system/libsystem_kernel.dylib dyld: loaded: /usr/lib/system/libsystem_m.dylib dyld: loaded: /usr/lib/system/libsystem_malloc.dylib dyld: loaded: /usr/lib/system/libsystem_network.dylib dyld: loaded: /usr/lib/system/libsystem_networkextension.dylib dyld: loaded: /usr/lib/system/libsystem_notify.dylib dyld: loaded: /usr/lib/system/libsystem_platform.dylib dyld: loaded: /usr/lib/system/libsystem_pthread.dylib dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib dyld: loaded: /usr/lib/system/libsystem_secinit.dylib dyld: loaded: /usr/lib/system/libsystem_trace.dylib dyld: loaded: /usr/lib/system/libunc.dylib dyld: loaded: /usr/lib/system/libunwind.dylib dyld: loaded: /usr/lib/system/libxpc.dylib dyld: loaded: /usr/lib/libobjc.A.dylib dyld: loaded: /usr/lib/libauto.dylib dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib A B C D 

我原来post中的代码曾用于优胜美地。 在El Capitan,它不起作用。 我最终做了以下方法( DYLD_INTERPOSE + DYLD_INSERT_LIBRARIES ):

 #define _GNU_SOURCE #include  #include  #include  #define DYLD_INTERPOSE(_replacment,_replacee) \ __attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \ __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee }; void* pMalloc(size_t size) //would be nice if I didn't have to rename my function.. { printf("Allocated: %zu\n", size); return malloc(size); } DYLD_INTERPOSE(pMalloc, malloc); 

来自dyld docs:

DYLD_INSERT_LIBRARIES这是一个冒号分隔的动态库列表,要在程序中指定的动态库之前加载。 这使您可以通过仅使用新模块加载临时动态共享库来测试在平面命名空间映像中使用的现有动态共享库的新模块。 请注意,这对使用动态共享库构建两级命名空间映像的映像没有影响,除非还使用了DYLD_FORCE_FLAT_NAMESPACE。

DYLD_FORCE_FLAT_NAMESPACE强制将程序中的所有图像链接为平面命名空间图像,并忽略任何两级命名空间绑定。 如果使用两级命名空间图像来允许图像具有多个定义的符号,则这可能导致程序无法使用多重定义的符号错误执行。

所以你的代码需要DYLD_FORCE_FLAT_NAMESPACE = 1。 无论如何,只有启用此选项, 我的实现才适用于/usr/local/bin/git

如果您可以重新编译被挂钩的可执行文件,那么我认为更简单的解决方案是使用-force_flat_namespace重新编译可执行文件:

 ➜ clang slow_leak.c -force_flat_namespace -o slow_leak ➜ DYLD_INSERT_LIBRARIES=malloc_hook.dylib ./slow_leak leaking in hooked malloc 

更多信息 这是在OSX 10.12.2 MacOS Sierra上。