bfd/
2009-06-06 H.J. Lu <hongjiu.lu@intel.com> * elf32-i386.c (elf_i386_link_hash_table): Add irelifunc. (elf_i386_link_hash_table_create): Initialize irelifunc. (elf_i386_check_relocs): Updated. Set up irelifunc for shared objects. (elf_i386_allocate_dynrelocs): Use irelifunc for dynamic relocation for non-GOT reference of STT_GNU_IFUNC symbol in shared objects. (elf_i386_relocate_section): Likewise. * elf64-x86-64.c (elf64_x86_64_link_hash_table): Add irelifunc. (elf64_x86_64_link_hash_table_create): Initialize irelifunc. (elf64_x86_64_check_relocs): Updated. Set up irelifunc for shared objects. (elf64_x86_64_allocate_dynrelocs): Use irelifunc for dynamic relocation for non-GOT reference of STT_GNU_IFUNC symbol in shared objects. (elf64_x86_64_relocate_section): Likewise. * elf-bfd.h (_bfd_elf_create_static_ifunc_sections): Renamed to ... (_bfd_elf_create_ifunc_sections): This. * elflink.c (_bfd_elf_create_static_ifunc_sections): Renamd to ... (_bfd_elf_create_ifunc_sections): This. Create .rel[a].ifunc for shared objects. ld/ 2009-06-06 H.J. Lu <hongjiu.lu@intel.com> * scripttempl/elf.sc: Add .rel.ifunc and .rela.ifunc.
This commit is contained in:
parent
0e7c7f11f4
commit
2a81c24ab1
@ -1,3 +1,32 @@
|
||||
2009-06-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf32-i386.c (elf_i386_link_hash_table): Add irelifunc.
|
||||
(elf_i386_link_hash_table_create): Initialize irelifunc.
|
||||
(elf_i386_check_relocs): Updated. Set up irelifunc for
|
||||
shared objects.
|
||||
(elf_i386_allocate_dynrelocs): Use irelifunc for dynamic
|
||||
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
|
||||
shared objects.
|
||||
(elf_i386_relocate_section): Likewise.
|
||||
|
||||
* elf64-x86-64.c (elf64_x86_64_link_hash_table): Add irelifunc.
|
||||
(elf64_x86_64_link_hash_table_create): Initialize irelifunc.
|
||||
(elf64_x86_64_check_relocs): Updated. Set up irelifunc for
|
||||
shared objects.
|
||||
(elf64_x86_64_allocate_dynrelocs): Use irelifunc for dynamic
|
||||
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
|
||||
shared objects.
|
||||
(elf64_x86_64_relocate_section): Likewise.
|
||||
|
||||
* elf-bfd.h (_bfd_elf_create_static_ifunc_sections): Renamed to
|
||||
...
|
||||
(_bfd_elf_create_ifunc_sections): This.
|
||||
|
||||
* elflink.c (_bfd_elf_create_static_ifunc_sections): Renamd to
|
||||
...
|
||||
(_bfd_elf_create_ifunc_sections): This. Create .rel[a].ifunc
|
||||
for shared objects.
|
||||
|
||||
2009-06-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf32-i386.c (elf_i386_check_relocs): Make room for dynamic
|
||||
|
@ -2146,7 +2146,7 @@ extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int);
|
||||
extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
|
||||
extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
|
||||
|
||||
extern bfd_boolean _bfd_elf_create_static_ifunc_sections
|
||||
extern bfd_boolean _bfd_elf_create_ifunc_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
||||
/* Large common section. */
|
||||
|
@ -678,6 +678,7 @@ struct elf_i386_link_hash_table
|
||||
asection *igotplt;
|
||||
asection *iplt;
|
||||
asection *irelplt;
|
||||
asection *irelifunc;
|
||||
|
||||
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
|
||||
asection *srelplt2;
|
||||
@ -777,6 +778,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
|
||||
ret->igotplt= NULL;
|
||||
ret->iplt = NULL;
|
||||
ret->irelplt= NULL;
|
||||
ret->irelifunc = NULL;
|
||||
ret->tls_ldm_got.refcount = 0;
|
||||
ret->next_tls_desc_index = 0;
|
||||
ret->sgotplt_jump_table_size = 0;
|
||||
@ -1279,21 +1281,30 @@ elf_i386_check_relocs (bfd *abfd,
|
||||
case R_386_PLT32:
|
||||
case R_386_GOT32:
|
||||
case R_386_GOTOFF:
|
||||
if (!info->shared && htab->iplt == NULL)
|
||||
if (htab->irelifunc == NULL && htab->iplt == NULL)
|
||||
{
|
||||
if (!_bfd_elf_create_static_ifunc_sections (abfd,
|
||||
info))
|
||||
if (!_bfd_elf_create_ifunc_sections (abfd, info))
|
||||
return FALSE;
|
||||
|
||||
htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
|
||||
htab->irelplt = bfd_get_section_by_name (abfd,
|
||||
".rel.iplt");
|
||||
htab->igotplt = bfd_get_section_by_name (abfd,
|
||||
".igot.plt");
|
||||
if (!htab->iplt
|
||||
|| !htab->irelplt
|
||||
|| !htab->igotplt)
|
||||
abort ();
|
||||
if (info->shared)
|
||||
{
|
||||
htab->irelifunc = bfd_get_section_by_name (abfd,
|
||||
".rel.ifunc");
|
||||
if (!htab->irelifunc)
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
|
||||
htab->irelplt = bfd_get_section_by_name (abfd,
|
||||
".rel.iplt");
|
||||
htab->igotplt = bfd_get_section_by_name (abfd,
|
||||
".igot.plt");
|
||||
if (!htab->iplt
|
||||
|| !htab->irelplt
|
||||
|| !htab->igotplt)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2038,10 +2049,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
||||
|
||||
/* Finally, allocate space. */
|
||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||
{
|
||||
asection * sreloc = elf_section_data (p->sec)->sreloc;
|
||||
sreloc->size += p->count * sizeof (Elf32_External_Rel);
|
||||
}
|
||||
htab->irelifunc->size += p->count * sizeof (Elf32_External_Rel);
|
||||
|
||||
/* For STT_GNU_IFUNC symbol, .got.plt has the real function
|
||||
addres and .got has the PLT entry adddress. We will load
|
||||
@ -3010,7 +3018,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|
||||
else
|
||||
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
|
||||
|
||||
sreloc = elf_section_data (input_section)->sreloc;
|
||||
sreloc = htab->irelifunc;
|
||||
loc = sreloc->contents;
|
||||
loc += (sreloc->reloc_count++
|
||||
* sizeof (Elf32_External_Rel));
|
||||
|
@ -496,6 +496,7 @@ struct elf64_x86_64_link_hash_table
|
||||
asection *igotplt;
|
||||
asection *iplt;
|
||||
asection *irelplt;
|
||||
asection *irelifunc;
|
||||
|
||||
/* The offset into splt of the PLT entry for the TLS descriptor
|
||||
resolver. Special values are 0, if not necessary (or not found
|
||||
@ -591,6 +592,7 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
|
||||
ret->igotplt= NULL;
|
||||
ret->iplt = NULL;
|
||||
ret->irelplt= NULL;
|
||||
ret->irelifunc = NULL;
|
||||
ret->sym_sec.abfd = NULL;
|
||||
ret->tlsdesc_plt = 0;
|
||||
ret->tlsdesc_got = 0;
|
||||
@ -1065,21 +1067,30 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
case R_X86_64_PLT32:
|
||||
case R_X86_64_GOTPCREL:
|
||||
case R_X86_64_GOTPCREL64:
|
||||
if (!info->shared && htab->iplt == NULL)
|
||||
if (htab->irelifunc == NULL && htab->iplt == NULL)
|
||||
{
|
||||
if (!_bfd_elf_create_static_ifunc_sections (abfd,
|
||||
info))
|
||||
if (!_bfd_elf_create_ifunc_sections (abfd, info))
|
||||
return FALSE;
|
||||
|
||||
htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
|
||||
htab->irelplt = bfd_get_section_by_name (abfd,
|
||||
".rela.iplt");
|
||||
htab->igotplt = bfd_get_section_by_name (abfd,
|
||||
".igot.plt");
|
||||
if (!htab->iplt
|
||||
|| !htab->irelplt
|
||||
|| !htab->igotplt)
|
||||
abort ();
|
||||
if (info->shared)
|
||||
{
|
||||
htab->irelifunc = bfd_get_section_by_name (abfd,
|
||||
".rela.ifunc");
|
||||
if (!htab->irelifunc)
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
|
||||
htab->irelplt = bfd_get_section_by_name (abfd,
|
||||
".rela.iplt");
|
||||
htab->igotplt = bfd_get_section_by_name (abfd,
|
||||
".igot.plt");
|
||||
if (!htab->iplt
|
||||
|| !htab->irelplt
|
||||
|| !htab->igotplt)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1880,10 +1891,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
|
||||
|
||||
/* Finally, allocate space. */
|
||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||
{
|
||||
asection * sreloc = elf_section_data (p->sec)->sreloc;
|
||||
sreloc->size += p->count * sizeof (Elf64_External_Rela);
|
||||
}
|
||||
htab->irelifunc->size += p->count * sizeof (Elf64_External_Rela);
|
||||
|
||||
/* For STT_GNU_IFUNC symbol, .got.plt has the real function
|
||||
addres and .got has the PLT entry adddress. We will load
|
||||
@ -2730,7 +2738,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
||||
outrel.r_addend = 0;
|
||||
}
|
||||
|
||||
sreloc = elf_section_data (input_section)->sreloc;
|
||||
sreloc = htab->irelifunc;
|
||||
loc = sreloc->contents;
|
||||
loc += (sreloc->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
|
107
bfd/elflink.c
107
bfd/elflink.c
@ -12492,31 +12492,17 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec,
|
||||
return reloc_sec;
|
||||
}
|
||||
|
||||
/* Create sections needed by STT_GNU_IFUNC symbol for static
|
||||
executables. */
|
||||
/* Create sections needed by STT_GNU_IFUNC symbol. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_create_static_ifunc_sections (bfd *abfd,
|
||||
struct bfd_link_info *info)
|
||||
_bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
flagword flags, pltflags;
|
||||
int ptralign;
|
||||
asection *s;
|
||||
const struct elf_backend_data *bed;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
|
||||
/* Should never be called for shared library. */
|
||||
BFD_ASSERT (!info->shared);
|
||||
|
||||
/* This function may be called more than once. */
|
||||
s = bfd_get_section_by_name (abfd, ".iplt");
|
||||
if (s != NULL)
|
||||
return TRUE;
|
||||
|
||||
bed = get_elf_backend_data (abfd);
|
||||
|
||||
/* We need to create .iplt, .rel[a].iplt, .igot, .igot.plt, */
|
||||
flags = bed->dynamic_sec_flags;
|
||||
|
||||
pltflags = flags;
|
||||
if (bed->plt_not_loaded)
|
||||
/* We do not clear SEC_ALLOC here because we still want the OS to
|
||||
@ -12528,47 +12514,68 @@ _bfd_elf_create_static_ifunc_sections (bfd *abfd,
|
||||
if (bed->plt_readonly)
|
||||
pltflags |= SEC_READONLY;
|
||||
|
||||
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
|
||||
return FALSE;
|
||||
|
||||
s = bfd_make_section_with_flags (abfd,
|
||||
(bed->rela_plts_and_copies_p
|
||||
? ".rela.iplt" : ".rel.iplt"),
|
||||
flags | SEC_READONLY);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
|
||||
return FALSE;
|
||||
|
||||
switch (bed->s->arch_size)
|
||||
if (info->shared)
|
||||
{
|
||||
case 32:
|
||||
ptralign = 2;
|
||||
break;
|
||||
/* We need to create .rel[a].ifunc for shared objects. */
|
||||
const char *rel_sec = (bed->rela_plts_and_copies_p
|
||||
? ".rela.ifunc" : ".rel.ifunc");
|
||||
|
||||
case 64:
|
||||
ptralign = 3;
|
||||
break;
|
||||
/* This function should be called only once. */
|
||||
s = bfd_get_section_by_name (abfd, rel_sec);
|
||||
if (s != NULL)
|
||||
abort ();
|
||||
|
||||
default:
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* We don't need the .igot section if we have the .igot.plt
|
||||
section. */
|
||||
|
||||
if (bed->want_got_plt)
|
||||
{
|
||||
s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
|
||||
s = bfd_make_section_with_flags (abfd, rel_sec,
|
||||
flags | SEC_READONLY);
|
||||
if (s == NULL
|
||||
|| !bfd_set_section_alignment (abfd, s, ptralign))
|
||||
|| ! bfd_set_section_alignment (abfd, s,
|
||||
bed->s->log_file_align))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = bfd_make_section_with_flags (abfd, ".igot", flags);
|
||||
/* This function should be called only once. */
|
||||
s = bfd_get_section_by_name (abfd, ".iplt");
|
||||
if (s != NULL)
|
||||
abort ();
|
||||
|
||||
/* We need to create .iplt, .rel[a].iplt, .igot and .igot.plt
|
||||
for static executables. */
|
||||
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
|
||||
return FALSE;
|
||||
|
||||
s = bfd_make_section_with_flags (abfd,
|
||||
(bed->rela_plts_and_copies_p
|
||||
? ".rela.iplt" : ".rel.iplt"),
|
||||
flags | SEC_READONLY);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s,
|
||||
bed->s->log_file_align))
|
||||
return FALSE;
|
||||
|
||||
switch (bed->s->arch_size)
|
||||
{
|
||||
case 32:
|
||||
ptralign = 2;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
ptralign = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* We don't need the .igot section if we have the .igot.plt
|
||||
section. */
|
||||
if (bed->want_got_plt)
|
||||
s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
|
||||
else
|
||||
s = bfd_make_section_with_flags (abfd, ".igot", flags);
|
||||
if (s == NULL
|
||||
|| !bfd_set_section_alignment (abfd, s, ptralign))
|
||||
return FALSE;
|
||||
|
@ -1,3 +1,7 @@
|
||||
2009-06-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* scripttempl/elf.sc: Add .rel.ifunc and .rela.ifunc.
|
||||
|
||||
2009-06-05 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* scripttempl/elf.sc: Remove .rel.ifunc.dyn and .rela.ifunc.dyn.
|
||||
|
@ -326,6 +326,8 @@ eval $COMBRELOCCAT <<EOF
|
||||
.rel.bss ${RELOCATING-0} : { *(.rel.bss${RELOCATING+ .rel.bss.* .rel.gnu.linkonce.b.*}) }
|
||||
.rela.bss ${RELOCATING-0} : { *(.rela.bss${RELOCATING+ .rela.bss.* .rela.gnu.linkonce.b.*}) }
|
||||
${REL_LARGE}
|
||||
.rel.ifunc ${RELOCATING-0} : { *(.rel.ifunc) }
|
||||
.rela.ifunc ${RELOCATING-0} : { *(.rela.ifunc) }
|
||||
EOF
|
||||
|
||||
if [ -n "$COMBRELOC" ]; then
|
||||
|
Loading…
x
Reference in New Issue
Block a user