2

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

Community
  • 1
  • 1
me_L_coding
  • 169
  • 10
  • You might have a look at http://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism http://stackoverflow.com/questions/7811656/ld-preload-only-working-for-malloc-not-free http://stackoverflow.com/questions/10913186/ld-preloading-malloc-and-free etc. – Yann Droneaud Feb 21 '13 at 10:19
  • I bet that `dlsym` is calling free... ;) – Mats Petersson Feb 21 '13 at 10:31
  • 1
    You should take the fact that `printf()` might call `malloc()` and `free()` into consideration. This is most likely occuring (hence, recursive `free()`) – Hasturkun Feb 21 '13 at 10:31
  • Note that there is no standard header called malloc.h. The malloc and free functions are found in stdlib.h. – Lundin Feb 21 '13 at 12:05

3 Answers3

1

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.

Yann Droneaud
  • 5,277
  • 1
  • 23
  • 39
  • I added the prefix, but that did not work out since they could not be found. However without the prefix it did work for malloc. – me_L_coding Feb 21 '13 at 10:26
  • declare the prefixed version as extern and use them directly. This was the way I used to overcome getgroups limitations in the old time. – Yann Droneaud Feb 21 '13 at 10:30
1

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.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks for the answer, i adopted your suggested code and got it to work; also printf was switched out for fputs. – me_L_coding Feb 21 '13 at 17:25
  • But a problem still remain, I am not able to retrieve any of the specifics from the application, such as the addresses of the allocated blocks. Reason for wanting them is since I want to record the usage of malloc/free i.e,. i want to know all the allocation sizes and the different free invocations (in the same order as they were invoked). My intention is to later replay these allocation with my custom malloc and free function. – me_L_coding Feb 21 '13 at 17:31
  • @me_L_coding: This sounds like a separate question. Are you unable to retrieve the data because you are now not using `printf` or for some other reason? There are various alternatives: Use `printf` with the static flag code. Use `fputs` but do your own formatting to convert addresses to human-readable values. Use `fputs` to write the addresses in binary. Create data structures to record the values during the interposed routines and, at program exit, use another routine to read those structures and write the data. – Eric Postpischil Feb 21 '13 at 17:43
  • Thanks for the replay! Let me explain what I meant with the previous comment. I actually got the application to work, i.e,. I quit using "malloc-dependent" function such as printf(3). Only now my problem is that I can't really output any relevant data from the application since those functions use malloc. Say I wanted to run an application such as "Emacs" togheter with my hooks; in some way I want to be able to extract the allocation sizes that emacs uses as well as the different free(3) invocations. (preserving the order of these calls ,ofcourse). In essance thats my "real" big problem. – me_L_coding Feb 22 '13 at 13:04
0

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.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227