me_L_coding
me_L_coding

Reputation: 354

Function interposition only working for malloc not free

I've come across a small problem while monitoring malloc and free trough the use of function interposition.

When performing the function interposition for just malloc, it works as exepcted. However, when trying to interpose free as well it ends up in a loop; i seems like free is recursivly invoked but i just dont know why.

This is the code for the malloc and free functions. (mod_malloc_free.c)

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

void* malloc(size_t size) {

   static void* (*real_malloc)(size_t) = NULL;

   printf("%s\n", "inside shared malloc");

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

   void * p = real_malloc(size);

   printf("malloc(%d) = %p\n",size, p );

   printf("%s\n", "returning from shared malloc");

   return p;

   }

void free(void* ap ) {

    static void (*real_free)(void*) = NULL;

  printf("inside shared free...\n");

  if(!real_free)
       real_free = dlsym(RTLD_NEXT, "free");

   printf("free = %p\n", ap);

   real_free(ap);

}

The main simply consists of:

#include <stdio.h>
#include <malloc.h>

int main(void) {

    void * p = malloc(123);

    printf("p = %p\n",p );

    free(p);

    return 0;

}

Compiled as:

gcc -shared -ldl -fPIC mod_malloc_free.c -o libcustom.so

gcc -o smallMain -Wall smallMain.c

LD_PRELOAD=./libcustom.so ./smallMain

Best regards

Nyfiken

Upvotes: 2

Views: 1069

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222908

It is likely printf is calling free. Of course, that implies it also performs memory allocation, so it raises the question why do you not see recursive calls in malloc. Likely printf is calling an alternative such as calloc or realloc.

To interpose in just your own code, use macros to replace the calls or link your code separately and use linker features to remove your malloc and free before linking with external libraries (such as the -unexported_symbol switch for the Apple version of ld).

To interpose in all code, remove printf from your routines. Call simpler routines, such as fputs instead. Alternatively, use a static flag to suppress the recursion:

void free(void *ap)
{
    static void (*RealFree)(void *) = 0;
    If (!RealFree)
        RealFree = dlsym(RTLD_NEXT, "free");

    static int InsideCall = 0;
    if (!InsideCall)
    {
        InsideCall = 1;
        … Do stuff…
        InsideCall = 0;
    }
}

(If you have multiple threads or exception handlers that perform memory allocation, additional steps must be taken.)

Upvotes: 2

Mats Petersson
Mats Petersson

Reputation: 129374

I would suggest that you use a macro to replace malloc/free with your own functions, instead of using function pointers.

Something like this should do it:

 #ifdef REPLACE_MALLOC
 #define malloc(x) my_mallc(x)
 #define free(x)   my_free(x)
 #endif

Don't forget to do:

 #undef malloc
 #undef free

before your actual implementation.

Note however that technically this is not "proper" - you are not supposed to use macros for things that are part of a standard library, so please don't come moaning here if it stops working - in particular, Microsoft already does something like this to replace malloc with it's debug version in debug builds.

Upvotes: 0

Yann Droneaud
Yann Droneaud

Reputation: 5463

glibc provides the real symbol (not weak) with __ prefix. So try to lookup symbol __malloc and __free.

And just to prevent recursion, don't use printf() or any other functions that might need to allocate memory inside your wrapper.

Upvotes: 1

Related Questions