inconsistencies if (at least) ELF relocation handling

Michael Matz
Tue May 4 15:19:48 GMT 2021


On Tue, 4 May 2021, Jan Beulich via Binutils wrote:

> > Yes, the point of RELA relocations was to move addends out of the
> > section contents into the relocation.  So src_mask should generally be
> > zero for RELA.  The ELF gABI wording under "Relocation" supports this
> > too, talking about addends being "either from the field to be
> > relocated or from the addend field contained in the relocation
> > record".  It doesn't say "and/or".  However, when a target applies
> > multiple relocations to the same r_offset where the addend
> > accumulates, a target might accumulate such addends in the section
> > contents.  (Which isn't exactly correct, the accumulation ought to be
> > done at full word width not the width of the field.)  Such relocs
> > might need src_mask equal to dst_mask.
> But such multiple relocations to the same r_offset are spec compliant
> only with REL, not with RELA, as per my understanding.

Even if the gABI would say so, that would be surprising; there's no reason 
for such restriction.  But the gABI doesn't say so, it calls such 
relocations "composed" and specifies how the calculations proceeds:

If multiple consecutive relocation records are applied to the same 
relocation location (r_offset), they are composed instead of being applied 
independently, as described above. By consecutive, we mean that the 
relocation records are contiguous within a single relocation section. By 
composed, we mean that the standard application described above is 
modified as follows:

In all but the last relocation operation of a composed sequence, the 
result of the relocation expression is retained, rather than having part 
extracted and placed in the relocated field. The result is retained at 
full pointer precision of the applicable ABI processor supplement.
In all but the first relocation operation of a composed sequence, the 
addend used is the retained result of the previous relocation operation, 
rather than that implied by the relocation type.

So, accumulation in full-word width, addend only matters for the first of 
a sequence of consecutive composed relocs.

Obviously the reality for specific psABIs might be different from that 
ideal, but it seems a sensible model.

> (Whether accumulation is okay to happen at less than full width imo 
> depends on whether intermediate values will be okay to be rejected when 
> overflowing, even if the final value would fit.)

See above.

> Perhaps then have a "compliant" mode which targets can opt-in to (long 
> term this might then become an opt-out)?
> >> As to the breakage on x86-64, I observe a number of "relocation 
> >> truncated to fit: R_X86_64_32 against `.debug_str'", due to negative 
> >> addends getting truncated to 32-bit unsigned values and this reloc 
> >> using complain_overflow_unsigned. In ELF it is my understanding that 
> >> addends - no matter what their origin - are always signed.
> > 
> > The ELF gABI does tend to give that idea by specifying r_addend as 
> > signed, but I believe there are relocations that only allow positive 
> > addends.  Processor ABIs are free to specify relocations like that..
> Interesting. I would assume such targets then ought to handle such 
> "non-standard" (I'm inclined to even say "non-conforming") relocations 
> locally, rather than requiring generic code to cover for this (and break 
> other targets)?

As calculations are word-width and r_addend is always word-width,
why would its signedness matter?  The same bit pattern results, which then 
needs to be interpreted according to the meaning of the relocation.  The 
value V is basically an word, and if it's a signed 32bit reloc, then
  V == (word)(int32_t)(uint32_t)V
needs to hold, and if it's a unsigned 32bit reloc then
  V == (word)(uint32_t)V
needs to hold.

For REL ABIs the signedness of addend does matter of course for how to 
extract A from the relocated fields, but eventually you arrive at a 
word-width A, at which point signedness again doesn't matter.

> Of course otoh I'm unconvinced R_X86_64_32 using 
> complain_overflow_unsigned is correct either. Imo it ought to be 
> complain_overflow_bitfield.


More information about the Binutils mailing list