There are several techniques you can use to achieve function wrapping at compile time with Clang and other compilers.

1. alias attribute (for simple wrappers)

The alias attribute is a GNU extension supported by Clang that creates a symbol alias. While it doesn’t wrap the function directly, you can use it to create a new, weakly-linked alias that points to your wrapper function. This is useful for intercepting calls to a specific function name.

How it works:

  • Define a wrapper function that calls the original function.
  • Use __attribute__((weak, alias("wrapper_function_name"))) on the original function’s declaration.
  • This is typically used in the same compilation unit as the original function’s definition.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

// The function we want to wrap
void original_function(void) {
    printf("Original function called.\n");
}

// The wrapper function
void wrapper_function(void) {
    printf("Before calling original_function.\n");
    original_function();
    printf("After calling original_function.\n");
}

// Create a weak alias so calls to original_function go to our wrapper
// Note: This needs to be done carefully to avoid infinite recursion.
// The wrapper_function must call the "real" original function symbol.
void original_function(void) __attribute__((weak, alias("wrapper_function")));

int main() {
    original_function(); // This call will be redirected to wrapper_function
    return 0;
}

2. Manual #define macros

You can use preprocessor macros to rename the original function and define a new macro with the old name that calls your wrapper. This is a common and straightforward method, but it is not type-safe and can interfere with debugging. 

How it works:

  • Rename the original function using a macro or by simply changing its name.
  • Define a new macro with the old name to perform the wrapping logic. 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>

// Use a macro to rename the function and define a wrapper
#define wrapped_function wrapped_function_real
void wrapped_function_real(void) {
    printf("Original function called.\n");
}

#define wrapped_function() \
    (printf("Before calling wrapped_function.\n"), \
     wrapped_function_real(), \
     printf("After calling wrapped_function.\n"))

int main() {
    wrapped_function();
    return 0;
}

3. Linker-based function interposition See Linker magic Post

4. Clang Plugins and LibTooling (advanced)

For a more robust and compile-time solution, you can write a custom Clang plugin or use its LibTooling API. This allows you to hook into the compilation process and perform more complex transformations on the Abstract Syntax Tree (AST), such as automatically creating a wrapper function for every function marked with a custom attribute. 

How it works:

  • Write a custom AST consumer that identifies functions with a specific attribute.
  • Programmatically modify the AST to create the new wrapper function and redirect calls to the original function.
  • This approach is powerful but requires significant knowledge of Clang’s internals.