I have build a little patch to append to a certain application and trace the invocations of some functions. Among them, malloc() and open(). I am using dlsym to store the pointer to the original symbol and replace the function name with my own. It compiles -and works- perfectly under linux. Here's the code:
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>
/**
* 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;
}
Then, I compile it with the following instruction, creating a pi.so.
gcc -Wall -O2 -fPIC -shared -ldl -o pi.so pi.c
And then, I use the LD_PRELOAD directive to inject it into any app.
LD_PRELOAD=/home/.../injection/pi.so <binary>
And it worjks marvellous under Linux! But when I get back home and try to compile it using GCC under Mac, it fails to compile and the LD_PRELOAd directive does not work. What should I change? Thank you very much.
On mach, you have to use DYLD_INSERT_LIBRARIES
macro instead of LD_PRELOAD
to specify a list of shared libraries to pre-load (1...*).
By default, standard functions are not getting replaced with functions from the shared objects just because they have the same names. You have to explicitly state what function overrides what using DYLD_INTERPOSE macro. It allows you to declare a replacement function with any name (for example, override open
with my_open
) and be able to call original function you are overriding. In addition to that, you don't have to resolve addresses of real functions manually.
Alternatively, to achieve Linux-like behavior you have to define DYLD_FORCE_FLAT_NAMESPACE
macro.
There is a lot more going on, see dyld manual for details.
So your code should look something like this:
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <mach-o/dyld-interposing.h>
/**
* 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)
The Mac OS X (10.6.4) does not contain any references to LD_PRELOAD - so it is ignored, and hence your attempt to interpose your code fails. All the world is not the same as Linux.
Looking through the man pages, I found:
$ man dyld
...
DYLD_INSERT_LIBRARIES This is a colon separated list of dynamic libraries to load before the ones specified in the program. This lets you test new modules of existing dynamic shared libraries that are used in flat-namespace images by loading a temporary dynamic shared library with just the new modules. Note that this has no effect on images built a two-level namespace images using a dynamic shared library unless DYLD_FORCE_FLAT_NAMESPACE is also used.
For OSX you'd have to use the DYLD_INSERT_LIBRARIES env. variable instead of LD_PRELOAD.
However I'm fairly certain you won't get the overriding to work. The closest thing I can find is you'll have to do some magic assembly tricks, which someone has neatly packaged up in the code under mach_override here: http://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code/
来源:https://stackoverflow.com/questions/3810326/ansi-c-patch-using-dlsym-compiles-ok-under-linux-but-fails-on-mac-os-x