3.6.8.2 Output Section LMA

Every section has a virtual address (VMA) and a load address (LMA); see Basic Script Concepts. The address expression which may appear in an output section description sets the VMA (see Output Section Address).

The expression lma that follows the AT keyword specifies the load address of the section.

Alternatively, with AT>lma_region expression, you may specify a memory region for the section's load address. See MEMORY. Note that if the section has not had a VMA assigned to it then the linker will use the lma_region as the VMA region as well.

If neither AT nor AT> is specified for an allocatable section, the linker will set the LMA such that the difference between VMA and LMA for the section is the same as the preceding output section in the same region. If there is no preceding output section or the section is not allocatable, the linker will set the LMA equal to the VMA. See Output Section Region.

This feature is designed to make it easy to build a ROM image. For example, the following linker script creates three output sections: one called .text, which starts at 0x1000, one called .mdata, which is loaded at the end of the .text section even though its VMA is 0x2000, and one called .bss to hold uninitialized data at address 0x3000. The symbol _data is defined with the value 0x2000, which shows that the location counter holds the VMA value, not the LMA value.

     SECTIONS
       {
       .text 0x1000 : { *(.text) _etext = . ; }
       .mdata 0x2000 :
         AT ( ADDR (.text) + SIZEOF (.text) )
         { _data = . ; *(.data); _edata = . ;  }
       .bss 0x3000 :
         { _bstart = . ;  *(.bss) *(COMMON) ; _bend = . ;}
     }

The run-time initialization code for use with a program generated with this linker script would include something like the following, to copy the initialized data from the ROM image to its runtime address. Notice how this code takes advantage of the symbols defined by the linker script.

     extern char _etext, _data, _edata, _bstart, _bend;
     char *src = &_etext;
     char *dst = &_data;
     
     /* ROM has data at end of text; copy it. */
     while (dst < &_edata) {
       *dst++ = *src++;
     }
     
     /* Zero bss */
     for (dst = &_bstart; dst< &_bend; dst++)
       *dst = 0;