linux中函数封装本身不开启调试追踪,需在函数内嵌入可追踪标记或调用行为:可用ftrace function_graph追踪内核函数、uprobe/tracepoint监控用户态封装函数、trace_printk快速打点、ebpf实现零侵入动态插桩。

用 ftrace 的 function_graph 追踪封装函数调用栈
如果你的封装函数是内核函数(比如自定义模块中的 my_wrapper_func()),需确保它未被编译器内联(加 __attribute__((noinline))),并启用函数图谱追踪:
- 确认内核配置:
CONFIG_FUNCTION_GRAPH_TRACER=y,且函数名出现在/proc/kallsyms中(grep my_wrapper_func /proc/kallsyms) - 启用追踪:
echo function_graph > /sys/kernel/debug/tracing/current_tracer - 过滤目标:
echo my_wrapper_func > /sys/kernel/debug/tracing/set_ftrace_filter - 开始记录:
echo 1 > /sys/kernel/debug/tracing/tracing_on,然后触发该函数调用
在用户态封装函数里插入 tracepoint 或 ustack
对于 C/C++ 用户程序中的封装函数(如 safe_open(const char *path)),无法直接用 kprobe,但可通过以下方式“暴露”给追踪工具:
- 使用
libbpf + uprobe:编译时保留调试符号(-g),运行时用bpftool或trace-cmd在函数入口设 uprobe - 手动打 tracepoint:调用
syscall(__NR_getpid)或raise(SIGUSR2)并配合 perf event 监听(需提前注册信号 handler 做标记) - 用
ltrace直接观察:若封装函数调用了 glibc 函数(如fopen,malloc),ltrace -e "safe_open" ./app可捕获其调用及返回
封装函数内嵌 printk 或 trace_printk(仅限内核模块)
这是最轻量、无需额外配置的方式,适合快速验证逻辑流:
- 在封装函数开头/结尾加
trace_printk("my_wrapper: enter, arg=%p ", arg); - 注意:
trace_printk输出到 ftrace ring buffer,需启用:echo 1 > /sys/kernel/debug/tracing/options/trace_printk - 查看:
cat /sys/kernel/debug/tracing/trace_pipe(实时)或trace(缓冲快照) - 优于普通
printk:不刷磁盘、无同步开销、支持格式化,且可被trace-cmd解析
用 eBPF 在函数入口自动注入探测逻辑
现代方式:不改源码,在运行时对封装函数地址插桩。适用于用户态或内核态函数:
- 用户态:用
bpftool uprobe或bpftrace -e 'uprobe:/path/to/binary:my_wrapper_func { printf("called\n"); }' - 内核态:用
kprobe直接绑定符号(需CONFIG_KPROBES=y,且函数非内联/不在黑名单) - 优势:完全外部控制,函数内部零修改;支持寄存器读取、参数提取、条件过滤











