As mentioned in the previous section, section merging and placement is done by the linker. The programmer can control how the sections are merged, and at what locations they are placed in memory through a linker script file. A very simple linker script file, is shown below.
The SECTIONS command is the most important linker
command, it specifies how the sections are to be merged and at what
location they are to be placed. |
|
Within the block following the
SECTIONS command, the . (period) represents the location counter. The
location is always initialised to 0x0 .
It can be modified by assigning a new value to it. Setting the
value to 0x0 at the beginning is
superfluous. |
|
This part of the script specifies
that, the .text section from the input
files abc.o and def.o should go to the .text section of the output file. |
The linker script can be further simplified and generalised by
using the wild card character *
instead of individually specifying the file names.
If the program contains both .text
and .data
sections, the .data
section merging and location can be
specified as shown below.
Listing 8. Multiple sections in linker scripts
SECTIONS {
. = 0x00000000;
.text : { * (.text); }
. = 0x00000400;
.data : { * (.data); }
}
Here, the .text
section is located
at 0x0
and .data
is located at 0x400
. Note that, if the location counter is not
assigned a different value, the .text
and .data
sections will be located at
adjacent memory locations.
To demonstrate the use of linker scripts, we will use the linker
script shown in Listing 8,
“Multiple sections in linker scripts” to control
the placement of a program’s .text
and .data
section. We will use a slightly modified version of the sum of
array program for this purpose. The code is shown below.
.data
arr: .byte 10, 20, 25 @ Read-only array of bytes
eoa: @ Address of end of array + 1
.text
start:
ldr r0, =eoa @ r0 = &eoa
ldr r1, =arr @ r1 = &arr
mov r3, #0 @ r3 = 0
loop: ldrb r2, [r1], #1 @ r2 = *r1++
add r3, r2, r3 @ r3 += r2
cmp r1, r0 @ if (r1 != r2)
bne loop @ goto loop
stop: b stop
The only change here is that the array is now in the
.data
section. Also note that the
nasty branch instruction to skip over the data is also not
required, since the linker script will place the .text
section and .data
section appropriately. As a result,
statements can be placed in the program, in any convenient way, and
the linker script will take care of placing the sections correctly
in memory.
When the program is linked, the linker script is passed as an input to the linker, as shown in the following command.
$ arm-none-eabi-as -o sum-data.o sum-data.s
$ arm-none-eabi-ld -T sum-data.lds -o sum-data.elf sum-data.o
The option -T sum-data.lds
specifies that sum-data.lds
is to be
used as the linker script. Dumping the symbol table, will provide
an insight into how the sections are placed in memory.
$ arm-none-eabi-nm -n sum-data.elf
00000000 t start
0000000c t loop
0000001c t stop
00000400 d arr
00000403 d eoa
From the symbol table it is obvious that the .text
is placed starting from address 0x0
and .data
section
is placed starting from address 0x400
.