Skip to content

Missing Linker Relaxation Relocations after Assembly Relaxation #150071

@lenary

Description

@lenary

The following example, when assembled with llvm-mc --triple=riscv32 -mattr=+relax,+experimental-xqcilb seems to have a bug:

.global foo

bar:
  jal x1, foo
  bne a0, a1, bar
  ret

Looking at the llvm-objdump -dr output (this has not been truncated)

jal.o:  file format elf32-littleriscv

Disassembly of section .text:

00000000 <bar>:
       0: c01f 0000 0000        qc.e.jal        0x0 <bar>
                        00000000:  R_RISCV_VENDOR       QUALCOMM
                        00000000:  R_RISCV_CUSTOM195    foo
                        00000000:  R_RISCV_RELAX        *ABS*
       6: feb51de3      bne     a0, a1, 0x0 <bar>
       a: 8082          ret

The bne is branching over a relaxable instruction, but has been resolved instead of having a relocation on it. This means that if the linker relaxes the qc.e.jal instruction, the bne will be incorrect.

I think the sequence of what is happening is:

  • jal x1, foo is parsed as JAL, as would be expected.
  • JAL is compressed to C_JAL in RISCVAsmParser::emitToStreamer
  • C_JAL is emitted, with a RISCV::fixup_riscv_rvc_jump fixup, which is not marked as linker relaxable.
  • C_JAL is jumping to an undefined symbol, so will be changed with relaxInstruction
  • relaxInstruction first relaxes to JAL and then the second time to QC_E_JAL
  • QC_E_JAL has a RISCV::fixup_riscv_qc_e_call_plt fixup, which is marked as linker relaxable!
  • nothing now marks the fragment and the section as linker relaxable.
  • When it comes time to apply the fixup to bne, I think RISCVAsmBackend::isPCRelFixupResolved is returning that the fixup is fully resolved, when it shouldn't be.

I think the relaxation of JAL to QC_E_JAL might be the only one we have right now which changes the fixup from being non-linker-relaxable to being linker-relaxable. (This is not going to be the case indefinitely, as there are now linker relaxations for R_RISCV_JAL, so the C_JAL to JAL relaxation will have the same bug once we update RISCVMCCodeEmitter::getImmOpValue for new relaxations in the psABI since we did this last time)

I think this is still violating invariants of the code, that fragments (and their parent sections) with linker relaxable fixups should be marked as linker relaxable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions