the 1st edition: 20120304 the 2nd edition: 20250505env: in 32bit linux, 64 bit 似乎有點不同??
在沒有 os 的環境下搞懂 bss 有點麻煩嗎?這次提供在 os 環境下, 看看 bss。首先找出 bss 開始和結束的地方。先來看看 default linker script。
我知道很長, 我和你一樣大部份有看沒有懂, 只看 list 1. L158 ~ L173 就好。
158 __bss_start = .; 159 .bss : 160 { 161 *(.dynbss) 162 *(.bss .bss.* .gnu.linkonce.b.*) 163 *(COMMON) 164 /* Align here to ensure that the .bss section occupies space up to 165 _end. Align after .bss to ensure correct alignment even if the 166 .bss section disappears because there are no input sections. 167 FIXME: Why do we need it? When there is no .bss section, we don't 168 pad the .data section. */ 169 . = ALIGN(. != 0 ? 32 / 8 : 1); 170 } 171 . = ALIGN(32 / 8); 172 . = ALIGN(32 / 8); 173 _end = .; PROVIDE (end = .);
_end, __bss_start 這兩個 symbol 就是 bss section 的開始和結束。先來看看程式執行結果。
i: 0x8049734
i: 0x8049738
&__bss_start: 0x8049734
&_end: 0x804973c
ABCDEF: 11223344
bss 從 0x8049734 ~ 0x804973c 佔了 8 byte。
b.c L3 ABCDEF 不是預期的 0。表示成功改變 bss 這個區域。這應該簡單多了, 而且也可以馬上在 linux 上實驗。
另外有的人可能會因為 b.c L3 的寫法好像沒給變數初值, 改用 L4 的寫法, 指定了 0 就以為是以 0 為初值, 在這個例子上, 就算這樣寫, ABCDEF 一樣是 11223344。
有趣的是, 如果是給 1, int ABCDEF = 1; 則 ABCDEF 的初值就還是1, 因為這時候 ABCDEF 就不放在 bss section 而是放在 data section。
看看 elf 裡頭的資訊:
[26] .bss NOBITS 08049734 000734 000008 00 WA 0 0 4 63: 08049738 4 OBJECT GLOBAL DEFAULT 26 ABCDEFbss 佔 8 byte, ABCDEF 則位於 0x08049738
source code: git clone git@github.com:descent/progs.git' cd bss
ref:
linux kernel 完全剖析 (3.5.4 p 96)