If I understand correctly, the .bss section in ELF files is used to allocate space for zero-initialized variables. Our tool chain produces ELF files, hence my question: does the .bss section actually have to contain all those zeroes? It seems such an awful waste of spaces that when, say, I allocate a global ten megabyte array, it results in ten megabytes of zeroes in the ELF file. What am I seeing wrong here?
If I understand correctly, the .bss section in ELF files is used to allocate
Share
Has been some time since i worked with ELF. But i think i still remember this stuff. No, it does not physically contain those zeros. If you look into an ELF file program header, then you will see each header has two numbers: One is the size in the file. And another is the size as the section has when allocated in virtual memory (
readelf -l ./a.out):Headers of type
LOADare the one that are copied into virtual memory when the file is loaded for execution. Other headers contain other information, like the shared libraries that are needed. As you see, theFileSizeandMemSizsignificantly differ for the header that contains thebsssection (the secondLOADone):For this example code:
The ELF specification says that the part of a segment that the mem-size is greater than the file-size is just filled out with zeros in virtual memory. The segment to section mapping of the second
LOADheader is like this:So there are some other sections in there too. For C++ constructor/destructors. The same thing for Java. Then it contains a copy of the
.dynamicsection and other stuff useful for dynamic linking (i believe this is the place that contains the needed shared libraries among other stuff). After that the.datasection that contains initialized globals and local static variables. At the end, the.bsssection appears, which is filled by zeros at load time because file-size does not cover it.By the way, you can see into which output-section a particular symbol is going to be placed by using the
-Mlinker option. For gcc, you use-Wl,-Mto put the option through to the linker. The above example shows thatais allocated within.bss. It may help you verify that your uninitialized objects really end up in.bssand not somewhere else:GCC keeps uninitialized globals in a COMMON section by default, for compatibility with old compilers, that allow to have globals defined twice in a program without multiple definition errors. Use
-fno-commonto make GCC use the .bss sections for object files (does not make a difference for the final linked executable, because as you see it’s going to get into a .bss output section anyway. This is controlled by the linker script. Display it withld -verbose). But that shouldn’t scare you, it’s just an internal detail. See the manpage of gcc.