試行錯誤のデバッグで探る、printf()内のポインタ経由での関数呼び出しが行き着く先とは:main()関数の前には何があるのか(3)(2/4 ページ)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、printf()内のポインタ経由での関数呼び出しが行き着く先を試行錯誤のデバッグで探る。
メッセージの出力箇所を探る
これでprintf()の中に入れたわけだが、ステップ実行によってさらに処理を先まで進めることで、ハロー・ワールドのメッセージが出力されている箇所を探っていこう。
ここではメッセージ出力が行われている関数が知りたいので、nextiで処理を進めていけばいいだろう。そこでnextiを何回か実行すると、図2.13のような関数の呼び出しが見つかる。
ニーモニックを見ると、「call 0x80591c0 <vfprintf>」とある。命令としては「0x80591c0という位置にある関数を呼び出す」という意味なのだが、アドレスからそこにある関数をGDBが割り出して、vfprintf()が呼ばれていると表示してくれているようだ。
ということで、どうやらvfprintf()という関数が呼び出されているようだ。この中で文字列の出力が行われているのだろうか。
関数の実行時に、メッセージが出力されるかどうかを試してみよう。まず画面上にメッセージが残ってしまっている場合には、Ctrl+Lで画面をリフレッシュする。さらにnextiで関数の処理を進めてみよう。
(gdb) nexti 0x08049381 in printf () (gdb)
すると図2.14のようになった。
表示が崩れてしまっていてわかりづらいのだが、よく見ると反転表示されている行の数行下に「Hello World!」の文字列が出力されていることがわかる。つまり、メッセージ出力が行われているということだ。
ということは、メッセージ出力が行われているのはvfprintf()という関数の呼び出しの先ということがわかる。
vfprintf()の中に入る
どうやらメッセージの出力は、vfprintf()という関数の先で行われているようだ。ということでvfprintf()にブレークポイントを新たに張って、再度実行してそこまで進めてみよう。
(gdb) break vfprintf Breakpoint 2 at 0x80591d3 (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) Starting program: /home/user/hello/hello Breakpoint 1, main (argc=1, argv=0xbffffc14) at hello.c:5 (gdb)
main()の先頭に張ったブレークポイントがまだ残っているので、main()の先頭でブレークしたはずだ。ここで「Hello World!」のメッセージがまだ画面上に残っているようならば、メッセージ出力のタイミングを見誤らないように、Ctrl+Lを押すことで画面をリフレッシュしておこう。
さらにcontinueを実行しよう。すると次のブレークポイントであるvfprintf()の先頭まで進むはずだ。画面は図2.15のようになるだろう。
先ほどと同様にnextiで処理を進め、メッセージが出力されるタイミングを調べよう。実際にやってみると、まず図2.16のようなstrchrnul()という関数の呼び出しがある。
メッセージの出力が行われているのはこの関数の先だろうか?
まあ関数名からして関係なさそうな気はするのだが、練習として一応見てみよう。nextiで関数を実行すると、図2.17のようになった。
メッセージが出力されるようなことは無かったようだ。よってこの関数呼び出しは関係ないようだ。
このようにしてメッセージ出力が行われる箇所を探っていくことができる。途中、repnzという命令でnextiで進まなくなる箇所があるが、数10回nextiを繰り返すと抜けられるので、気にせずに進めてほしい。
すると、図2.18の位置でメッセージが出力されることがわかる。なお図2.18の位置はメッセージ出力までに何度か通過しているようなのだが、その中で数回目にメッセージが出力されるようだ。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- プログラミング言語Cについて知ろう
プログラミング言語の基本となる「C」。正しい文法や作法を身に付けよう。Cには確かに学ぶだけの価値がある(編集部) - シェルコード解析に必携の「5つ道具」
コンピュータウイルスの解析などに欠かせないリバースエンジニアリング技術ですが、何だか難しそうだな、という印象を抱いている人も多いのではないでしょうか。この連載では、「シェルコード」を例に、実践形式でその基礎を紹介していきます。(編集部) - 【 od 】コマンド――ファイルを8進数や16進数でダンプする
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、「od」コマンドです。