Skip to content

Mocking: Link-time wrap

Example: share/doc/aceunit/examples/hello_world_mocked_link

Instead of rewriting the object file with objcopy, this approach uses the GNU/LLVM linker’s --wrap feature:

Terminal window
cc hello_test.o hello.o mock_puts.o testcases.o libaceunit-fork.a \
-Wl,--wrap=puts -Wl,--wrap=main

-Wl,--wrap=puts makes every call to puts in the linked objects resolve to __wrap_puts instead, while the real puts remains reachable as __real_puts. mock_puts.c defines __wrap_puts() to record calls into a buffer.

-Wl,--wrap=main is used differently: nothing needs to intercept calls to main() here, since nothing calls it as an ordinary function. The wrap simply frees up the main symbol so hello.c’s original main() becomes reachable as __real_main(argc, argv), which the test calls directly:

void test_hello(void) {
__real_main(0, NULL);
assert_puts("Hello, world!\n");
}
  • You’re on a GNU ld or LLVM lld toolchain (not available on the Darwin/macOS linker — see Darwin interposer instead).
  • You’d rather keep object files untouched and push the redirection entirely into link flags.

See also: objcopy override for the object-file-rewriting alternative, or Compile-time macro if you want zero dependency on linker features at all.