Martel
Martel

Reputation: 2734

Understanding linker script NOLOAD sections in embedded software

According to the GNU documentation for ld, a NOLOAD section works as following:

The `(NOLOAD)' directive will mark a section to not be loaded at run time. The linker will process the section normally, but will mark it so that a program loader will not load it into memory.

Now, regarding to the program loader, accordign to wikipedia:

Embedded systems typically do not have loaders, and instead, the code executes directly from ROM. In order to load the operating system itself, as part of booting, a specialized boot loader is used.

Then, what exactly a NOLOAD section does for FW / embedded software?

Upvotes: 10

Views: 15132

Answers (2)

Martel
Martel

Reputation: 2734

I have done several experiments, so I will add an answer in the specific context of embedded software, in particular in absence of loaders (included flash tools with such functionality). This is my understanding after the experiments I have done, but if anything is wrong I will be more than happy to edit the answer.

It's true that NOLOAD will mark a section so that 'the loader' knows that it must not load it into memory. Something similar will happen for flashing tools that receive an .elf file as an input, therefore, to some extent, act as loaders.

However, there are many cases in embedded software in which a loader is not present, for instance if the target device allows to update the firmware only with raw binary files, and it just copies the raw data at a particular address and nothing else. In this cases, NOLOAD will be useful to avoid making the raw binary file unnecessarily big: it will prevent a section to be added to the final binary file when it's not desirable.

Use cases in which it would not be desirable:

  • If the section in question needs to be initialized to a known value, such as 0x0, 0xff, or some magic number and then all 0x0 etc. Therefore it's not worth to have a (potentially) big section full of 0xff's, when this can be done in a loop at the startup script.
  • If that particular area of memory must not be overwritten during the update process. Beware of this will require to place that section at a particular position. See below.
  • If the section contains non-initialized data, such as .bss, but it's not .bss, in which case NOLOAD will need to be set explicitly. Of course, this will need to be initialized to 0 or whatever constant value by the startup script.

Notice that the NOLOAD section will still be present in the .elf file (it won't be marked as LOAD though), but it should be removed by objcopy when generating the raw binary file. There is one exception to this though: objcopy cannot 'remove' a section in between another two because it needs to keep the memory map somehow. For instance, having sections A B C, NOLOAD won't work on B, because objcopy will need to fill B with zeros to keep the offset of section C as expected. However, if C is NOLOAD and it's the last (potentially loadable) section, then it can be removed from the final binary image.

Another special case I have observed is the .bss section. This section is always treated (at least by my version of riscv64-uknown-elf toolchain) as NOLOAD, regardless if the linker script specifies it or not.

In summary, the uses of NOLOAD for embedded systems that do not use a loader are: to keep raw binary images smaller, or to not overwrite memory regions (usually flash) that one wants to leave with the value they had before the firmware update process started.

What NOLOAD cannot do if no loader is present, a.k.a. FW is updated as raw binary files, is to avoid a section to be put in a raw binary file if that section is in between another two that do need to be loaded. In such case, all the the NOLOAD sections will need to be moved to the end of the loadable memory.

As a side note, for the case of avoiding to overwrite memory, as far as I can see that could be worked out by not declaring that section at all. If symbols in that section need to be referenced from the source code, just declare those symbols at the right addresses.

Upvotes: 4

Guillaume Petitjean
Guillaume Petitjean

Reputation: 2718

The NOLOAD section defines a section that is required to link the program properly but must not be loaded to memory. For example you may need to link your program with some code located in ROM, so you tell the linker to mark the code in ROM as NOLOAD. Then the tool that will load the program (a debugger, an OS or whatever) will not load this part of the code.

Upvotes: 8

Related Questions