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