6

I am trying to provide memory wrappers on CentOS and using clang compiler/linker. I wrote wrappers for the allocation functions (malloc et al) and rerouted the calls using -Wl,-wrap,malloc.

This all works fine and I can see it in action. void* mem = malloc(10); // routes to __wrap_malloc free(mem);// routes to __wrap_free

However, the problem I am seeing is that any memory allocated within libc is not being routed to my wrapper but the application is making the free call that gets intercepted (and crash as a result). For example,

char* newStr = strdup("foo"); // The internal malloc in libcdoes not come to wrapper free(newStr); // The free call makes it to the wrapper

My program is in C++. I created a mallocimpl.cpp and did something like

extern "C"{ void* __wrap_malloc(size_t size) { // Route memory via custom memory allocator } //Similarly, __wrap_calloc, __wrap_realloc, __wrap_memalign and __wrap_free

Any ideas what I am doing wrong? Do I need any special compiler/linker flags?

Thanks in advance.

2
  • First of all , do you check the pointer if NULL before you use it? Commented Mar 16, 2018 at 0:22
  • 2
    This isn't a null pointer problem. Commented Mar 16, 2018 at 1:29

3 Answers 3

6

The recommended way to replace the glibc malloc implementation is ELF symbol interposition:

This way, you do not have to recompile everything, including glibc, and your malloc replacement will still be called once glibc removes the malloc hooks.

The __wrap approach does not work without recompiling (or at least rewriting) everything because all other libraries (including glibc) will use non-wrapped symbols.

Sign up to request clarification or add additional context in comments.

2 Comments

While I was hoping to avoid stuff like LD_PRELOAD which brings additional complexity in the application and it's execution, I'll go ahead and accept this answer. At the moment, I'll not integrate this solution and just rely on deprecated hooks. It does not seem like they are going anywhere. The original commit said they'll be removed in next release but they are still around after 6 years (probably due to lack of a good equivalent replacement).
Symbol interposition does not need LD_PRELOAD, you can just define the functions in the main program and export them (say, using -Wl,-E). The hooks will likely go away with the next glibc release.
1

There were some special "hooks" in glibc (__malloc_hook, __realloc_hook, __free_hook, __memalign_hook) to catch all mallocs of glibc: https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html

The GNU C Library lets you modify the behavior of malloc, realloc, and free by specifying appropriate hook functions. You can use these hooks to help you debug programs that use dynamic memory allocation, for example.

Hooks are unsafe and marked as deprecated in the man pages. Some variants are listed at An alternative for the deprecated __malloc_hook functionality of glibc

Also, check how alternative mallocs like jemalloc, tcmalloc and other implements their "preloading/linking of special library" to replace glibc malloc.

2 Comments

My current program actually uses hooks and I am trying to replace them with the wrappers for precisely the reason that they are deprecated :).
@mast3r_of_univ3rs3, your wrappers (-Wl,-wrap,...) don't change code inside glibc...
0

The only way to guarantee matching malloc / free would be to recompile everything, including libc. This is probably not practical for you, so your best option is to somehow track the memory allocated by your malloc wrapper and then appropriately either deallocate it yourself or invoke __real_free in your free wrapper based on how the memory was allocated.

3 Comments

Thanks for the suggestion. While I can track the mem allocator, I'd think there is a better solution for it. After all, the wrappers should be applied to the entire application. Also, I don't think I need to recompile everything. I have pre-built libraries like curl in my application whose allocations are getting re-routed correctly. The problem is unique to allocations made internally by libc.
@mast3r_of_univ3rs3, LD_PRELOAD will work to replace all mallocs (library should replace every function of malloc family). Check how jemalloc, tcmalloc and other alternative malloc works with relinking to their library or ld_preloading it: JEMALLOC_OVERRIDE___LIBC_MALLOC etc
@mast3r_of_univ3rs3 Try the LD_PRELOAD trick suggested by osgx. Never used it myself before, but looks like it works!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.