試行錯誤のデバッグで探る、printf()内のポインタ経由での関数呼び出しが行き着く先とは:main()関数の前には何があるのか(3)(1/4 ページ)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、printf()内のポインタ経由での関数呼び出しが行き着く先を試行錯誤のデバッグで探る。
書籍の中から有用な技術情報をピックアップして紹介する本シリーズ。今回は、秀和システム発行の書籍『ハロー“Hello, World” OSと標準ライブラリのシゴトとしくみ(2015年9月11日発行)』からの抜粋です。
ご注意:本稿は、著者及び出版社の許可を得て、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。
※編集部注:前回記事「「Hello World!」の主役printf()の内部動作をデバッガGDBで追う」はこちら
関数呼び出しの流れを見る
現在はstepiによって関数呼び出しをした後でlayout asmでアセンブラ表示に切替えたため、呼び出し前の状態を見ることができていない。
layout asmを指示した状態で、もう一度やりなおしてみよう。デバッガでのデバッグはこのように、何度もやりなおして探ることで感覚をつかんでいくといいかと思う。
ということでrunによってプログラムを再実行する。実行中の状態で再実行しているので「最初から実行するか?」と聞いてくるが、「y」を選択する。
(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)
画面は図2.8のようになった。main()の先頭でブレークしているのだが、アセンブラ表示の状態でブレークしているだろう。なお画面が崩れて「Hello World!」の表示が残ってしまっている場合には、Ctrl+Lで適宜画面をリフレッシュすることができる。
反転表示されている行を見ると、どうやら「mov 0xc(%ebp),%eax」という命令でブレークしているようだ。
まずはステップ実行によって、動作を進めてみよう。stepiを一回、実行してみる。
(gdb) stepi
すると図2.9のように、実行が1命令進んだ。
さらにstepiを繰り返し実行し、「call」という命令まで進めてみよう。
callという命令の位置で停止している。これは、x86の関数呼び出し命令だ。
もう一度、stepiを実行してみよう。
(gdb) stepi 0x08049360 in printf () (gdb)
呼び出し先の関数の中に入ったようだ。左から2列目の表示が「<printf>」に切り替わった点に注目してほしい。つまり今は、printf()の先頭で停止していることになる。
stepiで、処理を進めてみよう。
(gdb) stepi 0x08049361 in printf () (gdb)
関数の中でも、stepiによるステップ実行は問題無く行えるようだ。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- プログラミング言語Cについて知ろう
プログラミング言語の基本となる「C」。正しい文法や作法を身に付けよう。Cには確かに学ぶだけの価値がある(編集部) - シェルコード解析に必携の「5つ道具」
コンピュータウイルスの解析などに欠かせないリバースエンジニアリング技術ですが、何だか難しそうだな、という印象を抱いている人も多いのではないでしょうか。この連載では、「シェルコード」を例に、実践形式でその基礎を紹介していきます。(編集部) - 【 od 】コマンド――ファイルを8進数や16進数でダンプする
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、「od」コマンドです。