This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
relative GOT relocs in gold
- From: David Miller <davem at davemloft dot net>
- To: binutils at sourceware dot org
- Cc: iant at google dot com
- Date: Fri, 04 Apr 2008 12:22:46 -0700 (PDT)
- Subject: relative GOT relocs in gold
Unlike other platforms, when there is a GOT reloc (f.e.
R_SPARC_GOT{10,13,22}) that results in emitting a R_SPARC_RELATIVE
relocation for the dynamic linker, the relocation doesn't go into the
GOT slot, it ends up in the R_SPARC_RELATIVE reloc's addend instead.
The GOT entry in this case is cleared to zero.
For the curious, the existing BFD bits that implement this are
in elfxx-sparc.c:_bfd_sparc_elf_relocate_section(), specifically
this block of code:
case R_SPARC_GOT10:
case R_SPARC_GOT13:
case R_SPARC_GOT22:
...
if (h != NULL)
{
...
}
else
{
BFD_ASSERT (local_got_offsets != NULL
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
off = local_got_offsets[r_symndx];
/* The offset must always be a multiple of 8 on 64-bit and
4 on 32-bit. We use the least significant bit to record
whether we have already processed this entry. */
if ((off & 1) != 0)
off &= ~1;
else
{
if (info->shared)
{
asection *s;
Elf_Internal_Rela outrel;
/* We need to generate a R_SPARC_RELATIVE reloc
for the dynamic linker. */
s = htab->srelgot;
BFD_ASSERT (s != NULL);
outrel.r_offset = (htab->sgot->output_section->vma
+ htab->sgot->output_offset
+ off);
outrel.r_info = SPARC_ELF_R_INFO (htab, NULL,
0, R_SPARC_RELATIVE);
outrel.r_addend = relocation;
relocation = 0;
sparc_elf_append_rela (output_bfd, s, &outrel);
}
SPARC_ELF_PUT_WORD (htab, output_bfd, relocation,
htab->sgot->contents + off);
local_got_offsets[r_symndx] |= 1;
}
}
relocation = htab->sgot->output_offset + off - got_base;
I can't see any easy way to implement this using the
current gold target infrastructure and interfaces.
If there is a nice way, please show me! :-)
Otherwise, my initial suggestion is that perhaps we should add a way
to point GOT entries at relocations, or parts of a relocation, and add
a new GOT type for that and assosciated ->write() methods.
Then I could register the GOT entry with ->add_local_with_rela()
or similar, and tell it "and BTW, put there gsym->value() in
this relocation addend over here instead of the GOT slot."
Alternatively, we could have a target fixup pass that can walk over
the dynamic relocs, and for this case the sparc target would
transfer the GOT slot values into the associated R_SPARC_RELATIVE
reloc addends, and clear the GOT slot.
Any better ideas?