Skip to content
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

Merged
merged 1 commit into from Dec 14, 2023

Conversation

pussuw
Copy link
Contributor

@pussuw pussuw commented Dec 13, 2023

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

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.
@pussuw
Copy link
Contributor Author

pussuw commented Dec 13, 2023

@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...

@pussuw pussuw marked this pull request as draft December 13, 2023 15:55
@pussuw
Copy link
Contributor Author

pussuw commented Dec 13, 2023

Marking as draft so this does not get accidentally merged before I can run the tests

@pussuw pussuw marked this pull request as ready for review December 14, 2023 12:23
@pussuw
Copy link
Contributor Author

pussuw commented Dec 14, 2023

@pkarashchenko it works.

Test code as follows

main.c:

extern unsigned long badaddr;
extern unsigned long goodaddr;

int __attribute__((optimize("-O0"))) main (int argc, char *argv[])
//int main (int argc, char *argv[])
{
  //return (unsigned long)&badaddr != 7ul;
  return (unsigned long)&goodaddr != 7ul;
}

addr.S:

.globl badaddr
.globl goodaddr

.set usr_vma_base, 0xc0000000

.set badaddr, usr_vma_base+0x80000000
.set goodaddr, usr_vma_base+0x7ffff7ff

Using badaddr

[    0.037000] elf_symvalue: SHN_ABS: st_value=140000000
[    0.037000] up_relocateadd: PCREL_HI20 at c0000050 [00000697] to sym=0x80209520 st_value=140000000
[    0.038000] _calc_imm: offset=2147483568: hi=524288 lo=-80 off=7fffffb0
[    0.038000] up_relocateadd: ERROR: PCREL_HI20 at c0000050 bad:80000000
[    0.039000] elf_relocateadd: ERROR: Section 2 reloc 8: Relocation failed: -22
[    0.039000] elf_loadbinary: Failed to bind symbols program binary: -22
[    0.040000] exec_internal: ERROR: Failed to load program '/system/bin/init': -22
[    0.040000] _assert: Current Version: NuttX  10.4.0 66082b5dd6-dirty Dec 14 2023 13:50:45 risc-v
[    0.040000] _assert: Assertion failed : at file: init/nx_bringup.c:308 task: Idle_Task process: Kernel 0x80001b9c
[    0.040000] up_dump_register: EPC: 0000000080002250
[    0.040000] up_dump_register: A0: 0000000080201380 A1: 0000000000000134 A2: 0000000000000000 A3: 000000000000007e
[    0.040000] up_dump_register: A4: 0000000080200f68 A5: 0000000000000002 A6: 0000000080206cf0 A7: 0000000000000000
[    0.040000] up_dump_register: T0: 000000000000002e T1: 000000000000006a T2: 00000000000001ff T3: 000000000000006c
[    0.040000] up_dump_register: T4: 0000000000000068 T5: 0000000000000009 T6: 000000000000002a
[    0.040000] up_dump_register: S0: 0000000000000000 S1: 0000000080200f68 S2: 0000000080201ecc S3: 0000000000000000
[    0.040000] up_dump_register: S4: 0000000000000000 S5: 000000008001a350 S6: 8000000000046022 S7: 0000000080201eb8
[    0.040000] up_dump_register: S8: 0000000000000134 S9: 0000000000000000 S10: 0000000000000000 S11: 0000000000000000
[    0.040000] up_dump_register: SP: 0000000080206a00 FP: 0000000000000000 TP: 0000000000000000 RA: 0000000080002250
[    0.040000] dump_stack: User Stack:
[    0.040000] dump_stack:   base: 0x80206010
[    0.040000] dump_stack:   size: 00003056
[    0.040000] dump_stack:     sp: 0x80206a00
[    0.040000] stack_dump: 0x802069e0: 00000001 00000000 80200f68 00000000 80206a00 00000000 800023b4 00000000
[    0.040000] stack_dump: 0x80206a00: 80001b9c 00000000 8001d028 00000000 0000000f 00000000 80017c58 00000000
[    0.040000] stack_dump: 0x80206a20: 80200f68 00000000 80201380 00000000 00000000 00000000 8001a350 00000000
[    0.040000] stack_dump: 0x80206a40: 00000134 00000000 7474754e 00000058 80206c00 00000000 00000000 00000000
[    0.040000] stack_dump: 0x80206a60: 00000001 00000000 00000001 00000000 80206c00 00000000 00000000 2e303100
[    0.040000] stack_dump: 0x80206a80: 00302e34 00000000 80004750 00000000 36360000 62323830 36646435 7269642d
[    0.040000] stack_dump: 0x80206aa0: 44207974 31206365 30322034 31203332 30353a33 0035343a 800088aa 00000000
[    0.040000] stack_dump: 0x80206ac0: 80208b70 73697200 00762d63 00000000 ffffffea ffffffff 8000a532 00000000
[    0.040000] stack_dump: 0x80206ae0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    0.040000] stack_dump: 0x80206b00: 00000000 00000000 00000000 00000000 00000000 00000000 80200f58 00000000
[    0.040000] stack_dump: 0x80206b20: 80201ecc 00000000 00000064 00000000 ffffffea ffffffff 80008656 00000000
[    0.040000] stack_dump: 0x80206b40: 00000c00 00000000 80001e1e 00000000 00000000 00000000 80016400 00000000
[    0.040000] stack_dump: 0x80206b60: 00000000 00000000 00000c00 00000000 00000000 00000000 80201ed0 00000000
[    0.040000] stack_dump: 0x80206b80: 80200f68 00000000 80001d76 00000000 80400000 00000000 00400000 00000000
[    0.040000] stack_dump: 0x80206ba0: 00000026 00000000 00000000 00000000 00000000 00000000 87000000 00000000
[    0.040000] stack_dump: 0x80206bc0: 00000000 00000000 80000ba8 00000000 00000000 00000000 80000c54 00000000
[    0.040000] stack_dump: 0x80206be0: 00000000 00000000 00000000 00000000 00000000 00000000 8000004c 00000000
[    0.040000] stack_dump: 0x80206c00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    0.040000] dump_tasks:    PID GROUP PRI POLICY   TYPE    NPX STATE   EVENT      SIGMASK          STACKBASE  STACKSIZE      USED   FILLED    COMMAND
[    0.040000] dump_tasks:   ----   --- --- -------- ------- --- ------- ---------- ---------------- 0x802002f0      3072      3064    99.7%!   irq
[    0.040000] dump_task:       0     0   0 FIFO     Kthread - Running            0000000000000000 0x80206010      3056      2112    69.1%    Idle_Task
[    0.040000] dump_task:       1     1 100 RR       Kthread - Waiting Unlock     0000000000000000 0x8020a050      1968       528    26.8%    lpwork 0x80201b80 0x80201bb0

Using goodaddr:

[    0.040000] up_relocateadd: PCREL_HI20 at c0000050 [00000697] to sym=0x80209520 st_value=13ffff7ff
[    0.041000] _calc_imm: offset=2147481519: hi=524287 lo=1967 off=7ffff7af
[    0.042000] up_relocateadd: RELAX at c0000050 [7ffff697]
[    0.042000] elf_read: Read 24 bytes from offset 201760
[    0.042000] elf_symvalue: Other: 00000050+c0000000=c0000050
[    0.043000] up_relocateadd: PCREL_LO12_I at c0000054 [00068693] to sym=0x80209560 st_value=c0000050
[    0.043000] _calc_imm: offset=2147481519: hi=524287 lo=1967 off=7ffff7af

Tested with rv-virt:knsh64, had to disable optimizations for main, as the compiler did not want to produce the erroneous code otherwise.

@xiaoxiang781216 xiaoxiang781216 merged commit 90d7315 into apache:master Dec 14, 2023
26 checks passed
@pussuw pussuw deleted the riscv_hi20_fix branch December 14, 2023 15:20
@jerpelea jerpelea added this to To-Add in Release Notes - 12.4.0 Dec 27, 2023
@jerpelea jerpelea moved this from To-Add to processed in Release Notes - 12.4.0 Jan 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

2 participants