2009-06-03 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_allocate_dynrelocs): Allocate GOT entry for STT_GNU_IFUNC symbol with pointer equality. (elf_i386_relocate_section): Adjust R_386_GOT32 relocation against STT_GNU_IFUNC symbols for static executables. (elf_i386_finish_dynamic_symbol): Load GOT entry with PLT entry for STT_GNU_IFUNC symbol with pointer equality. * elf64-x86-64.c (elf64_x86_64_allocate_dynrelocs): Allocate GOT entry for STT_GNU_IFUNC symbol with pointer equality. (elf64_x86_64_finish_dynamic_symbol): Load GOT entry with PLT entry for STT_GNU_IFUNC symbol with pointer equality.
This commit is contained in:
parent
b517c9b616
commit
0018b0a3d5
|
@ -1,3 +1,17 @@
|
|||
2009-06-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf32-i386.c (elf_i386_allocate_dynrelocs): Allocate
|
||||
GOT entry for STT_GNU_IFUNC symbol with pointer equality.
|
||||
(elf_i386_relocate_section): Adjust R_386_GOT32 relocation
|
||||
against STT_GNU_IFUNC symbols for static executables.
|
||||
(elf_i386_finish_dynamic_symbol): Load GOT entry with
|
||||
PLT entry for STT_GNU_IFUNC symbol with pointer equality.
|
||||
|
||||
* elf64-x86-64.c (elf64_x86_64_allocate_dynrelocs): Allocate
|
||||
GOT entry for STT_GNU_IFUNC symbol with pointer equality.
|
||||
(elf64_x86_64_finish_dynamic_symbol): Load GOT entry with
|
||||
PLT entry for STT_GNU_IFUNC symbol with pointer equality.
|
||||
|
||||
2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
|
||||
|
||||
* coff-rs6000.c (xcoff_ppc_relocate_section): Allow undefined
|
||||
|
|
|
@ -2003,10 +2003,26 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
/* STT_GNU_IFUNC symbol uses .got.plt, not .got. But for
|
||||
shared library, we must go through GOT and we can't
|
||||
use R_386_IRELATIVE unless it is forced local. */
|
||||
if (!info->shared
|
||||
if (info->executable
|
||||
|| info->symbolic
|
||||
|| h->forced_local)
|
||||
h->got.refcount = 0;
|
||||
{
|
||||
if (h->pointer_equality_needed
|
||||
&& htab->sgot != NULL)
|
||||
{
|
||||
/* We can't use .got.plt, which contains the real
|
||||
function addres, since we need pointer equality.
|
||||
We will load the GOT entry with the PLT entry
|
||||
in elf_i386_finish_dynamic_symbol and don't
|
||||
need GOT relocation. */
|
||||
h->got.offset = htab->sgot->size;
|
||||
htab->sgot->size += 4;
|
||||
eh->tlsdesc_got = (bfd_vma) -1;
|
||||
goto skip_relgot;
|
||||
}
|
||||
else
|
||||
h->got.refcount = 0;
|
||||
}
|
||||
}
|
||||
else if (htab->elf.dynamic_sections_created
|
||||
&& h->plt.refcount > 0)
|
||||
|
@ -2153,6 +2169,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
else
|
||||
h->got.offset = (bfd_vma) -1;
|
||||
|
||||
skip_relgot:
|
||||
if (eh->dyn_relocs == NULL)
|
||||
return TRUE;
|
||||
|
||||
|
@ -2966,11 +2983,16 @@ elf_i386_relocate_section (bfd *output_bfd,
|
|||
relocation += gotplt->output_offset;
|
||||
}
|
||||
else
|
||||
relocation = (base_got->output_section->vma
|
||||
+ base_got->output_offset + off
|
||||
- gotplt->output_section->vma
|
||||
- gotplt->output_offset);
|
||||
|
||||
{
|
||||
relocation = (base_got->output_section->vma
|
||||
+ base_got->output_offset + off
|
||||
- gotplt->output_section->vma
|
||||
- gotplt->output_offset);
|
||||
/* Adjust for static executables. */
|
||||
if (htab->splt == NULL)
|
||||
relocation += gotplt->output_offset;
|
||||
}
|
||||
|
||||
goto do_relocation;
|
||||
|
||||
case R_386_GOTOFF:
|
||||
|
@ -4113,8 +4135,28 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
|
|||
of a version file, we just want to emit a RELATIVE reloc.
|
||||
The entry in the global offset table will already have been
|
||||
initialized in the relocate_section function. */
|
||||
if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if ((info->executable
|
||||
|| info->symbolic
|
||||
|| h->forced_local)
|
||||
&& h->def_regular
|
||||
&& h->pointer_equality_needed
|
||||
&& h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
/* The STT_GNU_IFUNC symbol is locally defined. But we can't
|
||||
use .got.plt, which contains the real function addres,
|
||||
since we need pointer equality. We load the GOT entry
|
||||
with the PLT entry without relocation. */
|
||||
asection *plt = htab->splt ? htab->splt : htab->iplt;
|
||||
if (htab->sgot == NULL
|
||||
|| h->plt.offset == (bfd_vma) -1)
|
||||
abort ();
|
||||
bfd_put_32 (output_bfd, (plt->output_section->vma
|
||||
+ plt->output_offset + h->plt.offset),
|
||||
htab->sgot->contents + h->got.offset);
|
||||
return TRUE;
|
||||
}
|
||||
else if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
{
|
||||
BFD_ASSERT((h->got.offset & 1) != 0);
|
||||
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
||||
|
|
|
@ -1841,10 +1841,26 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
|
|||
/* STT_GNU_IFUNC symbol uses .got.plt, not .got. But for
|
||||
shared library, we must go through GOT and we can't
|
||||
use R_X86_64_IRELATIVE unless it is forced local. */
|
||||
if (!info->shared
|
||||
if (info->executable
|
||||
|| info->symbolic
|
||||
|| h->forced_local)
|
||||
h->got.refcount = 0;
|
||||
{
|
||||
if (h->pointer_equality_needed
|
||||
&& htab->sgot != NULL)
|
||||
{
|
||||
/* We can't use .got.plt, which contains the real
|
||||
function addres, since we need pointer equality.
|
||||
We will load the GOT entry with the PLT entry
|
||||
in elf64_x86_64_finish_dynamic_symbol and don't
|
||||
need GOT relocation. */
|
||||
h->got.offset = htab->sgot->size;
|
||||
htab->sgot->size += GOT_ENTRY_SIZE;
|
||||
eh->tlsdesc_got = (bfd_vma) -1;
|
||||
goto skip_relgot;
|
||||
}
|
||||
else
|
||||
h->got.refcount = 0;
|
||||
}
|
||||
}
|
||||
else if (htab->elf.dynamic_sections_created
|
||||
&& h->plt.refcount > 0)
|
||||
|
@ -1971,6 +1987,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
|
|||
else
|
||||
h->got.offset = (bfd_vma) -1;
|
||||
|
||||
skip_relgot:
|
||||
if (eh->dyn_relocs == NULL)
|
||||
return TRUE;
|
||||
|
||||
|
@ -3727,8 +3744,28 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
|
|||
of a version file, we just want to emit a RELATIVE reloc.
|
||||
The entry in the global offset table will already have been
|
||||
initialized in the relocate_section function. */
|
||||
if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if ((info->executable
|
||||
|| info->symbolic
|
||||
|| h->forced_local)
|
||||
&& h->def_regular
|
||||
&& h->pointer_equality_needed
|
||||
&& h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
/* The STT_GNU_IFUNC symbol is locally defined. But we can't
|
||||
use .got.plt, which contains the real function addres,
|
||||
since we need pointer equality. We load the GOT entry
|
||||
with the PLT entry without relocation. */
|
||||
asection *plt = htab->splt ? htab->splt : htab->iplt;
|
||||
if (htab->sgot == NULL
|
||||
|| h->plt.offset == (bfd_vma) -1)
|
||||
abort ();
|
||||
bfd_put_64 (output_bfd, (plt->output_section->vma
|
||||
+ plt->output_offset + h->plt.offset),
|
||||
htab->sgot->contents + h->got.offset);
|
||||
return TRUE;
|
||||
}
|
||||
else if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
{
|
||||
if (!h->def_regular)
|
||||
return FALSE;
|
||||
|
|
Loading…
Reference in New Issue