[llvm] Arm ropi rwpi dynreloc consts (PR #207931)

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 02:46:14 PDT 2026


smithp35 wrote:

Having mentioned that rewriting RO/RW would likely be clunky on Arm, I think it could be simpler than I thought. Both ROPI and RWPI are of the form:
* Load/Materialise an offset into a register (offset from PC for ROPI, offset from SB for RWPI).
* Add the register to the appropriate base register, PC for ROPI and SB for RWPI).
```
        movw    r0, :lower16:rw(sbrel) // R_ARM_MOVW_BREL_NC
        movt    r0, :upper16:rw(sbrel) // R_ARM_MOVT_BREL
        add     r0, r9, r0

        movw    r0, :lower16:(ro-(.LPC1_0+8)) // R_ARM_MOVW_PREL_NC
        movt    r0, :upper16:(ro-(.LPC1_0+8)) // R_ARM_MOVT_PREL
.LPC1_0:
        add     r0, pc, r0
```

A sketch of a static-link time rewriter could work:
* New relocation types BREL_OR_PREL for each of the existing BREL and PREL relocation types used by ROPI/RWPI. I don't think these are strictly necessary as I think it is possible to transform PREL into BREL (by ignoring the addend) but not vice-versa.
* The BREL_OR_PREL instructions would have the  PREL addend, which would be interpreted as 0 when operating as BREL.
* New relocations that identify instructions that use either PC or SB with a register offset. This will need to be limited to a small number of instructions, ideally just add with ldr/str using a base register such as `ldr r0, [r9, r0]` and `ldr r0, [pc, r0]`. The linker would rewrite with the appropriate base-register depending on whether the destination is RO or RW.

I'm not advocating for a rewriter, just recording that I think it is possible on ARM without large amounts of linker work.

https://github.com/llvm/llvm-project/pull/207931


More information about the llvm-commits mailing list