目前已經了解到:.bss section 在 linking view 時是不佔檔案長度的,在 execution view 時,根據其長度來佔用記憶體大小。
關於 .bss section 的結構,其實一張圖就夠了。直接切入重點吧!
前言
先重新編譯 bss.c 範例:
# gcc -g -o bss bss.c
# ./bss
.bss section starts at 0x8049588
foo is 0.
foo is 12345.
.bss section starts at 0x8049588
依照先前日記的說明,.bss section 的長度為 12 bytes。無論程式是否有 uninitialized data,process 一定會有 .bss section,並且 .bss section 的長度至少為 4 bytes(IA32),第一筆資料是 "completed.1",該筆資料紀錄 .bss section 的起啟位址。
另外,在「linker script」裡,定義了一個叫 "__bss_start" 的符號,此符號才是紀錄 .bss section 的真正起始位址。不過,在此先不討論這個部份。
Process 的 .bss section 結構
Process 的 .bss section 佔用的記憶體大小,是根據 .bss section 的長度,在執行時期為每一筆 uninitialized data 保留下來的。其結構如下圖所示,我們以 bss.c 的範例來說明。
圖 .bss section 結構
由圖可以知道,範例的 .bss section 其 start address 為 0x8049584,這是直接查詢 .bss section 裡的 "completed.1" 符號得知的。'completed.1' 的 address 可利用 nm 查詢:
# nm -v bss|grep 'completed.1'
08049584 b completed.1
由此了解,.bss section 真正的 start address 應該是 'completed.1';不過,若把第一筆資料的 start address 當做 .bss section 的 start address 其實也無妨,或者說這是 .bss section「放 data」的 start address。
利用 gdb 來觀察
# gdb ./bss
...
(gdb) disassemble 0x8049588
Dump of assembler code for function foo:
0x08049588: add %al,(%eax)
0x0804958a: add %al,(%eax)
End of assembler dump.
(gdb) disassemble 0x8049584
Dump of assembler code for function completed.1:
0x08049584: add %al,(%eax)
0x08049586: add %al,(%eax)
(gdb) disassemble 0x804958c
Dump of assembler code for function bar:
0x0804958c: add %al,(%eax)
0x0804958e: add %al,(%eax)
End of assembler dump.