In Progress write more examples in c++
After writing a post about monkey patching in C++ using pointer hacking I thought I’d write about a method that might be cleaner.
You can substitute functions at link time to “monkey patch” a C or C++ program, most commonly using the –wrap option of the GNU linker (ld). This technique is typically used for unit testing and debugging, where you can wrap a function and inspect its calls and return values without changing the program’s source code.
--wrap option of the GNU linker (ld). This technique is typically used for unit testing and debugging, where you can wrap a function and inspect its calls and return values without changing the program’s source code.
How the ld --wrap option works
The GNU linker provides the --wrap=symbol option to replace any undefined reference to symbol with __wrap_symbol. Additionally, it resolves any reference to __real_symbol to the original symbol.
Example
Consider an original program that calls a function named foo(). You want to wrap foo() with your own version.
|
|
Wrapper Code
To wrap foo(), you need to create a new object file with two functions:
__wrap_foo(): Your substitute function.__real_foo(): A function that calls the originalfoo(). This is defined by the linker when you use--wrap.
|
|
Linking the Program
To create the final executable, compile your original code, the wrapper code, and then link them together with the --wrap option.
|
|
When my_program runs, the output will be:
Wrapped function called!
Original foo() called
Limitations and important considerations
- Internal calls: A key limitation of
--wrapis that it only affects calls to the target function that are “undefined” at the time of linking. If the original function and the call to it are in the same compilation unit (the same.cor.cppfile), the compiler may resolve the call internally before the linker has a chance to wrap it. To avoid this, you can:- Separate the original function and the calls into different compilation units.
- Compile with link-time optimization (LTO) disabled, as LTO can resolve these calls internally.
- Static vs. dynamic linking: The behavior of function substitution can differ based on whether you are statically or dynamically linking libraries. It is often more reliable with dynamically linked libraries.
- C++ name mangling: For C++ functions, you need to use the C-style name in the linker command. You can find this name by using
nmon the compiled object file or by declaring your C++ function asextern "C"to prevent name mangling. - One wrapper per function: You can only have one wrapper for a given function in a single executable. If you need multiple versions for testing, you may need to build separate executables.
Other techniques for runtime monkey patching
While not a link-time method, other techniques exist for runtime function substitution, though they are platform-dependent and have different trade-offs.
LD_PRELOAD(Linux): On Linux, you can set theLD_PRELOADenvironment variable to a shared library, which forces the dynamic linker to load it before any other libraries. If your library contains a function with the same name as one in another library, your version will be used.- Function pointers: In C and C++, you can design your program with function pointers for key components. You can then change the function pointer at runtime to “hot-swap” implementations, a much cleaner and more standard alternative to using the linker for patching.