implements proper linker script to support TLS

This change updates the linker script and dependend wile so that thread local
storage sections are properly supported and initailaized
This commit is contained in:
2026-02-01 06:43:47 +01:00
parent 6d5871687c
commit 1c9c00235d
7 changed files with 121 additions and 175 deletions

View File

@@ -4,9 +4,9 @@ ENTRY( _start )
INCLUDE memory_map.ld
REGION_ALIAS("REGION_TEXT", flash);
REGION_ALIAS("REGION_RODATA", flash);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("LOCATION_TEXT", flash);
REGION_ALIAS("LOCATION_RODATA", flash);
REGION_ALIAS("LOCATION_DATA", ram);
REGION_ALIAS("LOCATION_STACK", ram);
INCLUDE sections.ld

View File

@@ -1,12 +1,12 @@
OUTPUT_ARCH( "riscv" )
OUTPUT_ARCH(riscv)
ENTRY( _start )
ENTRY(_start)
INCLUDE memory_map.ld
REGION_ALIAS("REGION_TEXT", ram);
REGION_ALIAS("REGION_RODATA", ram);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("LOCATION_TEXT", ram);
REGION_ALIAS("LOCATION_RODATA", ram);
REGION_ALIAS("LOCATION_DATA", ram);
REGION_ALIAS("LOCATION_STACK", ram);
INCLUDE sections.ld

12
src/ram_dram.lds Normal file
View File

@@ -0,0 +1,12 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
INCLUDE memory_map.ld
REGION_ALIAS("LOCATION_TEXT", ram);
REGION_ALIAS("LOCATION_RODATA", ram);
REGION_ALIAS("LOCATION_DATA", dram);
REGION_ALIAS("LOCATION_STACK", dram);
INCLUDE sections.ld

View File

@@ -4,9 +4,9 @@ ENTRY( _start )
INCLUDE memory_map.ld
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_RODATA", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("LOCATION_TEXT", rom);
REGION_ALIAS("LOCATION_RODATA", rom);
REGION_ALIAS("LOCATION_DATA", ram);
REGION_ALIAS("LOCATION_STACK", ram);
INCLUDE sections.ld

View File

@@ -1,184 +1,108 @@
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
tls PT_TLS;
ram PT_NULL;
dram PT_NULL;
text PT_LOAD;
data PT_LOAD;
tls PT_TLS;
stack PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
__stack_segment_size = DEFINED(__stack_segment_size) ? __stack_segment_size : __stack_size;
.init ORIGIN(REGION_TEXT) :
/* Code/Const in LOCATION_TEXT */
. = ORIGIN(LOCATION_TEXT);
.text : ALIGN(4)
{
KEEP (*(.text.init.enter))
KEEP (*(.text.init.*))
KEEP (*(.text.init))
KEEP (*(SORT_NONE(.init)))
KEEP (*(.text.libgloss.start))
} >REGION_TEXT AT>REGION_TEXT :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
KEEP(*(.text.boot))
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >REGION_TEXT AT>REGION_TEXT :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >REGION_TEXT AT>REGION_TEXT :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >REGION_RODATA AT>REGION_RODATA :flash
.srodata :
{
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >REGION_RODATA AT>REGION_RODATA :flash
. = ALIGN(4);
.preinit_array :
KEEP(*(.init))
KEEP(*(.fini))
} > LOCATION_TEXT :text
/* trap/interrupt vectors */
.vectors : ALIGN(256)
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >REGION_RODATA AT>REGION_RODATA :flash
.init_array :
KEEP(*(.vectors .vectors.*))
} > LOCATION_TEXT
/* C++ ctors/dtors */
.init_array : ALIGN(4)
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >REGION_RODATA AT>REGION_RODATA :flash
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN(__init_array_end = .);
} > LOCATION_TEXT :text
.fini_array :
.fini_array : ALIGN(4)
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >REGION_RODATA AT>REGION_RODATA :flash
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN(__fini_array_end = .);
} > LOCATION_TEXT :text
.ctors :
/* .data in LOCATION_DATA, Load-Image in LOCATION_TEXT, PHDR is data */
.data : ALIGN(4)
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >REGION_RODATA AT>REGION_RODATA :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >REGION_RODATA AT>REGION_RODATA :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >REGION_RODATA AT>REGION_RODATA :flash
.data : ALIGN(4)
{
__DATA_BEGIN__ = .;
__data_start = .;
*(.data .data.*)
*(.gnu.linkonce.d.*)
__SDATA_BEGIN__ = .;
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
} >REGION_DATA AT>REGION_RODATA :ram_init
__data_end = .;
} > LOCATION_DATA AT> LOCATION_TEXT :data
__data_source = LOADADDR(.data);
.tdata : ALIGN(8) {
PROVIDE( __tls_base = . );
*(.tdata .tdata.* .gnu.linkonce.td.*)
} >REGION_DATA AT>REGION_RODATA :tls :ram_init
PROVIDE( __data_source = LOADADDR(.data) );
PROVIDE( __data_start = ADDR(.data) );
PROVIDE( __data_end = ADDR(.tdata) + SIZEOF(.tdata) );
PROVIDE( __tdata_source = LOADADDR(.tdata) );
PROVIDE( __tdata_size = SIZEOF(.tdata) );
.tbss : ALIGN(8) {
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon .tcommon.*)
PROVIDE( __tls_end = . );
} >REGION_DATA AT>REGION_DATA :tls :ram
PROVIDE( __tbss_size = SIZEOF(.tbss) );
PROVIDE( __tls_size = __tls_end - __tls_base );
.tbss_space : ALIGN(8) {
. = . + __tbss_size;
} >REGION_DATA :ram
.bss :
/* TLS: in LOCATION_DATA, initial values are in LOCATION_TEXT, PHDR is tls */
.tls : ALIGN(16)
{
__BSS_BEGIN__ = .;
*(.sbss*)
*(.gnu.linkonce.sb.*)
/* TLS init data (.tdata) */
__tls_base = .;
*(.tdata .tdata.* .gnu.linkonce.td.*)
__tdata_end = .;
__tdata_size = __tdata_end - __tls_base;
/* TLS bss (.tbss) */
__tbss_start = .;
*(.tbss .tbss.* .gnu.linkonce.tb.*)
__tbss_end = .;
__tbss_size = __tbss_end - __tbss_start;
__tls_size = __tbss_end - __tls_base;
} > LOCATION_DATA AT> LOCATION_TEXT :tls
__tdata_source = LOADADDR(.tls);
/* normales BSS (inkl. sbss), PHDR is data */
.bss (NOLOAD) : ALIGN(16)
{
__bss_start = .;
*(.sbss .sbss.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__BSS_END__ = .;
__bss_end = .;
} > LOCATION_DATA :data
} >REGION_BSS AT>REGION_BSS :ram
__global_pointer$ = .;
/* Heap/Stack Grenzen */
. = ALIGN(16);
__heap_start = .;
PROVIDE( __bss_start = ADDR(.tbss) );
PROVIDE( __bss_end = ADDR(.bss) + SIZEOF(.bss) );
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_segment_size :
/* __stack_top = ORIGIN(LOCATION_BSS) + LENGTH(LOCATION_BSS); */
/* PROVIDE(_sp = __stack_top); */
/* stack segement, PHDR is stack */
.stack ORIGIN(LOCATION_STACK) + LENGTH(LOCATION_STACK) - __stack_segment_size :
{
PROVIDE( _heap_end = . );
. = __stack_segment_size;
PROVIDE( _sp = . );
} >REGION_BSS AT>REGION_BSS :ram
} >LOCATION_STACK AT>LOCATION_STACK :stack
PROVIDE( tohost = . );
PROVIDE( fromhost = . + 8 );
/DISCARD/ : { *(.eh_frame*) *(.comment) *(.note .note.*) }
}