Determining BSS Size on Object File Determining BSS Size on Object File c c

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