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:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <picotls.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define EXTERN_C extern "C"
|
#define EXTERN_C extern "C"
|
||||||
@@ -24,6 +25,12 @@ EXTERN_C uint8_t __bss_end;
|
|||||||
EXTERN_C const uint8_t __data_source;
|
EXTERN_C const uint8_t __data_source;
|
||||||
EXTERN_C uint8_t __data_start;
|
EXTERN_C uint8_t __data_start;
|
||||||
EXTERN_C uint8_t __data_end;
|
EXTERN_C uint8_t __data_end;
|
||||||
|
EXTERN_C const uint8_t __data_source;
|
||||||
|
EXTERN_C uint8_t __tbss_start;
|
||||||
|
EXTERN_C uintptr_t __tbss_size;
|
||||||
|
EXTERN_C const uint8_t __tdata_source;
|
||||||
|
EXTERN_C uint8_t __tls_base;
|
||||||
|
EXTERN_C uintptr_t __tdata_size;
|
||||||
|
|
||||||
EXTERN_C function_t __init_array_start;
|
EXTERN_C function_t __init_array_start;
|
||||||
EXTERN_C function_t __init_array_end;
|
EXTERN_C function_t __init_array_end;
|
||||||
@@ -32,10 +39,10 @@ EXTERN_C function_t __fini_array_end;
|
|||||||
|
|
||||||
// This function will be placed by the linker script according to the section
|
// This function will be placed by the linker script according to the section
|
||||||
// Raw function 'called' by the CPU with no runtime.
|
// Raw function 'called' by the CPU with no runtime.
|
||||||
EXTERN_C void _start(void) __attribute__ ((naked,section(".text.init")));
|
EXTERN_C void _start(void) __attribute__ ((naked,section(".text.boot")));
|
||||||
|
|
||||||
// Entry and exit points as C functions.
|
// Entry and exit points as C functions.
|
||||||
EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".init")));
|
EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".text.boot")));
|
||||||
EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak));
|
EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak));
|
||||||
|
|
||||||
// Standard entry point, no arguments.
|
// Standard entry point, no arguments.
|
||||||
@@ -68,19 +75,22 @@ void _start(void) {
|
|||||||
void _initialize(void) {
|
void _initialize(void) {
|
||||||
// Init memory regions
|
// Init memory regions
|
||||||
// Clear the .bss section (global variables with no initial values)
|
// Clear the .bss section (global variables with no initial values)
|
||||||
memset((void*) &__bss_start,
|
memset((void*) &__bss_start, 0, (&__bss_end - &__bss_start));
|
||||||
0,
|
|
||||||
(&__bss_end - &__bss_start));
|
|
||||||
// Initialize the .data section (global variables with initial values)
|
// Initialize the .data section (global variables with initial values)
|
||||||
memcpy((void*)&__data_start,
|
memcpy((void*)&__data_start, (const void*)&__data_source, (&__data_end - &__data_start));
|
||||||
(const void*)&__data_source,
|
// Clear the .tbss section (thread local variables with no initial values)
|
||||||
(&__data_end - &__data_end));
|
memset((void*) &__tbss_start, 0, __tbss_size);
|
||||||
|
// Initialize the .tls section (thread local variables with initial values)
|
||||||
|
memcpy((void*) &__tls_base, (const void*)&__tdata_source, __tdata_size);
|
||||||
// Call constructors
|
// Call constructors
|
||||||
for (const function_t* entry=&__init_array_start;
|
for (const function_t* entry=&__init_array_start;
|
||||||
entry < &__init_array_end;
|
entry < &__init_array_end;
|
||||||
++entry) {
|
++entry) {
|
||||||
(*entry)();
|
(*entry)();
|
||||||
}
|
}
|
||||||
|
#ifdef __THREAD_LOCAL_STORAGE
|
||||||
|
_set_tls(__tls_base)
|
||||||
|
#endif
|
||||||
int rc = main();
|
int rc = main();
|
||||||
// Call destructors
|
// Call destructors
|
||||||
for (const function_t* entry=&__fini_array_start;
|
for (const function_t* entry=&__fini_array_start;
|
||||||
|
|||||||
@@ -135,12 +135,12 @@ trap_handler:
|
|||||||
*/
|
*/
|
||||||
.global _tx_initialize_low_level
|
.global _tx_initialize_low_level
|
||||||
.weak _tx_initialize_low_level
|
.weak _tx_initialize_low_level
|
||||||
.extern _end
|
.extern __heap_start
|
||||||
.extern board_init
|
.extern board_init
|
||||||
_tx_initialize_low_level:
|
_tx_initialize_low_level:
|
||||||
STORE sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
STORE sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
||||||
|
|
||||||
la t0, _end // Pickup first free address
|
la t0, __heap_start // Pickup first free address
|
||||||
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||||
li t0, MSTATUS_MIE
|
li t0, MSTATUS_MIE
|
||||||
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ ENTRY( _start )
|
|||||||
|
|
||||||
INCLUDE memory_map.ld
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
REGION_ALIAS("REGION_TEXT", flash);
|
REGION_ALIAS("LOCATION_TEXT", flash);
|
||||||
REGION_ALIAS("REGION_RODATA", flash);
|
REGION_ALIAS("LOCATION_RODATA", flash);
|
||||||
REGION_ALIAS("REGION_DATA", ram);
|
REGION_ALIAS("LOCATION_DATA", ram);
|
||||||
REGION_ALIAS("REGION_BSS", ram);
|
REGION_ALIAS("LOCATION_STACK", ram);
|
||||||
|
|
||||||
INCLUDE sections.ld
|
INCLUDE sections.ld
|
||||||
12
src/ram.lds
12
src/ram.lds
@@ -1,12 +1,12 @@
|
|||||||
OUTPUT_ARCH( "riscv" )
|
OUTPUT_ARCH(riscv)
|
||||||
|
|
||||||
ENTRY( _start )
|
ENTRY(_start)
|
||||||
|
|
||||||
INCLUDE memory_map.ld
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
REGION_ALIAS("REGION_TEXT", ram);
|
REGION_ALIAS("LOCATION_TEXT", ram);
|
||||||
REGION_ALIAS("REGION_RODATA", ram);
|
REGION_ALIAS("LOCATION_RODATA", ram);
|
||||||
REGION_ALIAS("REGION_DATA", ram);
|
REGION_ALIAS("LOCATION_DATA", ram);
|
||||||
REGION_ALIAS("REGION_BSS", ram);
|
REGION_ALIAS("LOCATION_STACK", ram);
|
||||||
|
|
||||||
INCLUDE sections.ld
|
INCLUDE sections.ld
|
||||||
12
src/ram_dram.lds
Normal file
12
src/ram_dram.lds
Normal 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
|
||||||
@@ -4,9 +4,9 @@ ENTRY( _start )
|
|||||||
|
|
||||||
INCLUDE memory_map.ld
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
REGION_ALIAS("REGION_TEXT", rom);
|
REGION_ALIAS("LOCATION_TEXT", rom);
|
||||||
REGION_ALIAS("REGION_RODATA", rom);
|
REGION_ALIAS("LOCATION_RODATA", rom);
|
||||||
REGION_ALIAS("REGION_DATA", ram);
|
REGION_ALIAS("LOCATION_DATA", ram);
|
||||||
REGION_ALIAS("REGION_BSS", ram);
|
REGION_ALIAS("LOCATION_STACK", ram);
|
||||||
|
|
||||||
INCLUDE sections.ld
|
INCLUDE sections.ld
|
||||||
218
src/sections.ld
218
src/sections.ld
@@ -1,184 +1,108 @@
|
|||||||
PHDRS
|
PHDRS
|
||||||
{
|
{
|
||||||
flash PT_LOAD;
|
text PT_LOAD;
|
||||||
ram_init PT_LOAD;
|
data PT_LOAD;
|
||||||
tls PT_TLS;
|
tls PT_TLS;
|
||||||
ram PT_NULL;
|
stack PT_NULL;
|
||||||
dram PT_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||||
__stack_segment_size = DEFINED(__stack_segment_size) ? __stack_segment_size : __stack_size;
|
__stack_segment_size = DEFINED(__stack_segment_size) ? __stack_segment_size : __stack_size;
|
||||||
.init ORIGIN(REGION_TEXT) :
|
|
||||||
{
|
|
||||||
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 :
|
/* Code/Const in LOCATION_TEXT */
|
||||||
|
. = ORIGIN(LOCATION_TEXT);
|
||||||
|
.text : ALIGN(4)
|
||||||
{
|
{
|
||||||
*(.text.unlikely .text.unlikely.*)
|
KEEP(*(.text.boot))
|
||||||
*(.text.startup .text.startup.*)
|
|
||||||
*(.text .text.*)
|
*(.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.*)
|
*(.rodata .rodata.*)
|
||||||
*(.gnu.linkonce.r.*)
|
|
||||||
} >REGION_RODATA AT>REGION_RODATA :flash
|
|
||||||
|
|
||||||
.srodata :
|
|
||||||
{
|
|
||||||
*(.srodata.cst16)
|
|
||||||
*(.srodata.cst8)
|
|
||||||
*(.srodata.cst4)
|
|
||||||
*(.srodata.cst2)
|
|
||||||
*(.srodata .srodata.*)
|
*(.srodata .srodata.*)
|
||||||
} >REGION_RODATA AT>REGION_RODATA :flash
|
KEEP(*(.init))
|
||||||
|
KEEP(*(.fini))
|
||||||
|
} > LOCATION_TEXT :text
|
||||||
|
|
||||||
. = ALIGN(4);
|
/* trap/interrupt vectors */
|
||||||
|
.vectors : ALIGN(256)
|
||||||
.preinit_array :
|
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
KEEP(*(.vectors .vectors.*))
|
||||||
KEEP (*(.preinit_array))
|
} > LOCATION_TEXT
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
|
||||||
} >REGION_RODATA AT>REGION_RODATA :flash
|
|
||||||
|
|
||||||
.init_array :
|
/* C++ ctors/dtors */
|
||||||
|
.init_array : ALIGN(4)
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
PROVIDE_HIDDEN(__init_array_start = .);
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
|
||||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
KEEP(*(.init_array))
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
PROVIDE_HIDDEN(__init_array_end = .);
|
||||||
} >REGION_RODATA AT>REGION_RODATA :flash
|
} > LOCATION_TEXT :text
|
||||||
|
|
||||||
.fini_array :
|
.fini_array : ALIGN(4)
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
|
||||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
KEEP(*(.fini_array))
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||||
} >REGION_RODATA AT>REGION_RODATA :flash
|
} > 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
|
__data_start = .;
|
||||||
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 .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
__data_end = .;
|
||||||
__SDATA_BEGIN__ = .;
|
} > LOCATION_DATA AT> LOCATION_TEXT :data
|
||||||
*(.sdata .sdata.*)
|
__data_source = LOADADDR(.data);
|
||||||
*(.gnu.linkonce.s.*)
|
|
||||||
} >REGION_DATA AT>REGION_RODATA :ram_init
|
|
||||||
|
|
||||||
.tdata : ALIGN(8) {
|
/* TLS: in LOCATION_DATA, initial values are in LOCATION_TEXT, PHDR is tls */
|
||||||
PROVIDE( __tls_base = . );
|
.tls : ALIGN(16)
|
||||||
*(.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 :
|
|
||||||
{
|
{
|
||||||
__BSS_BEGIN__ = .;
|
/* TLS init data (.tdata) */
|
||||||
*(.sbss*)
|
__tls_base = .;
|
||||||
*(.gnu.linkonce.sb.*)
|
*(.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.*)
|
*(.bss .bss.*)
|
||||||
*(.gnu.linkonce.b.*)
|
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
. = ALIGN(4);
|
__bss_end = .;
|
||||||
__BSS_END__ = .;
|
} > LOCATION_DATA :data
|
||||||
|
|
||||||
} >REGION_BSS AT>REGION_BSS :ram
|
__global_pointer$ = .;
|
||||||
|
|
||||||
PROVIDE( __bss_start = ADDR(.tbss) );
|
/* Heap/Stack Grenzen */
|
||||||
PROVIDE( __bss_end = ADDR(.bss) + SIZEOF(.bss) );
|
. = ALIGN(16);
|
||||||
|
__heap_start = .;
|
||||||
|
|
||||||
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
|
/* __stack_top = ORIGIN(LOCATION_BSS) + LENGTH(LOCATION_BSS); */
|
||||||
PROVIDE( _end = . );
|
/* PROVIDE(_sp = __stack_top); */
|
||||||
PROVIDE( end = . );
|
/* stack segement, PHDR is stack */
|
||||||
|
.stack ORIGIN(LOCATION_STACK) + LENGTH(LOCATION_STACK) - __stack_segment_size :
|
||||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_segment_size :
|
|
||||||
{
|
{
|
||||||
PROVIDE( _heap_end = . );
|
PROVIDE( _heap_end = . );
|
||||||
. = __stack_segment_size;
|
. = __stack_segment_size;
|
||||||
PROVIDE( _sp = . );
|
PROVIDE( _sp = . );
|
||||||
} >REGION_BSS AT>REGION_BSS :ram
|
} >LOCATION_STACK AT>LOCATION_STACK :stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PROVIDE( tohost = . );
|
PROVIDE( tohost = . );
|
||||||
PROVIDE( fromhost = . + 8 );
|
PROVIDE( fromhost = . + 8 );
|
||||||
|
|
||||||
|
/DISCARD/ : { *(.eh_frame*) *(.comment) *(.note .note.*) }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user