If we use readelf -s to view the character table, we will see:
$ readelf -s prog1.o Symbol 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 character ("variable") at this stage is a "common" character. He has not yet been "nominated" by the BSS.
See this question for more information on โcommonโ characters: What does โCOMโ mean in the Ndx column of a .symtab section?
Once your final executable is linked together, it will be placed in BSS, as you expected.
You can get around 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 can mark uninit as static . Thus, the compiler will know that no other .o file can reference it, so it will not be a โcommonโ character. Instead, it will be placed in 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
Jonathon reinhart
source share