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 import 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 placement 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 stopThe 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.oThe 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 eoaFrom the symbol table it is obvious that the .text is placed
starting from address 0x0 and .data section is placed starting
from address 0x400.