DYLD_LIBRARY_PATH和DYLD_INSERT_LIBRARIES无法正常工作

Bra*_*don 12 c macos osx-elcapitan

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

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

接下来我运行以下内容:

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

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

我错过了什么?

结果是:

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
Run Code Online (Sandbox Code Playgroud)

Bra*_*don 19

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

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>


#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);
Run Code Online (Sandbox Code Playgroud)

  • 关闭,但它并非来自那里.我正在查找如何"在OSX上挂钩函数"并遇到LD_PRELOAD和DYLD_INSERT_LIBRARIES,因为两者都没有工作,我查找了如何在OSX上执行`代码注入`并且遇到了`DYLD_INTERPOSE`的Google论坛帖子.有趣的是,直到我结合这两个想法才行. (3认同)
  • 非常感谢你的回答:) (2认同)
  • 看来这个答案来自http://stackoverflow.com/a/20717262/1027966。 (2认同)

mar*_*hor 6

来自dyld文档:

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

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

所以您的代码需要 DYLD_FORCE_FLAT_NAMESPACE=1。无论如何,我的实现仅适用于/usr/local/bin/git启用此选项的情况。


Nic*_*ers 6

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

\n\n
\xe2\x9e\x9c  clang slow_leak.c -force_flat_namespace -o slow_leak\n\xe2\x9e\x9c  DYLD_INSERT_LIBRARIES=malloc_hook.dylib ./slow_leak\nleaking\nin hooked malloc\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

提到的 HN(2 年后)的评论DYLD_FORCE_FLAT_NAMESPACE=1可以在重新编译不可行的情况下提供帮助。我还没有尝试过,所以 YMMV。

\n