Function Call Tracing について
Function Call Tracing は、C/C++ プログラムの関数呼び出しを追跡するスキルです。スレッドごとのログを Perfetto 用に変換し、信頼できないプロジェクトのビルドや実行もサンドボックス経由で行う手順を示します。
主な機能
- 01C/C++ 関数の開始・終了を追跡
- 02スレッドごとの呼び出しログ
- 03Perfetto 表示形式への変換
- 04サンドボックスでのビルドと実行
活用シーン
- 01マルチスレッドプログラムの呼び出し調査
- 02Perfetto で呼び出しタイムラインを確認
- 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 が取り除かれる)サンドボックス内でも実行時にバイナリが libtrace.so を見つけられます。
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
- ドットは呼び出しの深さを示します
- タイムスタンプは秒.ナノ秒です
- スレッドごとに 1 つのログファイルが生成されます
ユーザーからトレースを依頼された場合
手順
trace_instrument.cとtrace_to_perfetto.cppをプロジェクトにコピーします- 計測ライブラリをビルドします
- CFLAGS に
-finstrument-functionsを追加します - LDFLAGS に
-L$(LIBTRACE_DIR) -Wl,-rpath,$(LIBTRACE_DIR) -ltrace -ldl -lpthreadを追加します 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」(終了)イベント すべてのスレッドが、単一ファイル内でタイムスタンプにより同期されます。