diff --git a/Kconfig.zephyr b/Kconfig.zephyr index c5edf65402a..0cf29caac12 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -162,6 +162,13 @@ config CMAKE_LINKER_GENERATOR endchoice +config LLVM_USE_LD + bool "LLVM use ld linker" + depends on "${ZEPHYR_TOOLCHAIN_VARIANT}" = "llvm" + default y + help + Use binutils ld linker instead of LLVM built-in lld linker. + config HAVE_CUSTOM_LINKER_SCRIPT bool "Custom linker script provided" help diff --git a/cmake/linker/lld/target.cmake b/cmake/linker/lld/target.cmake index 562c6efdde9..dedae2f71c6 100644 --- a/cmake/linker/lld/target.cmake +++ b/cmake/linker/lld/target.cmake @@ -107,7 +107,7 @@ endfunction(toolchain_ld_link_elf) # Load toolchain_ld-family macros -include(${ZEPHYR_BASE}/cmake/linker/ld/target_base.cmake) +include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_base.cmake) include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_baremetal.cmake) include(${ZEPHYR_BASE}/cmake/linker/ld/target_cpp.cmake) include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake) diff --git a/cmake/linker/lld/target_baremetal.cmake b/cmake/linker/lld/target_baremetal.cmake index 76965ed81b2..6faf8f50cac 100644 --- a/cmake/linker/lld/target_baremetal.cmake +++ b/cmake/linker/lld/target_baremetal.cmake @@ -4,7 +4,7 @@ macro(toolchain_ld_baremetal) - # LINKERFLAGPREFIX comes from linker/ld/target.cmake + # LINKERFLAGPREFIX comes from linker/lld/target.cmake zephyr_ld_options( -nostdlib -static @@ -12,6 +12,13 @@ macro(toolchain_ld_baremetal) ${LINKERFLAGPREFIX},-N ) + # Force LLVM to use built-in lld linker + if(NOT CONFIG_LLVM_USE_LD) + zephyr_ld_options( + -fuse-ld=lld + ) + endif() + # Funny thing is if this is set to =error, some architectures will # skip this flag even though the compiler flag check passes # (e.g. ARC and Xtensa). So warning should be the default for now. diff --git a/cmake/linker/lld/target_base.cmake b/cmake/linker/lld/target_base.cmake new file mode 100644 index 00000000000..ecd3f9acfca --- /dev/null +++ b/cmake/linker/lld/target_base.cmake @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 + +# See root CMakeLists.txt for description and expectations of these macros + +macro(toolchain_ld_base) + + if(NOT PROPERTY_LINKER_SCRIPT_DEFINES) + set_property(GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES -D__GCC_LINKER_CMD__) + endif() + + # TOOLCHAIN_LD_FLAGS comes from compiler/clang/target.cmake + # LINKERFLAGPREFIX comes from linker/lld/target.cmake + zephyr_ld_options( + ${TOOLCHAIN_LD_FLAGS} + ) + + zephyr_ld_options( + ${LINKERFLAGPREFIX},--gc-sections + ${LINKERFLAGPREFIX},--build-id=none + ) + + # Sort each input section by alignment. + zephyr_ld_option_ifdef( + CONFIG_LINKER_SORT_BY_ALIGNMENT + ${LINKERFLAGPREFIX},--sort-section=alignment + ) + +endmacro() diff --git a/cmake/toolchain/llvm/generic.cmake b/cmake/toolchain/llvm/generic.cmake index b25e8cee284..0f24abbe98b 100644 --- a/cmake/toolchain/llvm/generic.cmake +++ b/cmake/toolchain/llvm/generic.cmake @@ -9,7 +9,11 @@ endif() set(LLVM_TOOLCHAIN_PATH ${CLANG_ROOT_DIR} CACHE PATH "clang install directory") set(COMPILER clang) -set(LINKER lld) +if(CONFIG_LLVM_USE_LD) + set(LINKER ld) +else() + set(LINKER lld) +endif() set(BINTOOLS llvm) if("${ARCH}" STREQUAL "arm") diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index d31ac5a720e..65e508c7d23 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -313,6 +313,15 @@ SECTIONS /* Needs KEEP() as ENTRY() is given a physical address */ KEEP(*(.text.__start)) +/* + * We need these sections to extract interrupt information, but they + * will be removed with "--gc-sections" by LLVM lld, so add keep + * command to save them. + */ +#ifndef CONFIG_LLVM_USE_LD + KEEP(*(.text.irqstubs)) + KEEP(*(".gnu.linkonce.t.exc_*_stub")) +#endif *(.text) *(".text.*") *(.gnu.linkonce.t.*) @@ -532,7 +541,22 @@ SECTIONS #include /DISCARD/ : { *(.note.GNU-stack) } +/* + * eh_frame section won't be removed even with "--gc-sections" by LLVM lld. + */ +#if !defined(CONFIG_EXCEPTIONS) + /DISCARD/ : { *(.eh_frame) } +#endif +/* + * The sections below are still treated as warnings + * with "--orphan-handling=warn" by LLVM lld. + */ +#if !defined(CONFIG_LLVM_USE_LD) + .symtab 0 : { *(.symtab) } + .strtab 0 : { *(.strtab) } + .shstrtab 0 : { *(.shstrtab) } +#endif } #ifdef CONFIG_XIP diff --git a/include/zephyr/arch/x86/intel64/linker.ld b/include/zephyr/arch/x86/intel64/linker.ld index 1226988f719..1af071b2da8 100644 --- a/include/zephyr/arch/x86/intel64/linker.ld +++ b/include/zephyr/arch/x86/intel64/linker.ld @@ -217,4 +217,21 @@ SECTIONS *(.rel.*) *(.rela.*) } +/* + * eh_frame section won't be removed even with "--gc-sections" by LLVM lld. + */ +#if !defined(CONFIG_EXCEPTIONS) + /DISCARD/ : { *(.eh_frame) } +#endif + +/* + * The sections below are still treated as warnings + * with "--orphan-handling=warn" by LLVM lld. + */ +#if !defined(CONFIG_LLVM_USE_LD) + .symtab 0 : { *(.symtab) } + .strtab 0 : { *(.strtab) } + .shstrtab 0 : { *(.shstrtab) } +#endif + }