PowerPC64 GOT_PCREL relocs
authorAlan Modra <amodra@gmail.com>
Thu, 5 Sep 2019 00:36:42 +0000 (10:06 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 5 Sep 2019 05:55:51 +0000 (15:25 +0930)
commit133a1f6041bc131afcb39bf1a124d8e0fc5547ea
tree0a27fae679a00e5d4c12655f38c05124eaf6253f
parent77486630b13e9e586b0a1556cba9876a0ede99da
PowerPC64 GOT_PCREL relocs

PC-relative relocs typically use the addend in adjusting what they are
relative to.  For example:
bcl 20,31,1f
1: mflr 12
addi 12,12,xxx-1b
generates "R_PPC64_REL16 xxx+0x4" for the addi (when little-endian).
The addend reflects the fact that you want the offset relative to the
previous insn not the current one in this case.

So the question is, will we ever want to do something like that for an
instruction using R_PPC64_GOT_PCREL34?  I thought so at the time I
first implemented support in ld but at the time I think the hardware
was possibly going to support pcrel+offset+reg addressing.  In which
case you might want something like:
load_big_offset_into_r2
pld 3,sym-big_offset@got@pcrel(2)
which would be a way of supporting more than 8G offsets from code to
the GOT.  We could do the same with
load_big_offset_into_r2
pla 9,sym-big_offset@got@pcrel
ldx 3,9,2
However, this is really a poor version of TOC-pointer relative code.

So let's go with an addend on R_PPC64_GOT_PCREL34 meaning that
sym+addend should be put in a GOT entry, and the relocation calculate
the pc-relative offset to that GOT entry.

Note that this is an extension to the ABI, which says (by the
expression given for GOT relocs) that non-zero addends on GOT and PLT
relocs are ignored.  This is true for all GOT/PLT relocs, not just the
pcrel ones.

* elf64-ppc.c (ppc64_elf_check_relocs): Interpret an addend in
GOT_PCREL and PLT_PCREL relocs as affecting the value stored
in the GOT/PLT entry rather than affecting the offset to that
GOI/PLT entry.
(ppc64_elf_edit_toc, ppc64_elf_relocate_section): Likewise.
bfd/ChangeLog
bfd/elf64-ppc.c