bfd relocation handling questions

Jan Beulich jbeulich@suse.com
Wed Apr 7 08:50:18 GMT 2021


On 07.04.2021 04:36, Alan Modra wrote:
> On Tue, Apr 06, 2021 at 09:22:22AM +0200, Jan Beulich wrote:
>> initially I only meant to look into making x86's @size also work when
>> the final link produces non-ELF output from ELF object files. But I
>> ran into more general issues, which I'd like to gain some understanding
>> on first. While my looking into this was x86 focused, I expect there's
>> on little x86-specific-ness there.
>>
>> It looks to me as if not only the x86 assembler (I'll bring this up as
>> a separate topic, perhaps by way of proposing one or more patches) but
>> many parts of binutils behave differently for 32-bit targets depending
>> on whether the bfd build is a BFD64 one. There are a few comments
>> indicating that overflow checking would actually require a wider type
>> for the calculations to be done in, but architectures where addresses
>> wrap (x86, x86-64) would presumably not want such overflows to be
>> detected anyway when the relocated item is a full-address-width one.
>> IOW I suspect that for x86 a BFD64 build would report overflows that
>> it shouldn't report.
>>
>> This is (I think) closely connected to the use of complain_overflow_*
>> in the howto entries.
> 
> Yes.
> 
>> Is there much sense in marking full-address-
>> width relocations as complain_overflow_unsigned or
>> complain_overflow_bitfield? Besides the BFD64 and wrapping aspects
>> above, these two overflow checking variants are effectively a more
>> involved way of complain_overflow_dont as long as all arithmetic is
>> done with bfd_vma values. Is their use, when an architecture does not
>> wrap addresses (if any such exists in the first place), purely for
>> documentation purposes?
> 
> A lot of BFD is quickly hacked together code copied from somewhere
> with minimal editing until "it worked".  Relocation howtos are
> particular bad since a lot of targets only use the entire howto when
> producing foreign output, and quite a few disable foreign output
> entirely (eg. "ld --oformat srec" gives an error on arm, aarch64,
> avr).
> 
> So I wouldn't presume that complain_overflow_* was "documenting"
> anything.  It's far more likely that someone copied the howto from
> some other reloc and didn't update to complain_overflow_dont.

IOW changing some of them would likely be a plausible thing to do.

What I'm missing though is some clarification on the differing
behavior for 32-bit targets in BFD64 vs non-BFD64 builds. Is this
intentional? Or does this again just "happen to be that way"?
(As an aside, with the move to C99 I think it would at least be
an option to force BFD64 builds uniformly.)

H.J. - any thoughts here towards intended new behavior for x86
in particular? Would you see a reason to keep any of the full-width
relocations using anything else than "dont"? Plus ...

>> Things get even more "interesting" when e.g. seeing that
>> R_X86_64_{8,16,64} all use complain_overflow_bitfield, but R_X86_64_32
>> uses complain_overflow_unsigned (with a special case for x32). (Similar
>> asymmetries exist between R_X86_64_PC{16,64} and R_X86_64_PC{8,32} as
>> well as R_386_PC8 vs R_386_PC{16,32}.) Are there any reasons for such
>> inconsistencies? (Of course R_*_PC16 are bogus anyway in 32- and 64-
>> bit objects, as with the exception of XBEGIN branches with operand
>> size overrides truncate %eip / %rip after adding the displacement, i.e.
>> the intended address will be branched to only if the respective code
>> gets placed in the low 64k of memory. IOW these aren't truly PC-relative
>> relocations in these cases. As a result I believe in these cases the
>> relocations ought to be retained in the final binary, so the dynamic
>> linker can [typically] properly complain.)

... making things at least consistent here?

>> Further, in the context of discussing what is now commit 2dfa8341e079
>> ("ELF DWARF in PE output") I was left with the impression that by
>> placing the new logic in bfd_elf_generic_reloc(), ELF output would be
>> similarly benefiting from that change. Maybe that's indeed the case
>> for debug info sections, and I simply misunderstood that the same
>> doesn't hold for "normal" sections?
> 
> ELF targets will be affected by the bfd_elf_generic_reloc change only
> in debug sections, but not if the target's relocate_section handles
> applying the relocation itself.  (I haven't checked if there are
> targets that avoid calling _bfd_final_link_relocate for debug relocs,
> but there migh be some.)

Thanks for confirming - I indeed didn't understand correctly what
you said on the earlier thread then.

>> Afaict for those
>> bfd_perform_relocation() (and hence the ->special_function hook)
>> would never be called (which is why my original attempt of placing
>> respective adjustments there wasn't a good one). This is quite
>> relevant to deal with the @size originating relocations on x86 -
>> initially I was hoping to handle these centrally in one place instead
>> of introducing new code besides the one already in elf32-i386.c and
>> elf64-x86_64.c.
>>
>> And finally I stumbled across bfd_check_overflow() doing more
>> exhaustive checking than _bfd_relocate_contents(). Wouldn't the latter
>> benefit from also doing the more thorough checks? I.e. wouldn't it
>> perhaps even better call the former, at once eliminating code
>> duplication there?
> 
> I think it's the other way around.  _bfd_relocate_contents picks up
> some overflows of bfd_vma sized relocations that bfd_check_overflow
> won't.  See the comment in bfd_perform_relocation where
> bfd_check_overflow is called.

Oh, indeed I got this the wrong way round. But is there a reason for
bfd_check_overflow() to be more relaxed? I.e. wouldn't it make sense
for the more thorough checking to me moved there, and for
_bfd_relocate_contents() to then call it?

Jan


More information about the Binutils mailing list