未来のいつか/hyoshiokの日記

hyoshiokの日々思うことをあれやこれや

gdb豆知識(続き)

gdb豆知識(d:id:hyoshiok:20080926#p1)の続き。

Windowsの開発環境は知らないのだけど、噂によると素敵なIDE(統合開発環境)が整備されていて、マウスでぐりぐり、ヘルプも充実、簡単簡単らしい。それから比べると、GNU Emacs+gcc+gdbというのは微妙にレトロ感あふれる。とは言うもののデバッグのプロセスはIDE的マルチウィンドウ、GUIでグリグリであろうとなかろうと基本は変らないので、よしとしよう。

コンパイル時のオプション

gccの-gオプションを付ける。Makefileコンパイルオプションは通常CFLAGSなのでCFLAGS=-gとしておく。最適化オプション(-O)と同時に付けることができるので(素晴しい)、最適化オプションも適当に付けておく。

時々、デバッグオプション(-g)を付けるときは最適化オプションをつけない、あるいは-O0(アルファベットのオーにゼロ)をするというような都市伝説のようなものがあるが、わたしは意味がないと思う。最適化したコードは、ソースコードの字面とは異なる実行フローとか、関数のインライン化とかいろいろ施されているが、それも含めてのデバッグプロセスになれるようにしたい。

gccのmanには下記のようなことが書いてある。

       -g  Produce debugging information in the operating system's
           native format (stabs, COFF, XCOFF, or DWARF 2).  GDB can
           work with this debugging information.

           On most systems that use stabs format, -g enables use of
           extra debugging information that only GDB can use; this
           extra information makes debugging work better in GDB but
           will probably make other debuggers crash or refuse to read
           the program.  If you want to control for certain whether to
           generate the extra information, use -gstabs+, -gstabs,
           -gxcoff+, -gxcoff, or -gvms (see below).

           GCC allows you to use -g with -O.  The shortcuts taken by
           optimized code may occasionally produce surprising results:
           some variables you declared may not exist at all; flow of
           control may briefly move where you did not expect it; some
           statements may not be executed because they compute
           constant results or their values were already at hand; some
           statements may execute in different places because they
           were moved out of loops.

           Nevertheless it proves possible to debug optimized output.
           This makes it reasonable to use the optimizer for programs
           that might have bugs.

gdbの起動方法

emacsの中から M-x gdb で起動する。プログラム名を入力する。

Current directory is ~/work/coreutils-6.10/build-tree/coreutils-6.10/src/
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) 

というような感じで起動できると思う。

ブレークポイントの設定

ブレークポイントは break (bと省略する) で設定する。

(gdb) b main
Breakpoint 1 at 0x8049724: file nl.c, line 455.

実行の開始

run 引数 で実行を開始する。下記はnlというプログラムにnl.cという引数を与えた例である。ブレークポイントが設定してあれば、そこに到達すると実行を一時停止する。

(gdb) run nl.c
Starting program: /home/hyoshiok/work/coreutils-6.10/build-tree/coreutils-6.10/src/nl nl.c
Breakpoint 1, main (argc=2, argv=0xbffa5c94) at nl.c:455
(gdb) 

(おまけ)使ったことのないコマンド

  • dump/append/restore

メモリの内容をファイルにダンプしたりリストアしたりするコマンドかあ。使ったことないや。

  • generate-core-file/gcore

coreファイルを生成するコマンド。使ったことないや。

  • init-if-undefined 変数=式

変数が未定義だったら式を代入。利用者定義のコマンドなんかで便利に使えそうだ。使ったことないや。

(gdb) p $a
$30 = void
(gdb) init-if-undefined $a=1
(gdb) p $a
$31 = 1
(gdb) init-if-undefined $a=2
(gdb) p $a
$32 = 1
(gdb) set $b=10
(gdb) p $b
$33 = 10
(gdb) init-if-undefined $b=1
(gdb) p $b
$34 = 10

続く。