bfd relocation handling questions

Jan Beulich jbeulich@suse.com
Tue Apr 6 07:22:22 GMT 2021


Hello,

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. 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?

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.)

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? 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?

Thanks much for any insights,
Jan


More information about the Binutils mailing list