sizeコマンドで苦手なセクションを覚える

今回もsizeコマンドです。

ずっと苦手、というかまったく理解してなかった、コンパイル、リンク、加えてセクションって何者なのか。この辺りの苦手意識を克服するためしばらくsizeコマンドで遊んでみます。
おそらく、どこかにある書籍を読めば、難しく書いてあるんじゃないかと思うんです。もしくは、gccのソース理解するとか。
しかし、今の私のスキルでは、どちらの方法も辛いんです(いや、スキルがあったとしても難しい本は読みませんが)。サルでも分かるとか、10日で分かるとかいう本があれば読むんですが、頭の良い人が分かる本って、簡単なことを難しく書いてあるんですよね。

とにかく使って覚えていこうと思います。
闇雲に使っているうちに、だんだん分かってくるんじゃないかと思ってます。

はい、続きです。
グローバル変数の定義だけのソースをコンパイルすると、どのセクションにも割り当たりませんでした。sizeコマンドの表示もオール0でしたね。

takk@deb9:~/tmp$ cat var1.c
char tmp[100];
takk@deb9:~/tmp$ gcc -c var1.c
takk@deb9:~/tmp$ size var1.o
   text	   data	    bss	    dec	    hex	filename
      0	      0	      0	      0	      0	var1.o
takk@deb9:~/tmp$ objdump -s var1.o

var1.o:     ファイル形式 elf64-x86-64

セクション .comment の内容:
 0000 00474343 3a202844 65626961 6e20362e  .GCC: (Debian 6.
 0010 332e302d 31382b64 65623975 31292036  3.0-18+deb9u1) 6
 0020 2e332e30 20323031 37303531 3600      .3.0 20170516.  
takk@deb9:~/tmp$ 

おそらくグローバル変数がどこからも使用されないからだと思います。
この変数をどこかで使えば、セクション確保されるのではないか、と考えました。
そして、こんなソースを思いつきます。

takk@deb9:~/tmp$ cat var2.c
char tmp[100];
char *tmp2=tmp;
takk@deb9:~/tmp$ 

tmp変数は、初期値がないためbssセクションに配置されるはずで、
tmp2は、tmpのアドレスを初期値としているためdataセクションに配置されるはず。

takk@deb9:~/tmp$ gcc -c var2.c
takk@deb9:~/tmp$ size var2.o
   text	   data	    bss	    dec	    hex	filename
      0	      8	      0	      8	      8	var2.o
takk@deb9:~/tmp$ objdump -s var2.o

var2.o:     ファイル形式 elf64-x86-64

セクション .data.rel.local の内容:
 0000 00000000 00000000                    ........        
セクション .comment の内容:
 0000 00474343 3a202844 65626961 6e20362e  .GCC: (Debian 6.
 0010 332e302d 31382b64 65623975 31292036  3.0-18+deb9u1) 6
 0020 2e332e30 20323031 37303531 3600      .3.0 20170516.  
takk@deb9:~/tmp$ 

ん~。bssに配置されてません。

あきらめて、次。

main関数があるとどうでしょうか。変数定義がない場合の空main関数のみでビルド。

takk@deb9:~/tmp$ cat main1.c
int main()
{

}
takk@deb9:~/tmp$ gcc main1.c
takk@deb9:~/tmp$ size
   text	   data	    bss	    dec	    hex	filename
   1521	    544	      8	   2073	    819	a.out
takk@deb9:~/tmp$ 

このbssの数字を覚えておいて、次は変数定義ありでビルド。

takk@deb9:~/tmp$ cat main2.c
char tmp[100];
int main()
{

}
takk@deb9:~/tmp$ gcc main2.c
takk@deb9:~/tmp$ size
   text	   data	    bss	    dec	    hex	filename
   1521	    544	    136	   2201	    899	a.out
takk@deb9:~/tmp$ 

bssが、8から136Byteに増えました。
コンパイルだけでなく、ビルド(リンク)まですると、bssセクションが確保されるってことでしょうか。

次は、空のmainで、グローバル変数のextern定義のみ。これはmain関数でtmp変数を使用していないため、ビルドできます。

takk@deb9:~/tmp$ cat main3.c
extern char tmp[100];
int main()
{

}
takk@deb9:~/tmp$ gcc main3.c
takk@deb9:~/tmp$ size
   text	   data	    bss	    dec	    hex	filename
   1521	    544	      8	   2073	    819	a.out
takk@deb9:~/tmp$ 

またbssが8になりました。

次は、2つのファイルをリンクしてみます。

takk@deb9:~/tmp$ cat main3.c
extern char tmp[100];
int main()
{

}
takk@deb9:~/tmp$ cat var1.c
char tmp[100];
takk@deb9:~/tmp$ gcc main3.c var1.c
takk@deb9:~/tmp$ size
   text	   data	    bss	    dec	    hex	filename
   1521	    544	    136	   2201	    899	a.out
takk@deb9:~/tmp$ 

main関数のあるソースにグローバル変数がある場合と全く同じになりました。

まだ、よく分からず。

Leave a Reply

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

CAPTCHA