diff options
author | Nick Clifton <nickc@redhat.com> | 2008-12-03 14:51:00 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2008-12-03 14:51:00 +0000 |
commit | e7c3341679431c5ecfc170a984d7196cdc175777 (patch) | |
tree | 5be48e5e73b1b747806d4cc47c80ca9893f3aea4 /bfd/elf64-x86-64.c | |
parent | 5d73705c26e9cb0108f95c127fc5b87c9a982289 (diff) | |
download | gdb-e7c3341679431c5ecfc170a984d7196cdc175777.zip gdb-e7c3341679431c5ecfc170a984d7196cdc175777.tar.gz gdb-e7c3341679431c5ecfc170a984d7196cdc175777.tar.bz2 |
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/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 7eecb22..1ea033b 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -974,6 +974,26 @@ elf64_x86_64_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. */ @@ -1255,7 +1275,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, If on the other hand, we are creating an executable, we may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the - symbol. */ + symbol. + + Also we must keep any relocations against IFUNC symbols as + they will be evaluated at load time. */ if ((info->shared && (sec->flags & SEC_ALLOC) != 0 && (((r_type != R_X86_64_PC8) @@ -1271,7 +1294,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, && (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 elf64_x86_64_dyn_relocs *p; struct elf64_x86_64_dyn_relocs **head; @@ -1291,6 +1315,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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) @@ -1830,6 +1857,13 @@ 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 + && ! 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 @@ -1866,7 +1900,16 @@ 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 (Elf64_External_Rela); } @@ -1970,7 +2013,6 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, srel->size += p->count * sizeof (Elf64_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; - } } } @@ -2039,7 +2081,7 @@ elf64_x86_64_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, @@ -2170,8 +2212,7 @@ elf64_x86_64_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) { @@ -2680,7 +2721,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && ((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; @@ -2766,9 +2808,12 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } } - 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 (Elf64_External_Rela); @@ -2778,7 +2823,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, 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; } |