-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Relocation trunacted to fit error R_RISCV_JAL while compiling kernel #738
Comments
|
I tried a build on my fedora rawhide box, with gcc-10.2 and binutils-2.35. I did not get a link error. I can see from your config file that you have gcc-9.3, and binutils-2.33. Checking ChangeLog entries, this could perhaps be |
|
@jim-wilson Did you try the kernel tree I shared ? I am getting linker error with configs generated with defconfig as well with gcc-10.2 & binutils-2.35. Earlier, I used to see the error only with the config shared. Here is the part of the config generated from defconfig |
|
Yes, I tried your tree, but it didn't fail for me with gcc-10 and binutils-2.35. I was able to reproduce last night using gcc-9.3 and binutils-2.33.1 though. Adding the patch from 25181 didn't fix it, so I need to try to debug it. |
|
Huh..I can't reproduce the issue with the config where CONFIG_HARDENED_USERCOPY is enabled. But it fails with the config generated using defconfig. I guess the fix works for some cases but fails for others. Here are the steps to reproduce the issue with gcc-10 & binutils-2.35
Here are the linker errors I see |
|
This is an alignment padding problem. There is a call from .init.text to .text. .init.text immediately follows .text. The call is in range of a jal instruction when relaxed. Further relaxation causes the .text target address to decrease. An alignment directlve between .init.text and .text means that the .init.text starting address does not decrease during relaxation. Normally, the difference between two code addresses can only decrease during relaxation. But alignment directives means that offsets can increase, worst case, by as much as the specified alignment. In this case, the offset ends up increasing just enough to make it too large for a JAL and we get a relocation overflow error at the end. The linker tries to take alignment directives into account, by adding section alignment to the offset before deciding if it will fit in a relaxed instruction. Normally alignments are small so this is OK. In this case you have a large alignment. But even worse is that the alignment is in between sections, and the RISC-V relaxation code isn't aware of it. This causes the relocation error as we aren't adjust for alignments properly. I don't know if we can handle alignment directives in between sections during relaxation time. The relaxation code may not have access to such linker script info. We do have access to section alignments though. I can work around the problem by making the section alignments explicit in the linker script. With this change In the executable .init.text is now specified to have 1<<21 alignment. it still has the same starting address as before. The link succeeds with this change. I get about a 6.6KB increase in the code size due to less relaxation, as the large section alignment will prevent a lot of cross section relaxation. For calls within a section, we use that section's alignment in the calculation. For calls across sections, e.g. from .init.text to .text, we use the max section alignment. We really should use the max section alignment of the sections in between the source and target sections, but it isn't obvious how to compute that, so we just use the max of all section alignments which is safe. This does mean that setting one section alignment to 1<<21 is going to affect all cross section relaxations though, and all relaxations inside that section. Relaxations within .text will still happen as before though, and I only see the .text size increase by 32 bytes. The .exit.text size increases by 100 bytes. And .init.text increases by 6.5K. Given that the kernel is about 8.9M a 6.5K increase should be OK. |
|
Thanks @jim-wilson . That fixes the problem. I am not sure if that will be acceptable to upstream kernel though. I will propose this to the mailing list. Thanks a lot for the investigation. I have a question though. This may be a very stupid question as I don't have much experience in toolchain. Why does the relaxation code doesn't have access to the alignment between sections while it have access to the section alignments ? |
|
I know that the linker goes through the linker script commands in order as it operates, repeating this until the result stablizes, and I don't know if the relaxation code has access to any of that info. But the relaxation code does have access to ELF stuff like section info, as that is all maintained in bfd not in the linker code. So the linker scripts are handled by the code in the ld dir, and input and output sections contents and flags are handled by the code in the bfd dir. The relaxation code is in the bfd dir also so it has access to all of the object file stuff, but maybe not the linker script. I'm more of a gcc expert than a binutils expert, so I don't kinow if there is some obscure way to get the info we need to fix this. |
|
Thanks @jim-wilson . @palmer-dabbelt any thoughts ? |
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com> Tested-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com>
In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com> Tested-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
|
@atishp04 Hi, is this issue got solved? |
|
No update/activity in over a year so presuming that there's no outstanding issue at this stage. |
mainline inclusion from mainline-5.11 commit b6566dc1acca38ce6ed845ce8a270fb181ff6d41 category: feature feature: native builds with llvm Signed-off-by: Polyos Project <polyos@iscas.ac.cn> --------------------------------------- [ Upstream commit ] In order to improve kernel text protection, we need separate .init.text/ .init.data/.text in separate sections. However, RISC-V linker relaxation code is not aware of any alignment between sections. As a result, it may relax any RISCV_CALL relocations between sections to JAL without realizing that an inter section alignment may move the address farther. That may lead to a relocation truncated fit error. However, linker relaxation code is aware of the individual section alignments. The detailed discussion on this issue can be found here. riscv-collab/riscv-gnu-toolchain#738 Keep the .init.text section aligned so that linker relaxation will take that as a hint while relaxing inter section calls. Here are the code size changes for each section because of this change. section change in size (in bytes) .head.text +4 .text +40 .init.text +6530 .exit.text +84 The only significant increase in size happened for .init.text because all intra relocations also use 2MB alignment. Suggested-by: Jim Wilson <jimw@sifive.com> Signed-off-by: Atish Patra <atish.patra@wdc.com> Tested-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
|
I want to known if this problem has been solved, I occur this proble when I want to cross-compile LLVM. /home/sole/work/qemu_rvv/llvm-project-main/clang/lib/CodeGen/CGBuiltin.cpp:21038:(.text+0x13606a): relocation truncated to fit: R_RISCV_JAL against `.L13090' |
Please explain how exactly you are building LLVM - i.e. all commands/steps taken: |
|
-- The C compiler identification is GNU 13.2.0 The cmake-policies(7) manual explains that the OLD behaviors of all -- LLD version: 19.0.0 The cmake-policies(7) manual explains that the OLD behaviors of all -- Looking for sys/resource.h |
|
What you've provided isn't sufficient for others to reproduce the issue. You need to ideally provide a small, self-contained, reproducible test case that will do this. You also didn't clarify all relevant details - how you built your RISC-V GCC toolchain, what specific LLVM tarball you downloaded to use, why you didn't build LLVM using these instructions, etc: That's why I asked for details of all of the commands that you used from start to finish to build GCC/LLVM/Clang etc. And then a small, self-contained, reproducible test program that illustrates the error. |
|
@dinyy could you file new issue for that? also plz give text version for the cmake command and ToolchainExample.cmake if possible? |
OK,I'm trying to upload all this. |
|
I file a new issue here:#1455 @TommyMurphyTM1234 |


Hi,
I am making some changes in linux kernel to improve kernel protection. I tried to move .init.text below .text both being in a different 2MB sections. This is done to apply different permissions to these areas. Kernel uses 2MB(PMD) mappings to improve kernel performance.
Here is the branch with the required changes.
https://github.com/atishp04/linux/tree/relocation_jal_issue
It works most of the time except when CONFIG_HARDENED_USERCOPY is enabled.
I see the following linker error in that case.
net/ipv4/ipconfig.o: in function
ic_setup_routes': /home/atish/workspace/linux/net/ipv4/ipconfig.c:400:(.init.text+0x1c4): relocation truncated to fit: R_RISCV_JAL against symbolip_rt_ioctl' defined in .text section in net/ipv4/fib_frontend.omake: *** [Makefile:1162: vmlinux] Error 1
This happens only when copy_from_user is called from function that is annotated with __init.
The relocation id seems to be RISCV_CALL from the objdump. I am not sure why linker converts it to JAL.
I further narrowed down the issue to a __builtin_constant_p
Here is the code path:
ip_rt_ioctl->rtentry_to_fib_config->copy_from_user->check_copy_size->check_object_size
Commenting line 118 avoids the issue.
The required config, temporary object file, compilation logs are shared here.
https://wdc.box.com/s/m6be2vlnpp1pljr20o1bzrxl87xdp93p
Reproduction steps:
https://github.com/atishp04/linux/tree/relocation_jal_issue
Please let me know if you need anything else.
@jim-wilson
The text was updated successfully, but these errors were encountered: