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 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 = . ;}
}
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 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.
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
- the start address of the
SECTIONS
statement – that is 0
– if we refer to .
outside an output section definition
- the VMA of an output section if we refer to
.
inside
that output section
As 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.
After I read a few more ld scripts, I came to the following understanding:
I wrote the below snippet for illustration of section declaration statement.
So as illustrated above, the section
declaration in a ld script has 2 important things to specify:
- the LMA at load time
- the VMA at run time
We can specify these addresses in 2 ways:
- precisely at a specific address
- or append to a memory region
These 2 ways have different positions in the section declaration statement as shown above, before or after the curly brace.
A section itself is a RIGID BODY. The location counter .
ONLY stands for the offset within its containing object. No more, no less. It's neither VMA nor LMA.
The offset's base can be either VMA or LMA of the containing section, depending on it is runtime or loadtime your are talking about.
But in a symbol assignment statement like below or other symbol manipulations with in a section declaration, VMA is used a the base of .
.
.data_flash : {_data_flash = .;} >CODE