Every section has a virtual address (VMA) and a load address (LMA); see
Basic Script Concepts. The virtual address is specified by the
see Output Section Address described earlier. The load address is
specified by the AT
or AT>
keywords. Specifying a load
address is optional.
The AT
keyword takes an expression as an argument. This
specifies the exact load address of the section. The AT>
keyword
takes the name of a memory region as an argument. See MEMORY. The
load address of the section is set to the next free address in the
region, aligned to the section's alignment requirements.
If neither AT
nor AT>
is specified for an allocatable
section, the linker will use the following heuristic to determine the
load address:
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;