I have a very simple linker script for a RISC-V bare-metal target:
link.ld
:
MEMORY
{
ram (rwx) : ORIGIN = 0, LENGTH = 0x1000
}
SECTIONS
{
. = 0x00000000;
.text : {
. = ALIGN(4);
*(.text)
*(.text.startup)
*(.rodata)
} > ram
.data : {
. = ALIGN(4);
*(.data)
} > ram
.bss : {
. = ALIGN(4);
__BSS_START__ = .;
*(.bss*)
*(COMMON)
__BSS_END__ = .;
} > ram
_end = .;
_sp_start = 0x00000fff;
_start = 0;
}
Everything works fine, I can compile and run embedded applications.
I'm trying to define an ELF file section that doesn't count for the allocated space, isn't loaded, etc. Pretty much the same thing as the debug symbols sections, just with arbitrary data.
So, I checked the ld
docs about Output Section Type:
DSECT
COPY
INFO
OVERLAY
These type names are supported for backward compatibility, and are rarely used. They all have the same effect: the section should be marked as not allocatable, so that no memory is allocated for the section when the program is run.
So I updated my linker script to:
MEMORY
{
ram (rwx) : ORIGIN = 0, LENGTH = 0x1000
}
SECTIONS
{
. = 0x00000000;
.text : {
. = ALIGN(4);
*(.text)
*(.text.startup)
*(.rodata)
} > ram
.data : {
. = ALIGN(4);
*(.data)
} > ram
.bss : {
. = ALIGN(4);
*(.bss*)
*(COMMON)
} > ram
.metadata (INFO): {
. = ALIGN(4);
*(.metadata)
}
_end = .;
_sp_start = 0x00000fff;
_start = 0;
}
And in my code, I added:
char metadata_buffer[] __attribute__ ((section (".metadata"))) = "METADATA";
Compiling, I see the new .metadata
section in the ELF file, but its size isn't 0
:
$ readelf -e app.elf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
...
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 001000 000206 00 AX 0 0 2
[ 2] .eh_frame PROGBITS 00000208 001208 0000f4 00 A 0 0 4
[ 3] .data PROGBITS 000002fc 0012fc 000000 00 WA 0 0 1
[ 4] .bss NOBITS 000002fc 0012fc 000000 00 WA 0 0 1
[ 5] .metadata PROGBITS 000002fc 0012fc 000009 00 W 0 0 4
...
[17] .shstrtab STRTAB 00000000 007deb 0000b4 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00000000 0x00000000 0x002fc 0x002fc RWE 0x1000
Section to Segment mapping:
Segment Sections...
00 .text .eh_frame
The size of the only program header didn't changed.
If in my code I do:
char metadata_buffer[10000] __attribute__ ((section (".metadata"))) = "METADATA";
I get this error when linking:
riscv32-unknown-elf/bin/ld: pe_gemv_0_0_0.elf section `.metadata' will not fit in region `ram'
riscv32-unknown-elf/bin/ld: region `ram' overflowed by 8716 bytes
Why? The .metadata
section is not in ram
.
If I define a dummy memory region and put .metadata
there, I can link. I don't understand why do I need to do this though.
MEMORY
{
ram (rwx) : ORIGIN = 0, LENGTH = 0x1000
other (rwx) : ORIGIN = 0, LENGTH = 0x1000000
}
SECTIONS
{
...
.metadata (INFO): {
. = ALIGN(4);
*(.metadata)
} > other
}
Any help is appreciated! Cheers!
Regarding why the .metadata
output section gets allocated within the MEMORY command's ram
region, check out the following text from the MEMORY chapter of the binutils docs:
The linker will place other sections which are not explicitly mapped into a memory region into the ‘ram’ memory region.
.. where the 'ram' region alludes to the example provided in that chapter.
So, if you have not associated an output section within the SECTION
command invocation in your linker script to a specific MEMORY region, binutils defaults to using the only MEMORY region that you have specified for that unassociated output section, which is the ram
memory region.
This is also why you get the region ram overflowed
error.
Hope that helps.