Wrapping Standard Library Function in C
It is straightforward to put print messages in user defined functions (for debugging or for logging purposes) but what if you want to do something similar to standard library functions? It is not that difficult either. GNU Linker's(ld) –wrap=symbol option helps achieving this.
Suppose, you want to wrap strlen. Here is the scheme:
- The program will be compiled with following linker option: -Wl,–wrap=strlen
- Call the strlen as-is in your program
- Define _wrapstrlen with the same prototype as strlen. Do whatever is desired inside this function and call _realstrlen. _realstrlen will call the actual library routine.
Here is a complete example wrapping strlen:
#include <stdio.h> #include <string.h> /* call to strlen will call __wrap_strlen first */ size_t __wrap_strlen (const char *s) { printf ("inside strlen wrapper\n"); /* lib's strlen call will happen with __real_strlen */ return __real_strlen (s); } int main (int argc, char *argv[]) { /* call to strlen remains as-is, and calls __wrap_strlen */ printf ("program's name length: %zu\n", strlen(argv[0])); return 0; }
Compile it as:
$ gcc wrap_strlen.c -Wl,--wrap=strlen -o wrap_strlen
Run:
$ ./wrap_strlen inside strlen wrapper program's name length: 13
Here is what ld info page says which is self-explanatory:
–wrap=symbol
Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to "_wrapsymbol". Any undefined reference to "_realsymbol" will be resolved to symbol.
This can be used to provide a wrapper for a system function. The wrapper function should be called "_wrapsymbol". If it wishes to call the system function, it should call "_realsymbol".
Here is a trivial example:
void * _wrapmalloc (sizet c) { printf ("malloc called with %zu\n", c); return _realmalloc (c); }
If you link other code with this file using –wrap malloc, then all calls to "malloc" will call the function "_wrapmalloc" instead. The call to "_realmalloc" in "_wrapmalloc" will call the real "malloc" function.
You may wish to provide a "_realmalloc" function as well, so that links without the –wrap option will succeed. If you do this, you should not put the definition of "_realmalloc" in the same file as "_wrapmalloc"; if you do, the assembler may resolve the call before the linker has a chance to wrap it to "malloc".
Well, short, wrapping it up!