include: Create linker for RX architecture

Add intial support for RX linker script
The RX GCC toolchain automatically adding an "_" as prefix
on every C symbol to comply to the arch ABI, for the C file
to understand the symbol define in linker script the
PLACE_SYMBOL_HERE() macro help to add "_" to linker script
define symbol if build with CONFIG_RX enable
This commit adding minimal support in common linker script
for RX arch

Signed-off-by: Duy Nguyen <duy.nguyen.xa@renesas.com>
This commit is contained in:
Duy Nguyen 2025-03-31 14:13:37 +07:00 committed by Benjamin Cabé
parent 702bed6af5
commit f00608ef56
12 changed files with 277 additions and 50 deletions

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2021 KT-Elektronik, Klaucke und Partner GmbH
* Copyright (c) 2024 Renesas Electronics Corporation
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Linker command/script file
*
* Generic Linker script for the riscv platform
*/
#include <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/devicetree_regions.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#ifdef CONFIG_XIP
#define ROMABLE_REGION ROM
#else
#define ROMABLE_REGION RAM
#endif
#define RAMABLE_REGION RAM
/* single bank configuration with 2 MB of code flash */
#define ROM_START (DT_REG_ADDR(DT_NODELABEL(code_flash)))
#define ROM_SIZE (DT_REG_SIZE(DT_NODELABEL(code_flash)))
#define RAM_START (CONFIG_SRAM_BASE_ADDRESS)
#define RAM_SIZE (KB(CONFIG_SRAM_SIZE))
_region_min_align = 4;
MEMORY
{
ROM (rx) : ORIGIN = ROM_START, LENGTH = ROM_SIZE
RAM (rwx): ORIGIN = RAM_START, LENGTH = RAM_SIZE
LINKER_DT_REGIONS()
/* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = 0xFFFFF780, LENGTH = 2K
}
ENTRY(CONFIG_KERNEL_ENTRY)
SECTIONS
{
#include <zephyr/linker/rel-sections.ld>
GROUP_START(ROMABLE_REGION)
. = ROM_START; /* for kernel logging */
PLACE_SYMBOL_HERE(__rodata_region_start);
.fvectors 0xFFFFFF80: AT(0xFFFFFF80)
{
KEEP(*(.fvectors))
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(_TEXT_SECTION_NAME,ROM_START,)
{
_image_text_start = .;
*(.text)
*(.text.*)
*(P)
etext = .;
} GROUP_LINK_IN(ROMABLE_REGION)
_image_text_end = .;
#include <zephyr/linker/common-rom.ld>
SECTION_PROLOGUE(.rvectors,,)
{
_rvectors_start = .;
KEEP(*(.rvectors))
_rvectors_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(init,,)
{
KEEP(*(.init))
__preinit_array_start = .;
KEEP(*(.preinit_array))
__preinit_array_end = .;
__init_array_start = (. + 3) & ~ 3;
KEEP(*(.init_array))
KEEP(*(SORT(.init_array.*)))
__init_array_end = .;
__fini_array_start = .;
KEEP(*(.fini_array))
KEEP(*(SORT(.fini_array.*)))
__fini_array_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(fini,,)
{
KEEP(*(.fini))
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(got,,)
{
*(.got)
*(.got.plt)
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
{
*(.rodata)
*(.rodata.*)
*(C_1)
*(C_2)
*(C)
_erodata = .;
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(eh_frame_hdr,,)
{
*(.eh_frame_hdr)
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(eh_frame,,)
{
*(.eh_frame)
} GROUP_LINK_IN(ROMABLE_REGION)
SECTION_PROLOGUE(jcr,,)
{
*(.jcr)
} GROUP_LINK_IN(ROMABLE_REGION)
/* TODO: is this section necessary? There is a similar section
* (_CTOR_SECTION_NAME) in common-rom.ld. This seems to be for
* C++ Constructors/Destructors? */
SECTION_PROLOGUE(tors,,)
{
__CTOR_LIST__ = .;
. = ALIGN(2);
__ctors = .;
*(.ctors)
__ctors_end = .;
__CTOR_END__ = .;
__DTOR_LIST__ = .;
__dtors = .;
*(.dtors)
__dtors_end = .;
__DTOR_END__ = .;
. = ALIGN(2);
} GROUP_LINK_IN(ROMABLE_REGION)
PLACE_SYMBOL_HERE(__rodata_region_end);
_mdata = .;
GROUP_END(ROMABLE_REGION)
GROUP_START(RAMABLE_REGION)
_image_ram_start = .;
#if CONFIG_SRAM_BASE_ADDRESS == 0
/* RX memory starts at address 0 which can be confused with NULL. To prevent this, block
* the first memory page (16 Bytes).
*/
SECTION_DATA_PROLOGUE(.null_blocker,,)
{
. = 0x10;
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
#endif
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
{
_data = .;
*(.data)
*(.data.*)
*(D)
*(D_1)
*(D_2)
*(.gnu.linkonce.*)
#include <snippets-rwdata.ld>
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/* the sections defined in common-ram.ld have to be initialized on
* reset as well, to place them before _edata */
#include <zephyr/linker/common-ram.ld>
_edata = .;
SECTION_PROLOGUE(_BSS_SECTION_NAME,,)
{
_bss = .;
*(.bss)
*(.bss.**)
*(COMMON)
*(B)
*(B_1)
*(B_2)
} GROUP_LINK_IN(RAMABLE_REGION)
_ebss = . ;
#include <zephyr/linker/common-noinit.ld>
_image_ram_end = .;
_end = .;
PROVIDE(__end = _end);
GROUP_END(RAMABLE_REGION)
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() CMake function.
*/
#include <snippets-sections.ld>
#include <zephyr/linker/debug-sections.ld>
}

View File

@ -42,10 +42,10 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)
SECTION_DATA_PROLOGUE(device_states,,)
{
/* Device states used by the device objects. */
__device_states_start = .;
PLACE_SYMBOL_HERE(__device_states_start);
KEEP(*(".z_devstate"));
KEEP(*(".z_devstate.*"));
__device_states_end = .;
PLACE_SYMBOL_HERE(__device_states_end);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#ifdef CONFIG_PM_DEVICE
@ -71,7 +71,7 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)
* These two symbols only used by gen_kobject_list.py
*/
_static_kernel_objects_begin = .;
PLACE_SYMBOL_HERE(_static_kernel_objects_begin);
#endif /* CONFIG_USERSPACE */
ITERABLE_SECTION_RAM_GC_ALLOWED(k_timer, Z_LINK_ITERABLE_SUBALIGN)
@ -103,10 +103,10 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)
#if defined(CONFIG_USB_DEVICE_STACK)
SECTION_DATA_PROLOGUE(usb_descriptor,,SUBALIGN(1))
{
__usb_descriptor_start = .;
PLACE_SYMBOL_HERE(__usb_descriptor_start);
*(".usb.descriptor")
KEEP(*(SORT_BY_NAME(".usb.descriptor*")))
__usb_descriptor_end = .;
PLACE_SYMBOL_HERE(__usb_descriptor_end);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
ITERABLE_SECTION_RAM(usb_cfg_data, Z_LINK_ITERABLE_SUBALIGN)
@ -115,10 +115,10 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)
#if defined(CONFIG_USB_DEVICE_BOS)
SECTION_DATA_PROLOGUE(usb_bos_desc,,SUBALIGN(1))
{
__usb_bos_desc_start = .;
PLACE_SYMBOL_HERE(__usb_bos_desc_start);
*(".usb.bos_desc")
KEEP(*(SORT_BY_NAME(".usb.bos_desc*")))
__usb_bos_desc_end = .;
PLACE_SYMBOL_HERE(__usb_bos_desc_end);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif /* CONFIG_USB_DEVICE_BOS */
@ -146,5 +146,5 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)
#endif
#ifdef CONFIG_USERSPACE
_static_kernel_objects_end = .;
PLACE_SYMBOL_HERE(_static_kernel_objects_end);
#endif

View File

@ -13,17 +13,17 @@
/* Use the native LIBC constructor code so that any native
* constructors get run before main is invoked
*/
__init_array_start = .;
PLACE_SYMBOL_HERE(__init_array_start);
#else
__zephyr_init_array_start = .;
PLACE_SYMBOL_HERE(__zephyr_init_array_start);
#endif
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*)
SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array .ctors))
#ifdef CONFIG_NATIVE_APPLICATION
__init_array_end = .;
PLACE_SYMBOL_HERE(__init_array_end);
#else
__zephyr_init_array_end = .;
PLACE_SYMBOL_HERE(__zephyr_init_array_end);
#endif
#ifdef CONFIG_NATIVE_LIBC
@ -35,7 +35,7 @@
* In this way, in native_simulator based targets, the host glibc process
* initialization code will not call the constructors before Zephyr loads.
*/
__CTOR_LIST__ = .;
PLACE_SYMBOL_HERE(__CTOR_LIST__);
#ifdef CONFIG_64BIT
QUAD(0)
QUAD(0)
@ -43,7 +43,7 @@
LONG(0)
LONG(0)
#endif
__CTOR_END__ = .;
PLACE_SYMBOL_HERE(__CTOR_END__);
#ifndef CONFIG_NATIVE_APPLICATION
/*
* Similar to the schenanigans required for the __CTOR_LIST__ and
@ -51,8 +51,8 @@
* to the same address to define an empty list. This prevents the glibc
* startup code from calling any global constructors before Zephyr loads.
*/
__init_array_start = .;
__init_array_end = .;
PLACE_SYMBOL_HERE(__init_array_start);
PLACE_SYMBOL_HERE(__init_array_end);
#endif
#endif
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

View File

@ -10,14 +10,14 @@
* sorted in the order they will be initialized (i.e. ordered
* by level, sorted by priority within a level)
*/
__init_start = .;
PLACE_SYMBOL_HERE(__init_start);
CREATE_OBJ_LEVEL(init, EARLY)
CREATE_OBJ_LEVEL(init, PRE_KERNEL_1)
CREATE_OBJ_LEVEL(init, PRE_KERNEL_2)
CREATE_OBJ_LEVEL(init, POST_KERNEL)
CREATE_OBJ_LEVEL(init, APPLICATION)
CREATE_OBJ_LEVEL(init, SMP)
__init_end = .;
PLACE_SYMBOL_HERE(__init_end);
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
ITERABLE_SECTION_ROM_NUMERIC(device, Z_LINK_ITERABLE_SUBALIGN)
@ -80,9 +80,9 @@
SECTION_DATA_PROLOGUE(app_shmem_regions,,)
{
__app_shmem_regions_start = .;
PLACE_SYMBOL_HERE(__app_shmem_regions_start);
KEEP(*(SORT(.app_regions.*)));
__app_shmem_regions_end = .;
PLACE_SYMBOL_HERE(__app_shmem_regions_end);
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
ITERABLE_SECTION_ROM(k_p4wq_initparam, Z_LINK_ITERABLE_SUBALIGN)

View File

@ -46,9 +46,9 @@
SECTION_DATA_PROLOGUE(symbol_to_keep,,)
{
__symbol_to_keep_start = .;
PLACE_SYMBOL_HERE(__symbol_to_keep_start);
KEEP(*(SORT(.symbol_to_keep*)));
__symbol_to_keep_end = .;
PLACE_SYMBOL_HERE(__symbol_to_keep_end);
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
ITERABLE_SECTION_ROM(shell, Z_LINK_ITERABLE_SUBALIGN)

View File

@ -14,27 +14,28 @@
/* clang-format off */
#define Z_LINK_ITERABLE(struct_type) \
_CONCAT(_##struct_type, _list_start) = .; \
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_start)); \
KEEP(*(SORT_BY_NAME(._##struct_type.static.*))); \
_CONCAT(_##struct_type, _list_end) = .
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_end));
#define Z_LINK_ITERABLE_NUMERIC(struct_type) \
_CONCAT(_##struct_type, _list_start) = .; \
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_start)); \
KEEP(*(SORT(._##struct_type.static.*_?_*))); \
KEEP(*(SORT(._##struct_type.static.*_??_*))); \
KEEP(*(SORT(._##struct_type.static.*_???_*))); \
KEEP(*(SORT(._##struct_type.static.*_????_*))); \
KEEP(*(SORT(._##struct_type.static.*_?????_*))); \
_CONCAT(_##struct_type, _list_end) = .
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_end));
#define Z_LINK_ITERABLE_ALIGNED(struct_type, align) \
. = ALIGN(align); \
Z_LINK_ITERABLE(struct_type);
#define Z_LINK_ITERABLE_GC_ALLOWED(struct_type) \
_CONCAT(_##struct_type, _list_start) = .; \
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_start)); \
*(SORT_BY_NAME(._##struct_type.static.*)); \
_CONCAT(_##struct_type, _list_end) = .
PLACE_SYMBOL_HERE(_CONCAT(_##struct_type, _list_end));
/* clang-format on */
#define Z_LINK_ITERABLE_SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN

View File

@ -8,7 +8,7 @@
#ifdef CONFIG_USERSPACE
z_kobject_data_begin = .;
PLACE_SYMBOL_HERE(z_kobject_data_begin);
SECTION_DATA_PROLOGUE(kobject_data,,)
{
@ -51,14 +51,14 @@
#ifdef KOBJECT_DATA_ALIGN
. = ALIGN(KOBJECT_DATA_ALIGN);
_kobject_data_area_start = .;
PLACE_SYMBOL_HERE(_kobject_data_area_start);
#endif
*(".kobject_data.data*")
*(".kobject_data.sdata*")
#ifdef KOBJECT_DATA_ALIGN
_kobject_data_area_end = .;
PLACE_SYMBOL_HERE(_kobject_data_area_end);
_kobject_data_area_used = _kobject_data_area_end - _kobject_data_area_start;
ASSERT(_kobject_data_area_used <= KOBJECT_DATA_SZ,

View File

@ -9,7 +9,7 @@
#ifdef CONFIG_GEN_PRIV_STACKS
SECTION_DATA_PROLOGUE(priv_stacks_noinit,(NOLOAD),)
{
z_priv_stacks_ram_start = .;
PLACE_SYMBOL_HERE(z_priv_stacks_ram_start);
/* During LINKER_KOBJECT_PREBUILT and LINKER_ZEPHYR_PREBUILT,
* space needs to be reserved for the rodata that will be
@ -36,7 +36,7 @@
*(".priv_stacks.noinit")
#endif /* LINKER_ZEPHYR_FINAL */
z_priv_stacks_ram_end = .;
PLACE_SYMBOL_HERE(z_priv_stacks_ram_end);
#if defined(LINKER_ZEPHYR_FINAL)
#ifdef KOBJECT_PRIV_STACKS_ALIGN

View File

@ -21,11 +21,11 @@
#ifdef KOBJECT_RODATA_ALIGN
. = ALIGN(KOBJECT_RODATA_ALIGN);
_kobject_rodata_area_start = .;
PLACE_SYMBOL_HERE(_kobject_rodata_area_start);
. = . + KOBJECT_RODATA_SZ;
_kobject_rodata_area_end = .;
PLACE_SYMBOL_HERE(_kobject_rodata_area_end);
#endif
#endif /* LINKER_ZEPHYR_PREBUILT */
@ -34,13 +34,13 @@
#ifdef KOBJECT_RODATA_ALIGN
. = ALIGN(KOBJECT_RODATA_ALIGN);
_kobject_rodata_area_start = .;
PLACE_SYMBOL_HERE(_kobject_rodata_area_start);
#endif
*(".kobject_data.rodata*")
#ifdef KOBJECT_RODATA_ALIGN
_kobject_rodata_area_end = .;
PLACE_SYMBOL_HERE(_kobject_rodata_area_end);
_kobject_rodata_area_used = _kobject_rodata_area_end - _kobject_rodata_area_start;
ASSERT(_kobject_rodata_area_used <= KOBJECT_RODATA_SZ,

View File

@ -9,10 +9,10 @@
* The linker will error out complaining that the location pointer
* is moving backwards if the reserved room isn't large enough.
*/
_kobject_text_area_start = .;
PLACE_SYMBOL_HERE(_kobject_text_area_start);
*(".kobject_data.literal*")
*(".kobject_data.text*")
_kobject_text_area_end = .;
PLACE_SYMBOL_HERE(_kobject_text_area_end);
_kobject_text_area_used = _kobject_text_area_end - _kobject_text_area_start;
#ifndef LINKER_ZEPHYR_FINAL
#ifdef CONFIG_DYNAMIC_OBJECTS

View File

@ -37,6 +37,18 @@
#include <zephyr/devicetree.h>
#endif
/* The GCC for Renesas RX processors adds leading underscores to C-symbols
* by default. As a workaroud for symbols defined in linker scripts to be
* available in C code, an alias with a leading underscore has to be provided.
*/
#if defined(CONFIG_RX)
#define PLACE_SYMBOL_HERE(symbol) \
symbol = .; \
PROVIDE(_CONCAT(_, symbol) = symbol)
#else
#define PLACE_SYMBOL_HERE(symbol) symbol = .
#endif
#ifdef _LINKER
/*
* generate a symbol to mark the start of the objects array for
@ -44,9 +56,10 @@
* (sorted by priority). Ensure the objects aren't discarded if there is
* no direct reference to them
*/
/* clang-format off */
#define CREATE_OBJ_LEVEL(object, level) \
__##object##_##level##_start = .; \
PLACE_SYMBOL_HERE(__##object##_##level##_start);\
KEEP(*(SORT(.z_##object##_##level##_P_?_*))); \
KEEP(*(SORT(.z_##object##_##level##_P_??_*))); \
KEEP(*(SORT(.z_##object##_##level##_P_???_*)));

View File

@ -33,24 +33,23 @@ static inline bool linker_is_in_rodata(const void *addr)
}
#endif
#if defined(CONFIG_ARM) || defined(CONFIG_ARC) || defined(CONFIG_X86) || \
defined(CONFIG_ARM64) || defined(CONFIG_NIOS2) || \
defined(CONFIG_RISCV) || defined(CONFIG_SPARC) || \
defined(CONFIG_MIPS) || defined(CONFIG_XTENSA)
#if defined(CONFIG_ARM) || defined(CONFIG_ARC) || defined(CONFIG_X86) || defined(CONFIG_ARM64) || \
defined(CONFIG_NIOS2) || defined(CONFIG_RISCV) || defined(CONFIG_SPARC) || \
defined(CONFIG_MIPS) || defined(CONFIG_XTENSA) || defined(CONFIG_RX)
extern char __rodata_region_start[];
extern char __rodata_region_end[];
#define RO_START __rodata_region_start
#define RO_END __rodata_region_end
#define RO_START __rodata_region_start
#define RO_END __rodata_region_end
#else
#define RO_START 0
#define RO_END 0
#define RO_START 0
#define RO_END 0
#endif
return (((const char *)addr >= (const char *)RO_START) &&
((const char *)addr < (const char *)RO_END));
#undef RO_START
#undef RO_END
#undef RO_START
#undef RO_END
}
#endif /* ZEPHYR_INCLUDE_LINKER_UTILS_H_ */