2
votes

I am new to embedded systems low-level programming and I am quite confused what happens exactly after the linker generate an output object file and during flashing the .bin file.

1- I see in the linker script that the loadable memory address(LMA) and virtual memory address(VMA) of a .bss section is in RAM, my question is how does it initially go to RAM since I flash my binary image in FLASH memory?

2- The start up codes I saw only zero out the .bss section in RAM, but how did it even get there if the start-up code didn't copy it to RAM as it does with the .data section ?

1
You could answer that yourself by checking which variables go to .bss and which initial value they have. Not clear what your problem is.too honest for this site
@Olaf I do understand that the .bss holds the uninitialized variables, but don't we still need a reference for the non-local variables that has zero value ? I mean do we actually flash the .bss section or do we just create a section filled with zeros in runtime ?Keith Ape
"I do understand that the .bss holds the uninitialized variables" - No, it does not! You might want to read more about this. Note also this is nothing even mentioned in the standard per se and platform-dependent.too honest for this site
The .bss section is not part of the .data section* in gcc, but a seperate NOLOAD section! Check your linker control file, read the ld-documentation. A segment is a different thing. "No it does not" - I cited the wrong assumption, not clear what you don't understand, but maybe you follow my advice and read the standard. Hint: Objects going into .bss for implementations which support it are initialised! In fact, you stated that yourself already. Well-meant: Sometimes it is a good thing to step back to see the whole picture. If you are too close you only see coloured dots.too honest for this site
I think your question is answered in the manual under output section LMA near the bottom of the page. Usually you need some assembler start up code to copy init data to RAM, set up a stack and zero the BSS. Then you can call a minimal 'C' function.artless noise

1 Answers

3
votes

It looks like the commenters largely answered your question, but putting this here for future folks who may come across the question:

What you're seeing here is an optimization. The .bss section by definition* is all 0's. While you could write a large array of zeros to flash and then copy the large array of zeros to ram on boot, why bother? All you really need to know is where the "relocated" array of 0's needs to end up. The linker file will usually define symbols named something like _sbss and _ebss (also commonly seen as _szero and _ezero). Now, the whole .bss section only takes up two words of memory in flash (the _sbss and _ebss symbols). Your startup routine (code that runs before main(), the same thing that copied the other data) can do something like memset(_sbss, 0, _ebss-_sbss) and the .bss section is set up and ready to go.

*in your, and most, modern environments .bss is defined to be all zeroes.