Mocking Made Easy: Audition Meets Valgrind

Posted on 2025-05-01T02:34:00Z

Audition version 1.0.5 has been released and includes basic support for Valgrind.

What is Valgrind?

Valgrind is a suite of tools for debugging and profiling Linux programs. It can automatically detect many common memory management and threading bugs, and offers detailed profiling of your application’s behavior. It works by running your program inside a virtual CPU.

Mocking in Audition

Mocking is one of Audition’s core features. It lets you replace any C function with a mock version that returns a controlled value.

Audition implements mocking through function hooking. This technique involves overwriting the beginning of a function’s machine code to redirect execution to a different function (the mock function). From the mock function, you can inspect arguments, assert behavior, and return stub values.

The Problem

Valgrind, by design, doesn’t run native code directly. Instead, it translates and simulates the program inside a virtual CPU. As a result, if a function is patched at runtime via a function hook, then Valgrind doesn’t notice, because it already translated the function before it was patched!

That means Audition’s mocks don’t work out of the box under Valgrind as it continues executing the original, unpatched function.

The Workaround

Valgrind provides a command-line option to address this: --smc-check=all.

This flag instructs Valgrind to detect and retranslate any self-modifying code, including runtime function hooks. This option makes Audition’s mocking work under Valgrind, however, it comes at the cost of additional performance overhead, since now all translated code must be revalidated and potentially retransformed at runtime.

The Correct Solution

Starting with Audition version 1.0.5, this workaround is no longer necessary.

Audition explicitly informs Valgrind when code has been modified. This means mocking works correctly under Valgrind by default, with no need for --smc-check=all.

Closing Thoughts

Audition version 1.0.5 introduces basic support for Valgrind, enabling the use of mocks alongside Valgrind without extra configuration. This release does not resolve all compatibility issues, for example, functions like malloc, calloc, and realloc are still not directly mockable, however, it nonetheless does mark an important step toward improving integration with Valgrind.