riscvarchive / riscv-binutils-gdb

RISC-V backports for binutils-gdb. Development is done upstream at the FSF.
GNU General Public License v2.0
147 stars 233 forks source link

Binutils-2.32 relocation truncated to fit: R_RISCV_RVC_LUI #173

Closed galak closed 5 years ago

galak commented 5 years ago

Seeing the following:

/home/galak/git/zephyr/samples/subsys/logging/logger/src/ext_log_system_adapter.c:36:(.text.ext_log_system_log_adapt+0x0): relocation truncated to fit: R_RISCV_RVC_LUI against `log_handler'
collect2: error: ld returned 1 exit status
%

If I drop these commits seems to link ok: https://github.com/riscv/riscv-binutils-gdb/commit/009b05a9c3c723d184f6fcda4aabdc84ef678146 https://github.com/riscv/riscv-binutils-gdb/commit/7de6f82c36c93f4ea8ec5cbf7bb0a5f636ffb045

jim-wilson commented 5 years ago

I need a testcase to reproduce. A zephyr git commit id and the make commands you used might be enough to reproduce.

galak commented 5 years ago

Zephyr commit: https://github.com/zephyrproject-rtos/zephyr/commit/a8b208aff77fddd4e02589ed00323a0921a7d77c

Short version:

export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
export CROSS_COMPILE=/<PATH>/riscv-none-elf-
cd <ZEPHYR_ROOT>
source zephyr-env.sh 
cd samples/subsys/logging/logger
mkdir build
cd build
cmake -DBOARD=rv32m1_vega_ri5cy ..
make

Detailed getting started guide: https://docs.zephyrproject.org/latest/getting_started/index.html

kito-cheng commented 5 years ago

Tested with -march=[rv32ic|rv32imc|rv32ima|rv32imac] -mabi=ilp32 can't reproduced? could you provide more detail such as which gcc or binutils you are using, and the configuration of gcc (gcc -v) or riscv-gnu-toolchain?

gcc: https://github.com/riscv/riscv-gcc/commit/bdf3ad8996cb305a822feb1eb11235e08fe4b974 binutils: https://github.com/riscv/riscv-binutils-gdb/commit/009b05a9c3c723d184f6fcda4aabdc84ef678146

riscv-gnu-toolchain configuration:

riscv-gnu-toolchain/configure --with-arch=[rv32ic|rv32imc|rv32ima|rv32imac] --enable-gcc-checking --disable-multilib
galak commented 5 years ago

So I used riscv-gnu-toolchain @ 7833a53f8b0d0edb2bec0bb9a177685ae75570d5 and binutils @ 009b05a9c3c723d184f6fcda4aabdc84ef678146. I built:

./configure --with-arch=rv32ima --with-abi=ilp32

I also see this with the Zephyr SDK tool set which is based on the patches from the riscv-gnu-toolchain repo.

Linux binary package:

https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.10.2/zephyr-sdk-0.10.2-setup.run

kito-cheng commented 5 years ago

Oh, Ok, I can reproduce now, thanks!

kito-cheng commented 5 years ago

Reduce case: https://drive.google.com/file/d/1FVwboQ72pzU0jcEAGT5zsWQlrJioBok1/view?usp=sharing

$ make
riscv32-unknown-elf-ld -melf32lriscv -o zephyr_prebuilt.elf -u _OffsetAbsSyms -u _ConfigAbsSyms -L . empty_file.c.obj -T linker.cmd  --whole-archive libapp.a libzephyr.a liblib__libc__minimal.a libboards__riscv__rv32m1_vega.a libdrivers__gpio.a libdrivers__serial.a --no-whole-archive libkernel.a offsets.c.obj -lgcc --gc-sections --sort-common=descending --sort-section=alignment -X -N --orphan-handling=warn
libapp.a(ext_log_system_adapter.c.obj): in function `ext_log_system_log_adapt':
/scratch/kitoc/zephyr/samples/subsys/logging/logger/src/ext_log_system_adapter.c:36:(.text.ext_log_system_log_adapt+0x0): relocation truncated to fit: R_RISCV_RVC_LUI against `log_handler'
Makefile:5: recipe for target 'all' failed
jim-wilson commented 5 years ago

I managed to reproduce after spending a lot of time resolving tools dependencies. But too late to do anything useful. Meanwhile, Kito extracted a testcase, so I'm using that for now. Adding --noinhibit-exec to the link, and using objdump, I see the problem function is

0000083e : 83e: 6501 0x6501 840: 00050513 mv a0,a0 844: a001 j 844 <ext_log_system_log_adapt+0\ x6>

This was originally

00000000 : 0: 00000537 lui a0,0x0 0: R_RISCV_HI20 log_handler 0: R_RISCV_RELAX ABS 4: 00050513 mv a0,a0 4: R_RISCV_LO12_I log_handler 4: R_RISCV_RELAX ABS 8: 00000317 auipc t1,0x0 8: R_RISCV_CALL ext_log_handler_set 8: R_RISCV_RELAX ABS c: 00030067 jr t1 # 8 <ext_log_system_log_adapt+0x8>

And the target function in the linker output is

000007fc : 7fc: 7139 addi sp,sp,-64 7fe: da3e sw a5,52(sp) ...

So the apparent problem here is that the target address starts above 0x1000 and is valid for c.lui, and then as relaxation proceeds it drops below 0x1000 and is no longer valid for c.lui. It looks like we can fix this by converting the c.lui to a c.li. We already do something similar for weak function support.

Also note that this requires code linked to an address of zero. Rocket-chip derived parts that I am familiar with don't put memory at 0, so won't trigger this problem. This is probably why it didn't turn up in our testing. The executable incidentally has

00000000 <__irq_wrapper>: 0: 7159 addi sp,sp,-112

and an accidental null pointer write will overwrite that, damaging that function.

jim-wilson commented 5 years ago

That should be 0x800 not 0x1000 above. Since we use lui/addi, 0x800 is lui 0x1/addi -0x800. The symbol in question is exactly 0x800 on the first pass through which is OK for c.lui, and then ends up as 0x7fc at the end which is not OK.

I have a proposed fix, which is to use c.li instead of c.lui when this happens. It works OK on the testcase. I now get

0000083e : 83e: 4501 li a0,0 840: 7fc00513 li a0,2044 844: b725 j 76c

The fprintf is for testing purposes; I suspect this won't trigger in my usual testing. This needs to come out before the patch goes upstream. The patch also needs a linker testcase which I haven't written yet.

relax-clui-to-lui.txt

aswaterman commented 5 years ago

LGTM.

On Wed, Aug 14, 2019 at 3:49 PM Jim Wilson notifications@github.com wrote:

That should be 0x800 not 0x1000 above. Since we use lui/addi, 0x800 is lui 0x1/addi -0x800. The symbol in question is exactly 0x800 on the first pass through which is OK for c.lui, and then ends up as 0x7fc at the end which is not OK.

I have a proposed fix, which is to use c.li instead of c.lui when this happens. It works OK on the testcase. I now get

0000083e : 83e: 4501 li a0,0 840: 7fc00513 li a0,2044 844: b725 j 76c

The fprintf is for testing purposes; I suspect this won't trigger in my usual testing. This needs to come out before the patch goes upstream. The patch also needs a linker testcase which I haven't written yet.

relax-clui-to-lui.txt https://github.com/riscv/riscv-binutils-gdb/files/3503608/relax-clui-to-lui.txt

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/riscv/riscv-binutils-gdb/issues/173?email_source=notifications&email_token=AAH3XQSRYAHSI7KN4DDXGLDQESDYJA5CNFSM4ILFDKS2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4KKZFY#issuecomment-521448599, or mute the thread https://github.com/notifications/unsubscribe-auth/AAH3XQQ4XRLH3YLU5YFKW43QESDYJANCNFSM4ILFDKSQ .

galak commented 5 years ago

Can verify this fixes the issue and doesn't cause any new ones for RISC-V support in Zephyr.

jim-wilson commented 5 years ago

Patch committed upstream.