summaryrefslogtreecommitdiff
path: root/bfd/elf32-i386.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2008-12-03 14:50:56 +0000
committerNick Clifton <nickc@redhat.com>2008-12-03 14:50:56 +0000
commita248d9f6aa039c4e776caa0b5cae6f0c0b654f35 (patch)
tree2b13999074c748000e819d796744e913df177e86 /bfd/elf32-i386.c
parentd3ac72fc45ec9d20f009b27feeb41b6927ad31ca (diff)
downloadgdb-a248d9f6aa039c4e776caa0b5cae6f0c0b654f35.tar.gz
include/elf/
* common.h (STT_IFUNC): Define. elfcpp/ * elfcpp.h (enum STT): Add STT_IFUNC. bfd/ * syms.c (struct bfd_symbol): Add new flag BSF_INDIRECT_FUNCTION. Remove redundant flag BFD_FORT_COMM_DEFAULT_VALUE. Renumber flags to remove gaps. (bfd_print_symbol_vandf): Return 'i' for BSF_INDIRECT_FUNCTION. (bfd_decode_symclass): Likewise. * elf.c (swap_out_syms): Translate BSF_INDIRECT_FUNCTION into STT_IFUNC. (elf_find_function): Treat STT_IFUNC in the same way as STT_FUNC. (_bfd_elf_is_function_type): Likewise. * elf32-arm.c (arm_elf_find_function): Likewise. (elf32_arm_adjust_dynamic_symbol): Likewise. (elf32_arm_swap_symbol_in): Likewise. (elf32_arm_additional_program_headers): Likewise. * elf32-i386.c (is_indirect_symbol): New function. (elf_i386_check_relocs): Also generate dynamic relocs for relocations against STT_IFUNC symbols. (allocate_dynrelocs): Likewise. (elf_i386_relocate_section): Likewise. * elf64-x86-64.c (is_indirect_symbol): New function. (elf64_x86_64_check_relocs): Also generate dynamic relocs for relocations against STT_IFUNC symbols. (allocate_dynrelocs): Likewise. (elf64_x86_64_relocate_section): Likewise. * elfcode.h (elf_slurp_symbol_table): Translate STT_IFUNC into BSF_INDIRECT_FUNCTION. * elflink.c (_bfd_elf_adjust_dynamic_reloc_section): Add support for STT_IFUNC symbols. (get_ifunc_reloc_section_name): New function. (_bfd_elf_make_ifunc_reloc_section): New function. * elf-bfd.h (struct bfd_elf_section_data): Add indirect_relocs field. * bfd-in2.h: Regenerate. gas/ * config/obj-elf.c (obj_elf_type): Add support for STT_IFUNC type. * doc/as.texinfo: Document new feature. * NEWS: Mention new feature. gas/testsuite/ * gas/elf/type.s: Add test of STT_IFUNC symbol type. * gas/elf/type.e: Update expected disassembly. * gas/elf/elf.exp: Update grep of symbol types. ld/ * NEWS: Mention new feature. * pe-dll.c (process_def_file): Replace use of redundant BFD_FORT_COMM_DEFAULT_VALUE with 0. * scripttempl/elf.sc: Add .rel.ifunc.dyn and .rela.ifunc.dyn sections. ld/testsuite/ * ld-mips-elf/reloc-1-n32.d: Updated expected output for reloc descriptions. * ld-mips-elf/reloc-1-n64.d: Likewise. * ld-i386/ifunc.d: New test. * ld-i386/ifunc.s: Source file for the new test. * ld-i386/i386.exp: Run the new test.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r--bfd/elf32-i386.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 7d14fef561d..ec0c16fd83e 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1193,6 +1193,26 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
return TRUE;
}
+/* Returns true if the hash entry refers to a symbol
+ marked for indirect handling during reloc processing. */
+
+static bfd_boolean
+is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
+{
+ const struct elf_backend_data * bed;
+
+ if (abfd == NULL || h == NULL)
+ return FALSE;
+
+ bed = get_elf_backend_data (abfd);
+
+ return h->type == STT_IFUNC
+ && bed != NULL
+ && (bed->elf_osabi == ELFOSABI_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || bed->elf_osabi == ELFOSABI_NONE);
+}
+
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure linkage
table, and dynamic reloc sections. */
@@ -1452,7 +1472,8 @@ elf_i386_check_relocs (bfd *abfd,
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
- || !h->def_regular)))
+ || !h->def_regular))
+ || is_indirect_symbol (abfd, h))
{
struct elf_i386_dyn_relocs *p;
struct elf_i386_dyn_relocs **head;
@@ -1472,6 +1493,9 @@ elf_i386_check_relocs (bfd *abfd,
return FALSE;
}
+ if (is_indirect_symbol (abfd, h))
+ (void) _bfd_elf_make_ifunc_reloc_section (abfd, sec, htab->elf.dynobj, 2);
+
/* If this is a global symbol, we count the number of
relocations we need for this symbol. */
if (h != NULL)
@@ -2033,6 +2057,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
}
}
}
+ else if (is_indirect_symbol (info->output_bfd, h))
+ {
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+ }
else if (ELIMINATE_COPY_RELOCS)
{
/* For the non-shared case, discard space for relocs against
@@ -2069,7 +2102,15 @@ 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;
+ asection *sreloc;
+
+ if (! info->shared
+ && is_indirect_symbol (info->output_bfd, h))
+ sreloc = elf_section_data (p->sec)->indirect_relocs;
+ else
+ sreloc = elf_section_data (p->sec)->sreloc;
+
+ BFD_ASSERT (sreloc != NULL);
sreloc->size += p->count * sizeof (Elf32_External_Rel);
}
@@ -2248,7 +2289,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
- elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
+ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
/* For every jump slot reserved in the sgotplt, reloc_count is
incremented. However, when we reserve space for TLS descriptors,
@@ -2361,8 +2402,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
/* If any dynamic relocs apply to a read-only section,
then we need a DT_TEXTREL entry. */
if ((info->flags & DF_TEXTREL) == 0)
- elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
- (PTR) info);
+ elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
if ((info->flags & DF_TEXTREL) != 0)
{
@@ -2879,7 +2919,8 @@ elf_i386_relocate_section (bfd *output_bfd,
&& ((h->def_dynamic
&& !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_undefined)))
+ || h->root.type == bfd_link_hash_undefined))
+ || is_indirect_symbol (output_bfd, h))
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
@@ -2919,19 +2960,23 @@ elf_i386_relocate_section (bfd *output_bfd,
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
}
- sreloc = elf_section_data (input_section)->sreloc;
- if (sreloc == NULL)
- abort ();
+ if ((! info->shared) && is_indirect_symbol (output_bfd, h))
+ sreloc = elf_section_data (input_section)->indirect_relocs;
+ else
+ sreloc = elf_section_data (input_section)->sreloc;
+
+ BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
loc = sreloc->contents;
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
/* If this reloc is against an external symbol, we do
not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes
an addend for the dynamic reloc. */
- if (! relocate)
+ if (! relocate || is_indirect_symbol (output_bfd, h))
continue;
}
break;