inconsistencies if (at least) ELF relocation handling

Michael Matz matz@suse.de
Wed May 5 13:36:33 GMT 2021


Hello,

On Wed, 5 May 2021, Jan Beulich wrote:

> > 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.
> 
> And what do you suggest R_X86_64_32 is? Signed? Unsigned? In

Unsigned, which is why X86_64_32S exists.  That was the intention at 
least.  Obviously as binutils didn't carefully check for overflows in 
either interpretation I'm sure there is now inconsistency in the wild.  
And that inconsistency might even go so far as to point out that the 
initial intention in the ABI was unsustainable, and that it needs to be 
signed _and_ unsigned, like ...

>     mov     $val, %eax
> 
> you can't infer the signedness of val. Granted R_X86_64_32 may not
> be an ideal example, as there's also R_X86_64_32S. Yet for the
> example above the assembler can't know which of the two to pick if
> R_X86_64_32 was strictly unsigned.

... here.  But actually I think the assembler can pick one, it needs to be 
consistent with the instruction it chooses to implement above mnemonic.  
The above mov does a zero extension to the full 64bit word width, which is 
consistent with choosing X86_64_32 when it's strictly unsigned.

An instruction like

      sub     $val, %rax

would use 32S.  What an instruction "sub $val, %eax" would choose: hmm ;-)
I think here we really would need to accept signed and unsigned 32bit 
values.

> Hence I would think R_X86_64_32S needs to be treated as strictly signed, 

I agree.

> but R_X86_64_32 should allow for the full range of signed and unsigned 
> 32-bit values (i.e. complain_overflow_bitfield), contrary to what the 
> psABI currently says.

I'm not sure here.  I would wish for it to be treated as strictly 
unsigned, but it's quite possible that this won't work (and I'm quite sure 
it _currently_ would cause regressions).  Certainly accepting values in
[-2^31, 2^32) seems like the conservative or only possible approach.

> Interestingly these two relocations are the only ones where the psABI 
> talks about sign-/zero-extension, i.e. the "signedness" of a relocation 
> type.

I came a year too late to know the full history how that came to be (the 
32S reloc was added in September 2000).  I'm guessing that reviewing the 
initial x86-64 instruction set it was noticed that "sometimes 32bit 
numbers are sign- and sometimes zero-extended before submitted to the 
arithmetic unit" and "therefore we need two relocation types for 
appropriate checking".  Why that unsigned/signed checking wasn't deemed 
necessary for other relocs, or was deemed necessary here, I don't know.  
Probably bugs occurred during bringup, and one of them was "oh, if the 
linker would have warned here, we wouldn't have run into this strange 
segfault".  As the short relocs aren't really used in code no bugs 
occurred there, so no stricter checking was done.


Ciao,
Michael.


More information about the Binutils mailing list