According to the ld manual on the special symbol .
, i.e.the Location Counter.
Note: . actually refers to the byte offset from the start of the current containing object. Normally this is the SECTIONS statement, whose start address is 0, hence . can be used as an absolute address. If . is used inside a section description however, it refers to the byte offset from the start of that section, not an absolute address. Thus in a script like this:
SECTIONS { . = 0x100 .text: { *(.text) . = 0x200 } . = 0x500 .data: { *(.data) . += 0x600 } }
The '.text' section will be assigned a starting address of 0x100 and a size of exactly 0x200 bytes, even if there is not enough data in the `.text' input sections to fill this area.
And the ld manual also says about output section's VMA and LMA:
Every loadable or allocatable output section has two addresses. The first is the VMA, or virtual memory address. This is the address the section will have when the output file is run. The second is the LMA, or load memory address. This is the address at which the section will be loaded. In most cases the two addresses will be the same. An example of when they might be different is when a data section is loaded into ROM, and then copied into RAM when the program starts up (this technique is often used to initialize global variables in a ROM based system). In this case the ROM address would be the LMA, and the RAM address would be the VMA.
So my question is:
If an output section is specified with different VMA and LMA, what's the base address for the byte offset .
?
In the below example, the .data
section has different VMA and LMA. My understanding is PLACE 1
specify the LMA
is in ROM2
, while PLACE 2
specify the VMA
is in RAM
? So what's the base address for the .
symbol within the .data
section?
SECTIONS
{
.text :
{
*(.text)
} > REGION_TEXT
.rodata :
{
*(.rodata)
rodata_end = .;
} > REGION_RODATA
.data : AT (rodata_end) <=========== PLACE 1
{
data_start = .;
*(.data)
} > REGION_DATA <=========== PLACE 2
data_size = SIZEOF(.data);
data_load_start = LOADADDR(.data);
.bss :
{
*(.bss)
} > REGION_BSS
}
The memory layout is below:
MEMORY
{
ROM : ORIGIN = 0, LENGTH = 2M /*0M ~ 2M*/
ROM2 : ORIGIN = 0x10000000, LENGTH = 1M /*256M ~ 257M*/
RAM : ORIGIN = 0x20000000, LENGTH = 1M /*512M ~ 513M*/
}
REGION_ALIAS("REGION_TEXT", ROM); /*0M ~ 2M*/
REGION_ALIAS("REGION_RODATA", ROM2); /*256M ~ 257M*/
REGION_ALIAS("REGION_DATA", RAM); /*512M ~ 513M*/
REGION_ALIAS("REGION_BSS", RAM); /*512M ~ 513M*/
To answer your question one can make use of two facts from the official ld
documentation.
First fact from Output Section LMA.
The following linker script creates three output sections: one called
.text
, which starts at0x1000
, one called.mdata
, which is loaded at the end of the.text
section even though its VMA is0x2000
, and one called.bss
to hold uninitialized data at address0x3000
. The symbol_data
is defined with the value0x2000
, 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 = . ;}
}
Second fact from The Location Counter.
. actually refers to the byte offset from the start of the current containing object. Normally this is the
SECTIONS
statement, whose start address is0
, hence.
can be used as an absolute address. If.
is used inside a section description however, it refers to the byte offset from the start of that section, not an absolute address.
Putting together these two pieces of information, one can say that the location counter specifies a VMA value by giving its offset from the start address of the current containing object (SECTIONS
statement or output section).
So the absolute base address for the location counter is
SECTIONS
statement – that is 0
– if we refer to .
outside an output section definition.
inside
that output sectionAs for the .data
section in your example, you’re right: PLACE 1
specifies the LMA is in ROM2
while PLACE 2
specify the VMA is in RAM
.
Since the location counter, when used inside a section description, refers to the byte offset from the start of that section, the base address for the .
symbol within the .data
section is 0
. However this is a relative address and it corresponds to the absolute address 0x20000000
which is the VMA of the .data
section. By the way, this is coherent with the fact stated above that PLACE 2
specifies the VMA is in the RAM
memory region (alias REGION_DATA
).
If your example were a real one, you could easily check what has just been stated by using the ADDR(section)
linker script language builtin function to get the VMA for the .data
section.