今回も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関数のあるソースにグローバル変数がある場合と全く同じになりました。
まだ、よく分からず。


コメント