Determining BSS Size on Object File
If we use readelf -s
to look at the symbol table, we'll see:
$ readelf -s prog1.oSymbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS bss.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 6 6: 0000000000000000 0 SECTION LOCAL DEFAULT 7 7: 0000000000000000 0 SECTION LOCAL DEFAULT 5 8: 0000000000000004 4 OBJECT GLOBAL DEFAULT COM uninit <<<< 9: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 main
We see that your uninit
symbol ("variable") is, at this stage, a "common" symbol. It has not yet been "assigned" to the BSS.
See this question for more information on "common" symbols: What does "COM" means in the Ndx column of the .symtab section?
Once your final executable is linked together, it will be put in the BSS as you expected.
You can bypass this behavior by passing the -fno-common
flag to GCC:
$ gcc -fno-common -c bss.c$ size bss.o text data bss dec hex filename 72 0 4 76 4c bss.o
Instead, you could mark uninit
as static
. This way, the compiler will know that no other .o
file can refer to it, so it will not be a "common" symbol. Instead, it will be placed into the BSS immediately, as you expected:
$ cat bss.c
static int uninit;int main() { uninit = 1; return 0;}
$ gcc -c bss.c $ size bss.o text data bss dec hex filename 72 0 4 76 4c bss.o