zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.61k stars 6.5k forks source link

LLVM: support -fuse-ld=lld linker on qemu_x86. #41776

Closed chen-png closed 2 years ago

chen-png commented 2 years ago

Describe the bug when tried to use LLVM built-in lld linker to build zephyr case, it met a link error "section 'boot.text' will not fit in region 'RAM': overflowed by 18446744072631615488 bytes"

To Reproduce Steps to reproduce the behavior:

  1. set LLVM toolchain: export ZEPHYR_TOOLCHAIN_VARIANT=llvm export LLVM_TOOLCHAIN_PATH=~/llvm/llvm-project/build_2 (notice: (the LLVM version must be after this commit https://github.com/llvm/llvm-project/commit/2bf06d9345caeb26520be8e830c092683bbdf0f7, otherwise, it couldn't support parsing quoted symbol like "__start" which is used for zephyr entry point))
  2. apply this patch, it's used for forcing llvm to use lld and solving option compatibility between ld and lld.

    
    diff --git a/Kconfig.zephyr b/Kconfig.zephyr
    index d2d3e0a8db..349a98da7b 100644
    --- a/Kconfig.zephyr
    +++ b/Kconfig.zephyr
    @@ -162,6 +162,12 @@ config CMAKE_LINKER_GENERATOR
    
    endchoice

+config LLVM_USE_BUILTIN_LLD

  1. west build -b qemu_x86 -p auto samples/hello_world/ -DCONFIG_LLVM_USE_BUILTIN_LLD=y
  2. See error

Logs and console output [83/97] Linking C executable zephyr/zephyr_pre0.elf FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map /home/chenpeng/zephyrproject/zephyr/build/zephyr/zephyr_pre0.map : && ccache /home/chenpeng/llvm/llvm-project/build_2/bin/clang --target=i686-pc-none-elf zephyr/CMakeFiles/zephyr_pre0.dir/misc/empty_file.c.obj -o zephyr/zephyr_pre0.elf zephyr/CMakeFiles/offsets.dir/./arch/x86/core/offsets/offsets.c.obj -Wl,-T zephyr/linker_zephyr_pre0.cmd -Wl,-Map=/home/chenpeng/zephyrproject/zephyr/build/zephyr/zephyr_pre0.map -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/arch/x86/core/libarchx86core.a zephyr/lib/libc/minimal/libliblibcminimal.a zephyr/lib/posix/liblibposix.a zephyr/subsys/random/libsubsysrandom.a zephyr/drivers/interrupt_controller/libdrivers__interrupt_controller.a zephyr/drivers/console/libdriversconsole.a zephyr/drivers/serial/libdriversserial.a zephyr/drivers/timer/libdrivers__timer.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a -L"/usr/lib64/gcc/x86_64-redhat-linux/9/32" -L/home/chenpeng/zephyrproject/zephyr/build/zephyr -lgcc -no-pie -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-section=alignment -Wl,-u,_OffsetAbsSyms -Wl,-u,_ConfigAbsSyms -nostdlib -static -Wl,-X -Wl,-N -fuse-ld=lld -Wl,--orphan-handling=warn && cd /home/chenpeng/zephyrproject/zephyr/build/zephyr && /home/chenpeng/.local/lib/python3.7/site-packages/cmake/data/bin/cmake -E echo clang-13: warning: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument] ld.lld: warning: :(.eh_frame) is being placed in '.eh_frame' ld.lld: warning: :(.symtab) is being placed in '.symtab' ld.lld: warning: :(.shstrtab) is being placed in '.shstrtab' ld.lld: warning: :(.strtab) is being placed in '.strtab' ld.lld: error: no memory region specified for section '.eh_frame' ld.lld: error: zephyr/linker_zephyr_pre0.cmd:101: unable to move location counter backward for: text ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705357312 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705357312 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705357473 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705357754 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358093 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358098 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358121 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358134 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358149 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358191 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358239 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358523 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705358605 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705359498 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705359722 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705359870 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705359900 bytes ld.lld: error: section 'text' will not fit in region 'RAM': overflowed by 18446744073705359914 bytes ld.lld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors) collect2: error: ld returned 1 exit status clang-13: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. FATAL ERROR: command exited with status 1: /home/chenpeng/.local/bin/cmake --build /home/chenpeng/zephyrproject/zephyr/build

Part of code of liner script linker_zephyr_pre0.cmd:

MEMORY
    {
    RAM (wx) : ORIGIN = (0 + 0x100000), LENGTH = (4194304 - 0x100000)
    IDT_LIST : ORIGIN = 0xFFFF1000, LENGTH = 2K

    }
  OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
  OUTPUT_ARCH("i386")
epoint = ((__start) - ((0x0 + 0x100000) - (0x0 + 0x100000)));
ENTRY(epoint)
 text :
 {
 __text_region_start = .;
 z_mapped_start = .;
. = 0x0;
. = ALIGN(4);
 KEEP(*(.text.__start))
 *(.text)
 *(".text.*")
 *(.gnu.linkonce.t.*)
 *(.init)
 *(.fini)
 *(.eini)
 . = ALIGN(0x1000);
 } > RAM

Environment (please complete the following information):

nashif commented 2 years ago

@tejlmand your input appreciated.

chen-png commented 2 years ago

@tejlmand Could you tell me the purpose of this two line?

. = 0x0; . = ALIGN(4);

it's from a generated liner script "snippets-rom-start.ld", I am curious why we need to set the location counter to 0x0, because the RAM region it starts from 0x100000, this will meet a location counter move backwards error.

chen-png commented 2 years ago

not sure why this "snippets-rom-start.ld" linker script for ROM is there, but for this case, it should does not matter. because that linker script is used for putting .text section into ROM, but in this case, we put .text in RAM, so I removed it, then it didn't report any move backwards error or overflow error. tested on qemu_x86, qemu_x86_64, built a hello_word and it worked well.

tejlmand commented 2 years ago

it's from a generated liner script "snippets-rom-start.ld", I am curious why we need to set the location counter to 0x0, because the RAM region it starts from 0x100000, this will meet a location counter move backwards error.

This originates from here, and is default included in the snippets-rom-start.ld: https://github.com/zephyrproject-rtos/zephyr/blob/875ec0a0cb02d261f758adf2d0f6a01ca566b4df/arch/common/rom_start_offset.ld#L7-L8

but the x86 doesn't place its text in rom, as it don't have a FLASH memory region. Seems lld is a bit more pedantic on this than ld on this.

One trick, is to set the rom offset == 0x100000, like this:

-DCONFIG_ROM_START_OFFSET=0x100000

This will fix both the overflow error and the location counter moving backwards. We should look into if this snippet make sense for x86: https://github.com/zephyrproject-rtos/zephyr/blob/875ec0a0cb02d261f758adf2d0f6a01ca566b4df/include/arch/x86/ia32/linker.ld#L94

it probably does, but then we should ensure it behaves properly.