GDBアセンブラ表示とメモリダンプ


アニメ『アイドルメモリーズ』(2016)

バーチャル空間でのアイドル活動という、ん~、まあ、いろんなセットが使えるって感じでしょうか。1話しか見てませんが、いきなり空中戦始まって、あれ、バトルもの? と思ってしまった。このノリで続いてくれればいいなあと思いつつ視聴していたら、後半パートで、実写出てきました。声優陣。でもアニメより面白いかも。中国語講座とか突然始まって、ひさびざに中国語も再入門したいなあと思いました。

アイドルメモリーズということで、今回は、メモリ関連です。
いつも、簡単な確認用にC言語で、HELLOを表示するプログラムを使いますが、HELLOって文字列は、どこのメモリに格納されるのだろう、と最近気になり始めました。まあ、少しずつ調べていこうと思いますが、今回は、-gオプションをつけてGDBでHELLOが格納されているメモリを確認したいと思います。

使用するプログラムはおなじみのこれ。

takk@deb9:~/tmp$ cat t.c
#include <stdio.h>

int main()
{
	printf("HELLO\n");

	return 0;
}
takk@deb9:~/tmp$ 

-gオプションをつけてビルドし、GDBを起動します。

takk@deb9:~/tmp$ gcc -g t.c
takk@deb9:~/tmp$ gdb a.out
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...done.
(gdb) 

いつものようにmainにブレイクポイントを設定してrun。

(gdb) b main
Breakpoint 1 at 0x6b4: file t.c, line 5.
(gdb) r
Starting program: /home/takk/tmp/a.out 

Breakpoint 1, main () at t.c:5
5		printf("HELLO\n");
(gdb) 

ちょうどprintfの行でプログラムカウンタが停止してます。

プログラムカウンタの値を確認します。info registersコマンドで、pcを指定します。

(gdb) info reg pc
pc             0x5555555546b4	0x5555555546b4 <main+4>
(gdb) 

次に、disassembleコマンドで、現在のプログラムカウンタ前後のアセンブラを表示します。

(gdb) disass
Dump of assembler code for function main:
   0x00005555555546b0 <+0>:	push   %rbp
   0x00005555555546b1 <+1>:	mov    %rsp,%rbp
=> 0x00005555555546b4 <+4>:	lea    0x99(%rip),%rdi        # 0x555555554754
   0x00005555555546bb <+11>:	callq  0x555555554560 <puts@plt>
   0x00005555555546c0 <+16>:	mov    $0x0,%eax
   0x00005555555546c5 <+21>:	pop    %rbp
   0x00005555555546c6 <+22>:	retq   
End of assembler dump.
(gdb) 

callqの行にputsと表示されていますが、実はprintfは内部でputsが使用されるので、
このputsの実行前に、使用しているアドレスが、HELLOが格納されているメモリになります。コメント欄の# 0x555555554754が、それっぽいです。

メモリの内容を確認してみます。x/sを使うと、ヌル(0)が格納されているメモリまで文字列とみなして一気に表示してくれます。

(gdb) x/s 0x555555554754
0x555555554754:	"HELLO"
(gdb) 

HELLOが表示されました。やはりこのアドレスでした。

メモリの表示の仕方を変えてみます。x/1cを使うと、指定メモリを1文字だけ表示します。

(gdb) x/1c 0x555555554754
0x555555554754:	72 'H'
(gdb) 

Hの16進72と、Hが表示されました。
Enterだけを入力すると、前回実行したコマンドの続き実行してくれます。
メモリの表示コマンドなので、同じメモリを表示するのではなく、次のメモリを表示します。

つまりEnterだけを連続4回入力すると、

(gdb) 
0x555555554755:	69 'E'
(gdb) 
0x555555554756:	76 'L'
(gdb) 
0x555555554757:	76 'L'
(gdb) 
0x555555554758:	79 'O'
(gdb) 
0x555555554759:	0 '\000'
(gdb) 

このように、Hに続いてE、L、L、O、ヌル(0)が表示されます。

HELLOが定義されているメモリの後方には何が格納されているのでしょうか。
Enter入力を続けます。

(gdb) 
0x55555555475a:	0 '\000'
(gdb) 
0x55555555475b:	0 '\000'
(gdb) 
0x55555555475c:	1 '\001'
(gdb) 
0x55555555475d:	27 '\033'
(gdb) 
0x55555555475e:	3 '\003'
(gdb) 
0x55555555475f:	59 ';'
(gdb) 
0x555555554760:	56 '8'
(gdb) 
0x555555554761:	0 '\000'
(gdb) 

何か意味のありそうなデータが格納されています。

つづく

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA