プログラムの呼び出しを一覧にする
ltrace と strace は、プログラムが呼ぶ関数と、OS に頼む操作を、実行しながら一覧にする道具です。コードを1行も読まなくても、どのファイルを開こうとしているかが分かります。
調べるのは、自分で作ったプログラムと、ラボのプログラムだけです。
このレッスンのゴール
メモ
ltrace と strace で、プログラムが探すファイルを見つけられる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| ライブラリ呼び出し | 用意された関数を呼ぶこと | fopen |
| システムコール | プログラムが OS の核に頼む操作 | openat |
| トレース | 実行中の呼び出しを、順に記録すること | |
| ENOENT | そのファイルがない、という誤りの名前 | |
| 設定ファイル | プログラムが起動時に読む、設定を書いたファイル |
学生が入力するセルは、このプレビューでは空白です。
呼び出しには2つの層がある
プログラムは、fopen のようなライブラリの関数を呼びます。ライブラリは、その裏で OS の核に、openat のようなシステムコールで頼みます。
ltrace は上の層、strace は下の層を見せます。2つを並べると、何を頼み、何が起きたかが分かります。
設定ファイルを探すプログラム
次の練習用プログラムは、名前を受け取り、/tmp/rev6-名前.cfg を開こうとします。あれば loaded、なければ no config と出します。
ソースを作ってバイナリにし、ソースを消してから、呼び出しを追います。
ソースを書く
printf '%s\n' '#include <stdio.h>' '#include <stdlib.h>' 'int main(int c, char **v) {' ' char p[64];' ' FILE *f;' ' if (c != 2) { puts("usage: rev6 NAME"); return 2; }' ' snprintf(p, sizeof p, "/tmp/rev6-%s.cfg", v[1]);' ' f = fopen(p, "r");' ' if (f) { fclose(f); puts("loaded"); return 0; }' ' puts("no config");' ' return 1;' '}' > /tmp/rev6.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
プログラムを作る
gcc -O0 -no-pie -o /tmp/rev6 /tmp/rev6.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ソースを消す
rm /tmp/rev6.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ライブラリ呼び出しを追う
ltrace /tmp/rev6 spring 2>&1 | grep fopenここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
fopen の行から道が読める
行の最初は呼んだ関数で、括弧の中は引数です。fopen("/tmp/rev6-spring.cfg", "r") は、その道のファイルを読むために開く、という意味です。
行の終わりの = nil は、開けなかったという意味です。ファイルの名前が、実行しながら作られていたことも分かります。
システムコールを追う
strace -e trace=openat /tmp/rev6 spring 2>&1 | grep rev6ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
行の終わりの読み方
| 行の終わり | 意味 |
|---|---|
| = 3 | 開けた。3 はファイルの番号 |
| = -1 ENOENT | そのファイルがなかった |
| = -1 EACCES | 権限がなくて開けなかった |
| = nil | fopen が開けなかった |
学生が入力するセルは、このプレビューでは空白です。
ファイルを作ると結果が変わる
探されているファイルを作ってから、同じ操作をもう一度見ます。空のファイルで十分です。
今度は、行の終わりが = 3 になり、プログラムは loaded と答えます。トレースで道が分かったので、答えが変わりました。
探されているファイルを作る
touch /tmp/rev6-spring.cfgここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
もう一度システムコールを追う
strace -e trace=openat /tmp/rev6 spring 2>&1 | grep rev6ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
そのまま実行する
/tmp/rev6 springここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
作ったファイルを消す
rm /tmp/rev6-spring.cfgここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
ltrace と strace は、同じものを見せると思いがちです。実際は、ltrace は関数の呼び出し、strace は OS への要求を見せます。fopen が1つあれば、その裏に openat が出ますが、数も名前も違います。