From f2a1572ac2f1845e819fe1756565c10f76d63579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20R=C3=B8nningstad?= Date: Wed, 6 Mar 2019 17:28:05 +0100 Subject: [PATCH] cmake: Add function for adding snippets to the linker file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows snippets to be placed in different locations: - The noinit, rwdata and rodata output sections - Two different locations for placing custom output sections, one location for RAM and another for all other sections. Signed-off-by: Øyvind Rønningstad --- cmake/app/boilerplate.cmake | 3 + cmake/extensions.cmake | 101 ++++++++++++++++++++ include/arch/arc/v2/linker.ld | 21 ++++ include/arch/arm/cortex_m/scripts/linker.ld | 22 +++++ include/arch/nios2/linker.ld | 21 ++++ include/arch/riscv32/common/linker.ld | 21 ++++ include/arch/x86/linker.ld | 21 ++++ soc/riscv32/openisa_rv32m1/linker.ld | 27 ++++++ 8 files changed, 237 insertions(+) diff --git a/cmake/app/boilerplate.cmake b/cmake/app/boilerplate.cmake index f95fa48fb1e..2e44b39a8fb 100644 --- a/cmake/app/boilerplate.cmake +++ b/cmake/app/boilerplate.cmake @@ -118,6 +118,9 @@ add_custom_target( # Equivalent to rm -rf build/* ) +# Dummy add to generate files. +zephyr_linker_sources(SECTIONS) + # The BOARD can be set by 3 sources. Through environment variables, # through the cmake CLI, and through CMakeLists.txt. # diff --git a/cmake/extensions.cmake b/cmake/extensions.cmake index 3f089e27d74..bd7e9802557 100644 --- a/cmake/extensions.cmake +++ b/cmake/extensions.cmake @@ -745,6 +745,101 @@ function(zephyr_check_compiler_flag lang option check) endif() endfunction() +# zephyr_linker_sources( ) +# +# is one or more .ld formatted files whose contents will be +# copied/included verbatim into the given in the global linker.ld. +# Preprocessor directives work inside . Relative paths are resolved +# relative to the calling file, like zephyr_sources(). +# is one of +# NOINIT Inside the noinit output section. +# RWDATA Inside the data output section. +# RODATA Inside the rodata output section. +# RAM_SECTIONS Inside the RAMABLE_REGION GROUP. +# SECTIONS Near the end of the file. Don't use this when linking into +# RAMABLE_REGION, use RAM_SECTIONS instead. +# +# Use NOINIT, RWDATA, and RODATA unless they don't work for your use case. +# +# When placing into NOINIT, RWDATA, or RODATA, the contents of the files will be +# placed inside an output section, so assume the section definition is already +# present, e.g.: +# _mysection_start = .; +# KEEP(*(.mysection)); +# _mysection_end = .; +# _mysection_size = ABSOLUTE(_mysection_end - _mysection_start); +# +# When placing into SECTIONS or RAM_SECTIONS, the files must instead define +# their own output sections to acheive the same thing: +# SECTION_PROLOGUE(.mysection,,) +# { +# _mysection_start = .; +# KEEP(*(.mysection)) +# _mysection_end = .; +# } GROUP_LINK_IN(ROMABLE_REGION) +# _mysection_size = _mysection_end - _mysection_start; +# +# Note about the above examples: If the first example was used with RODATA, and +# the second with SECTIONS, the two examples do the same thing from a user +# perspective. +# +# Friendly reminder: Beware of the different ways the location counter ('.') +# behaves inside vs. outside section definitions. +function(zephyr_linker_sources location) + # Set up the paths to the destination files. These files are #included inside + # the global linker.ld. + set(snippet_base "${__build_dir}/include/generated") + set(sections_path "${snippet_base}/snippets-sections.ld") + set(ram_sections_path "${snippet_base}/snippets-ram-sections.ld") + set(noinit_path "${snippet_base}/snippets-noinit.ld") + set(rwdata_path "${snippet_base}/snippets-rwdata.ld") + set(rodata_path "${snippet_base}/snippets-rodata.ld") + + # Clear destination files if this is the first time the function is called. + get_property(cleared GLOBAL PROPERTY snippet_files_cleared) + if (NOT DEFINED cleared) + file(WRITE ${sections_path} "") + file(WRITE ${ram_sections_path} "") + file(WRITE ${noinit_path} "") + file(WRITE ${rwdata_path} "") + file(WRITE ${rodata_path} "") + set_property(GLOBAL PROPERTY snippet_files_cleared true) + endif() + + # Choose destination file, based on the argument. + if ("${location}" STREQUAL "SECTIONS") + set(snippet_path "${sections_path}") + elseif("${location}" STREQUAL "RAM_SECTIONS") + set(snippet_path "${ram_sections_path}") + elseif("${location}" STREQUAL "NOINIT") + set(snippet_path "${noinit_path}") + elseif("${location}" STREQUAL "RWDATA") + set(snippet_path "${rwdata_path}") + elseif("${location}" STREQUAL "RODATA") + set(snippet_path "${rodata_path}") + else() + message(fatal_error "Must choose valid location for linker snippet.") + endif() + + foreach(file IN ITEMS ${ARGN}) + # Resolve path. + if(IS_ABSOLUTE ${file}) + set(path ${file}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${file}) + endif() + + if(IS_DIRECTORY ${path}) + message(FATAL_ERROR "zephyr_linker_sources() was called on a directory") + endif() + + # Append the file contents to the relevant destination file. + file(READ ${path} snippet) + file(APPEND ${snippet_path} "\n/* From ${path}: */\n" "${snippet}\n") + endforeach() +endfunction(zephyr_linker_sources) + + # Helper function for CONFIG_CODE_DATA_RELOCATION # Call this function with 2 arguments file and then memory location function(zephyr_code_relocate file location) @@ -1018,6 +1113,12 @@ function(zephyr_library_link_libraries_ifdef feature_toggle item) endif() endfunction() +function(zephyr_linker_sources_ifdef feature_toggle) + if(${${feature_toggle}}) + zephyr_linker_sources(${ARGN}) + endif() +endfunction() + macro(list_append_ifdef feature_toggle list) if(${${feature_toggle}}) list(APPEND ${list} ${ARGN}) diff --git a/include/arch/arc/v2/linker.ld b/include/arch/arc/v2/linker.ld index 8d971ef48c0..fc2d6c0037e 100644 --- a/include/arch/arc/v2/linker.ld +++ b/include/arch/arc/v2/linker.ld @@ -115,6 +115,10 @@ SECTIONS { *(".rodata.*") *(.gnu.linkonce.r.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RODATA_LD #include #endif @@ -139,6 +143,11 @@ SECTIONS { #include +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + #if defined(CONFIG_USERSPACE) #define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN #define SMEM_PARTITION_ALIGN MPU_ALIGN @@ -181,6 +190,10 @@ SECTIONS { *(".noinit.*") *(".kernel_noinit.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_NOINIT_LD #include #endif @@ -195,6 +208,10 @@ SECTIONS { *(".data.*") *(".kernel.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RWDATA_LD #include #endif @@ -228,6 +245,10 @@ SECTIONS { /* Located in project source directory */ #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_GEN_ISR_TABLES #include diff --git a/include/arch/arm/cortex_m/scripts/linker.ld b/include/arch/arm/cortex_m/scripts/linker.ld index 7656c5f34e7..d9bb5a96068 100644 --- a/include/arch/arm/cortex_m/scripts/linker.ld +++ b/include/arch/arm/cortex_m/scripts/linker.ld @@ -235,6 +235,10 @@ SECTIONS *(".rodata.*") *(.gnu.linkonce.r.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RODATA_LD #include #endif @@ -385,6 +389,11 @@ SECTIONS _ramfunc_rom_start = LOADADDR(.ramfunc); #endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */ +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + #if defined(CONFIG_USERSPACE) #define APP_SHARED_ALIGN . = ALIGN(_region_min_align); #define SMEM_PARTITION_ALIGN MPU_ALIGN @@ -427,6 +436,10 @@ SECTIONS *(".noinit.*") *(".kernel_noinit.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_NOINIT_LD #include #endif @@ -440,6 +453,10 @@ SECTIONS *(".data.*") *(".kernel.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RWDATA_LD #include #endif @@ -516,6 +533,11 @@ SECTIONS #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/include/arch/nios2/linker.ld b/include/arch/nios2/linker.ld index 888a7feb6c1..b56c7f46523 100644 --- a/include/arch/nios2/linker.ld +++ b/include/arch/nios2/linker.ld @@ -147,6 +147,10 @@ SECTIONS *(".rodata.*") *(.gnu.linkonce.r.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RODATA_LD #include #endif @@ -195,6 +199,10 @@ SECTIONS *(.data) *(".data.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RWDATA_LD #include #endif @@ -224,6 +232,11 @@ SECTIONS *(.sdata .sdata.* .gnu.linkonce.s.*) *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) __data_ram_end = .; @@ -260,6 +273,10 @@ SECTIONS #ifdef CONFIG_SOC_NOINIT_LD #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include } GROUP_LINK_IN(RAMABLE_REGION) @@ -273,6 +290,10 @@ SECTIONS /* Located in project source directory */ #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_GEN_ISR_TABLES #include diff --git a/include/arch/riscv32/common/linker.ld b/include/arch/riscv32/common/linker.ld index 21c12e1e45c..e4bbe2367fa 100644 --- a/include/arch/riscv32/common/linker.ld +++ b/include/arch/riscv32/common/linker.ld @@ -110,6 +110,10 @@ SECTIONS *(".rodata.*") *(.gnu.linkonce.r.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RODATA_LD #include #endif @@ -135,6 +139,10 @@ SECTIONS *(.sdata .sdata.* .gnu.linkonce.s.*) *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RWDATA_LD #include #endif @@ -143,6 +151,10 @@ SECTIONS #include +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include __data_ram_end = .; SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) @@ -174,6 +186,10 @@ SECTIONS *(.noinit) *(".noinit.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_NOINIT_LD #include #endif @@ -183,6 +199,11 @@ SECTIONS _image_ram_end = .; _end = .; /* end of image */ +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/include/arch/x86/linker.ld b/include/arch/x86/linker.ld index 88a21728313..e32fb4f2137 100644 --- a/include/arch/x86/linker.ld +++ b/include/arch/x86/linker.ld @@ -152,6 +152,10 @@ SECTIONS #endif /* CONFIG_X86_FIXED_IRQ_MAPPING */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RODATA_LD #include #endif @@ -207,6 +211,11 @@ SECTIONS __gcov_bss_size = __gcov_bss_end - __gcov_bss_start; #endif /* CONFIG_COVERAGE_GCOV */ +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + #ifdef CONFIG_USERSPACE /* APP SHARED MEMORY REGION */ #define SMEM_PARTITION_ALIGN(size) MMU_PAGE_ALIGN @@ -260,6 +269,10 @@ SECTIONS *(".noinit.*") *(".kernel_noinit.*") +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_NOINIT_LD #include #endif @@ -296,6 +309,10 @@ SECTIONS #endif /* LINKER_PASS2 */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_SOC_RWDATA_LD #include #endif @@ -446,6 +463,10 @@ SECTIONS /* Located in project source directory */ #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #include diff --git a/soc/riscv32/openisa_rv32m1/linker.ld b/soc/riscv32/openisa_rv32m1/linker.ld index 4c725e3dc6a..ddbd7566fa2 100644 --- a/soc/riscv32/openisa_rv32m1/linker.ld +++ b/soc/riscv32/openisa_rv32m1/linker.ld @@ -113,6 +113,12 @@ SECTIONS *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + } GROUP_LINK_IN(ROMABLE_REGION) _image_rodata_end = .; @@ -143,6 +149,12 @@ SECTIONS /* https://groups.google.com/a/groups.riscv.org/d/msg/sw-dev/60IdaZj27dY/TKT3hbNlAgAJ */ *(.sdata .sdata.* .gnu.linkonce.s.*) *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) #include @@ -175,8 +187,19 @@ SECTIONS * will not be cleared during the boot process. */ *(.noinit .noinit.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + } GROUP_LINK_IN(RAMABLE_REGION) +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + _image_ram_end = .; _end = .; /* end of image */ @@ -186,6 +209,10 @@ SECTIONS /* Located in project source directory */ #include #endif +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include #ifdef CONFIG_GEN_ISR_TABLES /* Bogus section, post-processed during the build to initialize interrupts. */