关于 Function Call Tracing
Function Call Tracing 是用于追踪 C 和 C++ 程序函数调用的技能,可记录各线程日志并转换为 Perfetto 可视化格式。它指导编码 Agent 在沙箱中构建、运行不可信项目并转换日志。
主要功能
- 01追踪 C/C++ 函数进入与退出
- 02按线程记录调用日志
- 03转换为 Perfetto 可视化格式
- 04通过沙箱执行构建与运行
适用场景
- 01检查多线程程序的函数调用
- 02在 Perfetto 中查看调用时间线
- 03安全追踪不可信项目
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gadievron/ raptor --skill function-call-tracing安装后在 Claude Code 中输入/function-call-tracing确认已加载。
附带文件trace_instrument.ctrace_to_perfetto.cpp
详细介绍
函数调用跟踪
用途
跟踪 C/C++ 程序中的所有函数调用,生成按线程划分的日志并使用 Perfetto 进行可视化。
隔离
被跟踪的项目不可信——其构建脚本和生成的二进制文件都可以执行任意代码。任何运行目标构建系统或经过插桩的二进制文件的命令,都必须通过 libexec/raptor-run-sandboxed --output-dir <dir> <cmd> [args...] 执行(--output-dir = 命令写入的目录:构建时为项目目录,运行时为工作目录)。沙箱会按设计清除加载器变量(LD_LIBRARY_PATH、LD_PRELOAD);经过插桩的链接会将 rpath 写入二进制文件,因此在沙箱中运行时无需设置加载器变量即可解析 libtrace.so。如果沙箱步骤失败,应修复沙箱执行路径——绝不能直接运行目标程序。构建插桩库本身(RAPTOR 自身的技能源代码)无需使用沙箱。
组件
1. 插桩库(trace_instrument.c)
捕获函数进入和退出事件,并写入按线程划分的日志。
构建:
gcc -c -fPIC trace_instrument.c -o trace_instrument.o
gcc -shared trace_instrument.o -o libtrace.so -ldl -lpthread
2. Perfetto 转换器(trace_to_perfetto.cpp)
将日志转换为供 Perfetto UI 使用的 Chrome JSON。
构建:
g++ -O3 -std=c++17 trace_to_perfetto.cpp -o trace_to_perfetto
用法
步骤 1:添加到构建配置
LIBTRACE_DIR 是存放 libtrace.so 的绝对目录;-Wl,-rpath 可让二进制文件在沙箱中运行时找到该库(沙箱会清除 LD_LIBRARY_PATH)。
CFLAGS += -finstrument-functions -g
LDFLAGS += -L$(LIBTRACE_DIR) -Wl,-rpath,$(LIBTRACE_DIR) -ltrace -ldl -lpthread
步骤 2:构建目标(在沙箱中——构建脚本不可信)
libexec/raptor-run-sandboxed --output-dir <project-dir> make ENABLE_TRACE=1
步骤 3:运行(在沙箱中;rpath 可解析 libtrace.so——无需设置加载器变量)
libexec/raptor-run-sandboxed --output-dir <working-dir> <project-dir>/program
# Creates trace_<tid>.log files
步骤 4:转换为 Perfetto 格式(在沙箱中——日志字节来自不可信的目标程序,且转换器是原生代码)
libexec/raptor-run-sandboxed --output-dir <working-dir> ./trace_to_perfetto trace_*.log -o trace.json
# Open trace.json in ui.perfetto.dev
日志格式
[seq] [timestamp] [dots] [ENTRY|EXIT!] function_name
[0] [1.000000000] [ENTRY] main
[1] [1.000050000] . [ENTRY] helper
[2] [1.000100000] . [EXIT!] helper
[3] [1.000150000] [EXIT!] main
- 点号表示调用深度
- 时间戳格式为秒.纳秒
- 每个线程对应一个日志文件
用户请求跟踪时
步骤
- 将
trace_instrument.c和trace_to_perfetto.cpp复制到项目中 - 构建插桩库
- 将
-finstrument-functions添加到 CFLAGS - 将
-L$(LIBTRACE_DIR) -Wl,-rpath,$(LIBTRACE_DIR) -ltrace -ldl -lpthread添加到 LDFLAGS - 通过
libexec/raptor-run-sandboxed --output-dir <project-dir> ...构建项目 - 通过
libexec/raptor-run-sandboxed --output-dir <working-dir> ...运行经过插桩的二进制文件(rpath 可解析libtrace.so) - 通过
libexec/raptor-run-sandboxed --output-dir <working-dir> ./trace_to_perfetto trace_*.log -o trace.json转换日志(将不可信的日志字节传入原生解析器) - 提供 ui.perfetto.dev 的链接
构建系统检测
Makefile: 按条件添加标志
ENABLE_TRACE ?= 0
ifeq ($(ENABLE_TRACE),1)
CFLAGS += -finstrument-functions -g
LDFLAGS += -L$(LIBTRACE_DIR) -Wl,-rpath,$(LIBTRACE_DIR) -ltrace -ldl -lpthread
endif
CMake: 添加选项
option(ENABLE_TRACE "Enable tracing" OFF)
if(ENABLE_TRACE)
add_compile_options(-finstrument-functions -g)
link_directories(${LIBTRACE_DIR})
add_link_options(-Wl,-rpath,${LIBTRACE_DIR})
link_libraries(trace dl pthread)
endif()
输出
- trace_.log:按线程划分的文本日志
- trace.json:Perfetto Chrome JSON 格式
- 在 https://ui.perfetto.dev 查看
Perfetto JSON 格式
函数 ENTRY → “B”(开始)事件 函数 EXIT! → “E”(结束)事件 所有线程按时间戳对齐并存于同一个文件。