tags:

views:

90

answers:

2

I have searched online a lot but I couldn't find an example that works with g++, all examples work with gcc. The error I keep getting is

wrap_malloc.o: In function `__wrap_malloc(unsigned int)':
wrap_malloc.cc:(.text+0x20): undefined reference to `__real_malloc(unsigned int)'
wrap_malloc.o: In function `main':
wrap_malloc.cc:(.text+0x37): undefined reference to `__wrap_malloc'
collect2: ld returned 1 exit status

The code that creates this error is the following (this code works if I compile it with gcc and change the headers from cstdio to stdio.h):

#include <cstdio>
#include <cstdlib>

void *__real_malloc(size_t);

void *__wrap_malloc(size_t c) {
  printf("My malloc called with %d\n", c);
  return __real_malloc(c);
}

int main(void) {
  void *ptr = malloc(12);
  free(ptr);
  return 0;
}

This is how I compile it:

wrap_malloc.o: wrap_malloc.cc
    g++ -c wrap_malloc.cc -o wrap_malloc.o

wrap_malloc: wrap_malloc.o
    g++ wrap_malloc.o -o wrap_malloc -Wl,--wrap,malloc

Thank you!

A: 

If this is the complete code, the problem you are having is that you haven't implemented __real_malloc()!

And by the way, identifiers with double-underscores are reserved by the language. You might want to think about picking different names.

John Dibling
This code is a demo, I am planning to use the wrappers just for testing. If the code is compiled with --wrap=malloc it will redirect all the calls to __wrap_malloc. If you want to use the real thing you have to call __real_malloc. Here is the documentation => Any undefined reference to symbol will be resolved to "__wrap_ symbol ". Any undefined reference to "__real_ symbol " will be resolved to symbol.This can be used to provide a wrapper for a system function. The wrapper function should be called "__wrap_ symbol ". If it wishes to call the system function, it should call "__real_ symbol ".
John B.
+4  A: 

When you use a C++ compiler, all names are mangled. What this means becomes clear when you run nm wrap_malloc.o, which should give you something like this:

00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
         U __Z13__real_mallocj
00000000 T __Z13__wrap_mallocj
         U _printf

This means that you use (U) a symbol called __Z13__real_mallocj and that you define a symbol in the text segment (T) called __Z13__wrap_mallocj. But you probably want a symbol called __real_malloc. To achieve this you have to say the compiler that __real_malloc is a C-style function, like this:

extern "C" void *__real_malloc(size_t);

extern "C" void *__wrap_malloc(size_t c) {
  printf("My malloc called with %d\n", c);
  return __real_malloc(c);
}

Now the output of nm is:

00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
         U ___real_malloc
00000000 T ___wrap_malloc
         U _printf

You can see that the name _printf hasn't changed. This is because in the header files, many functions are declared as extern "C" already.

Note: I did all of the above on Windows in the cygwin environment. That's why there is an additional leading underscore in the external symbols.

Roland Illig
Thanks a lot! Now I understand the problem.
John B.