sysvbannerの動きをGDBで追う(ステップ実行と変数表示)

sysvbannerの動きをGDBで追う(GDBの起動)」の続きです。mainにブレイクポイントを設定してrunした所から始めます。

(gdb) b main
Breakpoint 1 at 0x8048440: file banner.c, line 132.
(gdb) run HELLO
Starting program: /home/takk/sysvbanner-1.0.15/banner HELLO

Breakpoint 1, main (argc=2, argv=0xbffff794) at banner.c:132
132	  for (argv++; --argc; argv++) {
(gdb) 

ステップ実行(ステップオーバー)は、「next」(省略「n」)です。ステップイン(関数内に入る)は、「step」(省略「s」)です。

(gdb) n
133	    len = strlen(*argv);
(gdb) 

何も入力せずに、Enterだけを押すと、前回実行したコマンドが実行されます。ですので、ステップ実行を連続で行う場合は、「next」の後、Enterだけを叩いていけば良いです。この辺りの操作性はとても良いです。

(gdb) 
134	    if (len > 10)
(gdb) 

続けてEnter。

(gdb) 
136	    for (a = 0; a < 7; a++) {
(gdb) 

変数の内容を表示する場合は、「print」(省略「p」)です。

136	    for (a = 0; a < 7; a++) {
(gdb) p a
$1 = 134514194
(gdb) 

このタイミングでaの内容を表示しても、初期化されていませんので、0は入っていません。nextで次の行へ移ったタイミングで確認すると0で初期化されています。

(gdb) n
137	      for (b = 0; b < len; b++) {
(gdb) p a
$2 = 0
(gdb) 

さて、printコマンドでは、毎回入力しなければならないので面倒です。予め登録した変数の内容を毎回表示したいときは、「display」(省略「disp」)を使います。

136	    for (a = 0; a < 7; a++) {
(gdb) disp a
1: a = 134514194
(gdb) n
137	      for (b = 0; b < len; b++) {
1: a = 0
(gdb) 

オート変数をすべてdisplayで表示するように登録したいと思います。mainのすぐ下にあるオート変数を確認してみましょう。「list」コマンドでmain関数から+4行目を表示してみます。

(gdb) list main,+4
128	{
129	  int a, b, c, len, ind;
130	  char line[80];
131	
132	  for (argv++; --argc; argv++) {
(gdb) 

これらの変数をdisplayで登録してみます。aは既に登録していますので、b,c,len,ind,lineについて登録します。

(gdb) display b
2: b = 134523828
(gdb) display c
3: c = 47
(gdb) display len
4: len = 5
(gdb) display ind
5: ind = 134513341
(gdb) display line
6: line = "\001\000\000\000,\000\000\000\006\000\000\000}0\264,\000\000\000\000\064\367\377\277\250\366\377\277\240\366\377\277\062\202\004\b0\371\377\267\000\000\000\000\277\000\000\000\026o\352\267\377\377\377\377\316\366\377\277\370\333\341\267C\"\344\267\000\000\000\000}0\264,\001\000\000"
(gdb) 

登録したので、プログラムを最初から動かしてみます。最初から始めるか聞かれるので、y、Enterを押します。

(gdb) run HELLO
The program being debugged has been started already.
Start it from the beginning? (y or n) 
(gdb) run HELLO
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/takk/sysvbanner-1.0.15/banner HELLO

Breakpoint 1, main (argc=2, argv=0xbffff794) at banner.c:132
132	  for (argv++; --argc; argv++) {
6: line = "\001\000\000\000,\000\000\000\006\000\000\000}0\264,\000\000\000\000\064\367\377\277\250\366\377\277\240\366\377\277\062\202\004\b0\371\377\267\000\000\000\000\277\000\000\000\026o\352\267\377\377\377\377\316\366\377\277\370\333\341\267C\"\344\267\000\000\000\000}0\264,\001\000\000"
5: ind = 134513341
4: len = -1073743695
3: c = 47
2: b = 134523828
1: a = 134514194
(gdb) 

この状態でステップ実行していきましょう。nextします。

(gdb) n
133	    len = strlen(*argv);
6: line = "\001\000\000\000,\000\000\000\006\000\000\000}0\264,\000\000\000\000\064\367\377\277\250\366\377\277\240\366\377\277\062\202\004\b0\371\377\267\000\000\000\000\277\000\000\000\026o\352\267\377\377\377\377\316\366\377\277\370\333\341\267C\"\344\267\000\000\000\000}0\264,\001\000\000"
5: ind = 134513341
4: len = -1073743695
3: c = 47
2: b = 134523828
1: a = 134514194
(gdb) 

この時点では、strlen()は実行されていませんので、lenにはわけの分からない値が入っていますね。このままEnter押せば、strlen()が実行されますので、

(gdb) 
134	    if (len > 10)
6: line = "\001\000\000\000,\000\000\000\006\000\000\000}0\264,\000\000\000\000\064\367\377\277\250\366\377\277\240\366\377\277\062\202\004\b0\371\377\267\000\000\000\000\277\000\000\000\026o\352\267\377\377\377\377\316\366\377\277\370\333\341\267C\"\344\267\000\000\000\000}0\264,\001\000\000"
5: ind = 134513341
4: len = 5
3: c = 47
2: b = 134523828
1: a = 134514194
(gdb) 

lenには5が格納されました。

次に、displayの変数を解除してみます。「undisplay 番号」(省略「und」)で、lineの表示を解除します。lineの番号である6を指定します。

(gdb) und 6
(gdb) disp
5: ind = 134513341
4: len = 5
3: c = 47
2: b = 134523828
1: a = 134514194
(gdb) 

全部解除したい場合は、引数なしでundisplayします。

(gdb) und 6
(gdb) disp
5: ind = 134513341
4: len = 5
3: c = 47
2: b = 134523828
1: a = 134514194
(gdb) 

10進、16進等の表示スタイルは、「display/書式」で指定できます。

(gdb) disp/s *argv
1: x/s *argv  0xbffff8d5:	"HELLO"
(gdb) disp/c c
2: /c c = 47 '/'
(gdb) disp/x a
3: /x a = 0x8048612
(gdb) 

/sは文字列、/cは文字、/xは16進、/oは8進、/dは10進指定となります。

コメント

タイトルとURLをコピーしました