Trace Function Calls in C/C++ Programs
Sometimes, it’s helpful to trace function calls in your program. Fortunately, GCC and Clang provide a built-in feature for this: function instrumentation via the -finstrument-functions flag. Here’s a hands-on tutorial.
Step 1: Create a Simple Program
Let’s start with a straightforward C++ program (main.cpp):
1 | |
Step 2: Write the Instrumentation Hooks
With -finstrument-functions, the compiler injects calls to two special functions at the entry and exit of every function:
__cyg_profile_func_enter(void *func, void *caller)(on entry)__cyg_profile_func_exit(void *func, void *caller)(on exit)
Here’s an implementation that prints the function names using dladdr (POSIX):
1 | |
Note: The attribute no_instrument_function is crucial! Otherwise, the instrumented hooks would recursively call themselves and likely crash.
Step 3: Compile the Program
Compile with function instrumentation enabled, and ensure symbols are exported for name resolution:
1 | |
-finstrument-functions: injects calls on entry/exit.-ldl: links the dynamic loader library, needed fordladdr.-rdynamic: exports all symbols fordladdrto resolve names.
Step 4: Run the Program
Run the binary:
1 | |
- You see the entry/exit for
mainand forfoo(mangled name:_Z3foovin this case). - The hooks print function names as you enter/exit them, allowing you to trace the call flow.
Trace Function Calls in C/C++ Programs
https://jifengwu2k.github.io/2026/02/28/Trace-Function-Calls-in-C-C-Programs/