diff options
author | Nick Clifton <nickc@redhat.com> | 2009-04-30 15:47:13 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2009-04-30 15:47:13 +0000 |
commit | d8045f234d8865a7a7bfce71e81fcbeaf4098a7e (patch) | |
tree | 31e6bc2d28ac295c02dde51ed85fc561675e29a6 /bfd/elf32-i386.c | |
parent | b22a5a41858f1962abba75900ef9928efca36bcd (diff) | |
download | gdb-d8045f234d8865a7a7bfce71e81fcbeaf4098a7e.zip gdb-d8045f234d8865a7a7bfce71e81fcbeaf4098a7e.tar.gz gdb-d8045f234d8865a7a7bfce71e81fcbeaf4098a7e.tar.bz2 |
include/elf
2009-04-30 Nick Clifton <nickc@redhat.com>
* common.h (STT_GNU_IFUNC): Define.
elfcpp
2009-04-30 Nick Clifton <nickc@redhat.com>
* (enum STT): Add STT_GNU_IFUNC.
gas
2009-04-30 Nick Clifton <nickc@redhat.com>
* config/obj-elf.c (obj_elf_type): Add support for a
gnu_indirect_function type.
* config/tc-i386.c (tc_i386_fix_adjustable): Do not adjust fixups
against indirect function symbols.
* doc/as.texinfo (.type): Document the support for the
gnu_indirect_function symbol type.
* NEWS: Mention the new feature.
gas/testsuite
2009-04-30 Nick Clifton <nickc@redhat.com>
* gas/elf/elf.exp: Extend type test to include an ifunc symbol.
Provide an alternative test for targets which do not support ifunc
symbols.
(type.s): Add entry for an ifunc symbol.
(type.e): Add ifunc entry to expected symbol dump.
(section2.e-armelf): Add entry for ifunc symbol.
(type-noifunc.s): New file.
(type-noifunc.e): New file.
bfd/
2009-04-30 Nick Clifton <nickc@redhat.com>
* elf-bfd.h (struct bfd_elf_section_data): Add indirect_relocs
section pointer.
(struct elf_obj_data): Add has_ifunc_symbols boolean.
* elf.c (swap_out_syms): Convert BSF_GNU_INDIRECT_FUNCTION flags
into a STT_GNU_IFUNC symbol type.
(_bfd_elf_is_function_type): Accept STT_GNU_IFUNC as a function
type.
(_bfd_elf_set_osabi): Set the osasbi field to ELFOSABI_LINUX if
the binary contains ifunc symbols.
* elfcode.h (elf_slurp_symbol_table): Translate the STT_GNU_IFUNC
symbol type into a BSF_GNU_INDIRECT_FUNCTION flag.
* elf32-i386.c (is_indirect_function): New function.
(elf_i386_check_relocs): Create an ifunc output section.
(allocate_dynrelocs): Create dynamic relocs in the ifunc output
section if necessary.
(elf_i386_relocate_section): Emit a reloc against an ifunc symbol
if necessary.
(elf_i386_add_symbol_hook): New function. Set the
has_ifunc_symbols field of the elf_obj_data structure if an ifunc
symbol is encountered.
(elf_backend_post_process_headers): Define.
(elf_backend_add_symbol_hook): Define.
(elf_i386_post_process_headers): Rename to
elf_i388_fbsd_post_process_headers.
* elf64-x86_64.c (IS_X86_64_PCREL_TYPE): New macro.
(is_indirect_function): New function.
(elf64_x86_64_check_relocs): Create an ifunc output section.
(allocate_dynrelocs): Create dynamic relocs in the ifunc output
section if necessary.
(elf64_x86_64_relocate_section): Emit a reloc against an ifunc
symbol if necessary.
(elf_i386_add_symbol_hook): Set the has_ifunc_symbols field of the
elf_obj_data structure if an ifunc symbol is encountered.
(elf_backend_post_process_headers): Define.
* elflink.c (_bfd_elf_adjust_dynamic_symbol): Always create a PLT
if we have ifunc symbols to handle.
(get_ifunc_reloc_section_name): New function. Computes the name
for an ifunc section.
(_bfd_elf_make_ifunc_reloc_section): New function. Creates a
section to hold ifunc relocs.
* syms.c (BSF_GNU_INDIRECT_FUNCTION): Define.
(bfd_print_symbol_vandf): Handle ifunc symbols.
(bfd_decode_symclass): Likewise.
* bfd-in2.h: Regenerate.
binutils
2009-04-30 Nick Clifton <nickc@redhat.com>
* readelf.c (dump_relocations): Display a relocation against an
ifunc symbol as if it were a function invocation.
(get_symbol_type): Handle STT_GNU_IFUNC.
ld
2009-04-30 Nick Clifton <nickc@redhat.com>
* NEWS: Mention support for IFUNC symbols.
ld/testsuite
2009-04-30 Nick Clifton <nickc@redhat.com>
* ld-ifunc: New directory.
* ld-ifunc/ifunc.exp: New file: Run the IFUNC tests.
* ld-ifunc/prog.c: New file.
* ld-ifunc/lib.c: New file.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 3c56685..c0276c0 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1196,6 +1196,25 @@ 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_GNU_IFUNC + && (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. */ @@ -1473,6 +1492,12 @@ elf_i386_check_relocs (bfd *abfd, if (sreloc == NULL) return FALSE; + + /* Create the ifunc section as well, even if we have not encountered a + indirect function symbol yet. We may not even see one in the input + object file, but we can still encounter them in libraries. */ + (void) _bfd_elf_make_ifunc_reloc_section + (abfd, sec, htab->elf.dynobj, 2); } /* If this is a global symbol, we count the number of @@ -1815,6 +1840,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) struct elf_i386_link_hash_table *htab; struct elf_i386_link_hash_entry *eh; struct elf_i386_dyn_relocs *p; + bfd_boolean use_indirect_section = FALSE; if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -2036,6 +2062,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } } + else if (is_indirect_symbol (info->output_bfd, h) + && h->dynindx == -1 + && ! h->forced_local) + { + if (bfd_elf_link_record_dynamic_symbol (info, h) + && h->dynindx != -1) + use_indirect_section = TRUE; + else + return FALSE; + } else if (ELIMINATE_COPY_RELOCS) { /* For the non-shared case, discard space for relocs against @@ -2074,7 +2110,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { asection *sreloc; - sreloc = elf_section_data (p->sec)->sreloc; + if (use_indirect_section) + 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); @@ -2877,6 +2916,12 @@ elf_i386_relocate_section (bfd *output_bfd, || h->root.type != bfd_link_hash_undefweak) && (r_type != R_386_PC32 || !SYMBOL_CALLS_LOCAL (info, h))) + || (! info->shared + && h != NULL + && h->dynindx != -1 + && ! h->forced_local + && ((struct elf_i386_link_hash_entry *) h)->dyn_relocs != NULL + && is_indirect_symbol (output_bfd, h)) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL @@ -2925,7 +2970,16 @@ 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 (! info->shared + && h != NULL + && h->dynindx != -1 + && ! h->forced_local + && is_indirect_symbol (output_bfd, h) + && elf_section_data (input_section)->indirect_relocs != NULL + && elf_section_data (input_section)->indirect_relocs->contents != NULL) + sreloc = elf_section_data (input_section)->indirect_relocs; + else + sreloc = elf_section_data (input_section)->sreloc; BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL); @@ -4045,6 +4099,24 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h) return _bfd_elf_hash_symbol (h); } +/* Hook called by the linker routine which adds symbols from an object + file. */ + +static bfd_boolean +elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED, + struct bfd_link_info * info ATTRIBUTE_UNUSED, + Elf_Internal_Sym * sym, + const char ** namep ATTRIBUTE_UNUSED, + flagword * flagsp ATTRIBUTE_UNUSED, + asection ** secp ATTRIBUTE_UNUSED, + bfd_vma * valp ATTRIBUTE_UNUSED) +{ + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; + + return TRUE; +} + #define TARGET_LITTLE_SYM bfd_elf32_i386_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 @@ -4089,6 +4161,9 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h) ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_plt_sym_val elf_i386_plt_sym_val #define elf_backend_hash_symbol elf_i386_hash_symbol +#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook +#undef elf_backend_post_process_headers +#define elf_backend_post_process_headers _bfd_elf_set_osabi #include "elf32-target.h" @@ -4106,15 +4181,10 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h) executables and (for simplicity) also all other object files. */ static void -elf_i386_post_process_headers (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED) +elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) { - Elf_Internal_Ehdr *i_ehdrp; - - i_ehdrp = elf_elfheader (abfd); + _bfd_elf_set_osabi (abfd, info); - /* Put an ABI label supported by FreeBSD >= 4.1. */ - i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; #ifdef OLD_FREEBSD_ABI_LABEL /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); @@ -4122,10 +4192,12 @@ elf_i386_post_process_headers (bfd *abfd, } #undef elf_backend_post_process_headers -#define elf_backend_post_process_headers elf_i386_post_process_headers +#define elf_backend_post_process_headers elf_i386_fbsd_post_process_headers #undef elf32_bed #define elf32_bed elf32_i386_fbsd_bed +#undef elf_backend_add_symbol_hook + #include "elf32-target.h" /* VxWorks support. */ |