Wael Boutglay
Wael Boutglay

Reputation: 1383

It is possible to force an executable to use an user defined 'malloc'?

I want to understand how memory tracker and leak detector work, so I come with this idea, I have an executable, and I want to force it while execution to use my own memory allocation functions instead of the usual system functions ("malloc", "realloc"...).

My own functions are stored in a library (static or shared) or just an object file (".o"), thik about something like that:

void *my_own_malloc(unsigned long size) {
     printf("allocate: %lu\n", size);
     return malloc(size);
}

PS: I don't have to change the executable source code (I don't have source code)

PS2: I want to do that in all different platform (Windows, OS X & Linux...)

Upvotes: 3

Views: 813

Answers (1)

brm
brm

Reputation: 3816

I don't know about the other platforms, but on GNU/Linux you could pre-load a small memory tracking library with the LD_PRELOAD environment variable in which your own malloc and free are defined.

Your own malloc would probably want to allocate memory using the real malloc function, so there's a possible recursive problem here. To work around this, the dlsym function can use an RTLD_NEXT argument to obtain the pointer to the next (i.e. the 'real') malloc function.

A very small test of this could look like the following:

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

void *malloc(size_t size)
{
    static void *(*real_malloc)(size_t size) = 0;

    if (!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

    void *result = real_malloc(size);
    fprintf(stderr, "malloc(%d) = %p\n", (int)size, result);
    return result;
}

void free(void *ptr)
{
    static void (*real_free)(void *ptr) = 0;
    if (!real_free)
        real_free = dlsym(RTLD_NEXT, "free");

    real_free(ptr);
    fprintf(stderr, "free(%p)\n", ptr);
}

If we call this file fakemalloc.c, it can be compiled into a fakemalloc.so shared object with the command

gcc -fPIC -shared -Wl,-soname,fakemalloc.so -o fakemalloc.so fakemalloc.c -ldl

As a test, to see which malloc and free calls happen in a call to the ls command, you'd need to execute

LD_PRELOAD=/path/to/fakemalloc.so ls

EDIT: As mentioned in a comment, on glibc-systems you can avoid the RTLD_NEXT approach by using the functions __libc_malloc and __libc_free. This would produce the following code:

#include <stdio.h>

void *__libc_malloc(size_t size);
void *__libc_free(void *ptr);

void *malloc(size_t size)
{
    void *result = __libc_malloc(size);
    fprintf(stderr, "malloc(%d) = %p\n", (int)size, result);
    return result;
}

void free(void *ptr)
{
    __libc_free(ptr);
    fprintf(stderr, "free(%p)\n", ptr);
}

Upvotes: 4

Related Questions