使用dlsym的Ansi C补丁在linux下编译好但在Mac Os X上失败

我已经构建了一个小补丁来附加到某个应用程序并跟踪某些函数的调用。 其中,malloc()和open()。 我使用dlsym存储指向原始符号的指针,并用我自己的名称替换函数名称。 它可以在linux下完美编译和工作。 这是代码:

#define _GNU_SOURCE #include  #include  #include  #include  #include  /** * Interponemos nuestra funcion open * * @param char* filename * @param int flags **/ int open(char * filename, int flags) { static int (*real_open)(char*, int) = NULL; if (!real_open) real_open = dlsym(RTLD_NEXT, "open"); // Entero int p = real_open(filename, flags); fprintf(stderr, "Abrimos %s) = %i\n", filename, flags); // Devolvemos return p; } //-------------------------------------------------------- /** * Interponemos nuestra funcion malloc * * @param size_t size */ void* malloc(size_t size) { static void* (*real_malloc)(size_t) = NULL; if (!real_malloc) real_malloc = dlsym(RTLD_NEXT, "malloc"); void *p = real_malloc(size); // Memoria reservada fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p); // Devolvemos return p; } 

然后,我用以下指令编译它,创建一个pi.so.

 gcc -Wall -O2 -fPIC -shared -ldl -o pi.so pi.c 

然后,我使用LD_PRELOAD指令将其注入任何应用程序。

 LD_PRELOAD=/home/.../injection/pi.so  

它在Linux下令人惊叹! 但是当我回到家并尝试在Mac下使用GCC编译它时,它无法编译并且LD_PRELOAd指令不起作用。 我应该改变什么? 非常感谢你。

在Mach上,您必须使用DYLD_INSERT_LIBRARIES宏而不是LD_PRELOAD来指定要预加载的共享库列表(1 … *)。

默认情况下,标准函数不会被共享对象中的函数替换,因为它们具有相同的名称。 您必须明确说明使用DYLD_INTERPOSE宏覆盖什么函数。 它允许您使用任何名称声明替换函数(例如,使用my_open覆盖open )并且能够调用您覆盖的原始函数。 除此之外,您不必手动解析实际function的地址。

或者,要实现类似Linux的行为,您必须定义DYLD_FORCE_FLAT_NAMESPACE宏。

还有很多事情要发生,详见dyld手册。

所以你的代码应该是这样的:

 #define _GNU_SOURCE #include  #include  #include  #include  #include  #include  /** * Interponemos nuestra funcion open * * @param char* filename * @param int flags **/ int my_open(char * filename, int flags) { // Entero int p = open(filename, flags); fprintf(stderr, "Abrimos %s) = %i\n", filename, flags); // Devolvemos return p; } DYLD_INTERPOSE(my_open, open) //-------------------------------------------------------- /** * Interponemos nuestra funcion malloc * * @param size_t size */ void* my_malloc(size_t size) { void *p = malloc(size); // Memoria reservada fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p); // Devolvemos return p; } DYLD_INTERPOSE(my_malloc, malloc) 

Mac OS X(10.6.4)不包含对LD_PRELOAD的任何引用 – 因此它被忽略,因此您尝试插入代码失败。 全世界都与Linux不同。

通过手册页,我发现:

 $ man dyld 

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

对于OSX,您必须使用DYLD_INSERT_LIBRARIES环境。 变量而不是LD_PRELOAD。

但是我相当肯定你不会让压倒性的工作。 我能找到的最接近的东西是你必须做一些魔术组装技巧,有人在mach_override下的代码中整齐地打包了: http ://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code /