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
riscv/arch_elf: Check for _HI20 relocation validity #11389
Conversation
As pointed out in apache#11322 there is a hardware design issue in RISC-V that affects RV64 relocations. The problem is with how address bits are loaded into registers via lui / auipc and sign extension. If the hi20 relocation value happens to have its 32-bit sign bit set, i.e. value is 0x80000000 (but not negative! i.e. negative in 64-bit format) the relocation will fail, as the address is erroneously sign extended: 0x00000000_80000000 becomes 0xffffffff_80000000 which is not correct. Also, make sure the correct opcode is used with PCREL_HI20, it expects AUIPC (not LUI). The C compiler will never emit such code but when hand- writing assembly code this can happen.
@pkarashchenko this should now detect the issue discussed in #11322 . I still need to test a bit more but the code itself is ready for review. If I understood the problem description in the tickets you pointed out, the problem is exactly with 32-bit sign extension, so if the value is negative (in u64) the relocation works fine, but the singular exception is when the symbol value is positive but has the 32-bit sign bit set. Took a while to understand, and I'm not 100% sure I still do... |
Marking as draft so this does not get accidentally merged before I can run the tests |
@pkarashchenko it works. Test code as follows main.c:
addr.S:
Using badaddr
Using goodaddr:
Tested with rv-virt:knsh64, had to disable optimizations for main, as the compiler did not want to produce the erroneous code otherwise. |
Summary
As pointed out in #11322 there is a hardware design issue in RISC-V that affects RV64 relocations. The problem is with how address bits are loaded into registers via lui / auipc and sign extension.
If the hi20 relocation value happens to have its 32-bit sign bit set, i.e. value is 0x80000000 (but not negative! i.e. negative in 64-bit format) the relocation will fail, as the address is erroneously sign extended:
0x00000000_80000000 becomes 0xffffffff_80000000 which is not correct.
Also, make sure the correct opcode is used with PCREL_HI20, it expects AUIPC (not LUI). The C compiler will never emit such code but when hand- writing assembly code this can happen.
Impact
Fix two unlikely issues with risc-v elfloader
Testing
rv-virt:knsh64