Often times it is useful to instrument a program you do not have the source to in an attempt to learn more about it. This can be for debugging purposes, blackbox testing, or for providing alternate versions of common functions/libraries (to name a few). On Linux, there is a very useful feature for doing just this: LD_PRELOAD
.
In this post I will cover how to build a shim library for an alternate version of malloc
. This is not an uncommon approach (valgrind
originally did this) and can be a useful trick to have in your toolbox.
In general (and very simplified), the flow of execution can be thought of in the following way:
All functions defined in libraries (i.e. not in your program) will be loaded at runtime and when you call a function in that library control is handed over to the library implementation to do work on your behalf.
In the cases I describe above, however, you want to change that control flow without having access to the original source code or library implementation. Enter LD_PRELOAD
. LD_PRELOAD
allows you to modify the order of library loading to request a user-specified library be loaded prior to other libraries. Using this mechanism one can provide a function named the same as one found in libc.so
(e.g. malloc
) and have that code executed instead of the version found in libc.so
.
This process is called interpositioning and it changes the above control flow into something similar to the following:
With that, you can provide whatever implementation you'd like for malloc
. In this example, I simply print the details about the memory returned from libc malloc
but you could provide an entirely separate memory allocation process here if you wanted to. You might do this, for example, if you wanted to test edge cases in a program where malloc
returned NULL
(often times not checked for).
Using the sample code I've provided you need to compile with _GNU_SOURCE
into a shard library:
gcc -D_GNU_SOURCE -W -Wall -Wextra -Werror -fPIC -shared -Wl,-soname,libmymalloc.so -Wl,--no-as-needed -o libmymalloc.so -ldl mymalloc.c
Then you can provide that library when you execute the program:
LD_PRELOAD=/full/path/to/libmymalloc.so ./sample
Example:
[square@home (interpose)]$ LD_PRELOAD=/tmp/sample/libmymalloc.so ./sample
Enter a number: 42
[MALLOC] 42 bytes at 0x81c1008