X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=c50e98d92bf357d76cc7a30b0caa12d4295e212a;hb=d63388ff701ef7f579dad732b4ffb7c89b1758d5;hp=3dd28e44637895e45ef851aae0ee3b3b17b96b44;hpb=22edb2f16480aef5e060ad021199c3086300a4f5;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 3dd28e4463..c50e98d92b 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,12 +1,12 @@ /* Intel 80386/80486-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,10 +16,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" @@ -330,6 +331,20 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return 0; } +static reloc_howto_type * +elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++) + if (elf_howto_table[i].name != NULL + && strcasecmp (elf_howto_table[i].name, r_name) == 0) + return &elf_howto_table[i]; + + return NULL; +} + static void elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, @@ -622,11 +637,14 @@ struct elf_i386_obj_tdata static bfd_boolean elf_i386_mkobject (bfd *abfd) { - bfd_size_type amt = sizeof (struct elf_i386_obj_tdata); - abfd->tdata.any = bfd_zalloc (abfd, amt); if (abfd->tdata.any == NULL) - return FALSE; - return TRUE; + { + bfd_size_type amt = sizeof (struct elf_i386_obj_tdata); + abfd->tdata.any = bfd_zalloc (abfd, amt); + if (abfd->tdata.any == NULL) + return FALSE; + } + return bfd_elf_mkobject (abfd); } /* i386 ELF linker hash table. */ @@ -653,6 +671,9 @@ struct elf_i386_link_hash_table /* Value used to fill the last word of the first plt entry. */ bfd_byte plt0_pad_byte; + /* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */ + bfd_vma next_tls_desc_index; + union { bfd_signed_vma refcount; bfd_vma offset; @@ -672,7 +693,7 @@ struct elf_i386_link_hash_table ((struct elf_i386_link_hash_table *) ((p)->hash)) #define elf_i386_compute_jump_table_size(htab) \ - ((htab)->srelplt->reloc_count * 4) + ((htab)->next_tls_desc_index * 4) /* Create an entry in an i386 ELF linker hash table. */ @@ -718,7 +739,8 @@ elf_i386_link_hash_table_create (bfd *abfd) if (ret == NULL) return NULL; - if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc)) + if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc, + sizeof (struct elf_i386_link_hash_entry))) { free (ret); return NULL; @@ -732,6 +754,7 @@ elf_i386_link_hash_table_create (bfd *abfd) ret->sdynbss = NULL; ret->srelbss = NULL; ret->tls_ldm_got.refcount = 0; + ret->next_tls_desc_index = 0; ret->sgotplt_jump_table_size = 0; ret->sym_sec.abfd = NULL; ret->is_vxworks = 0; @@ -778,9 +801,6 @@ static bfd_boolean elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) { struct elf_i386_link_hash_table *htab; - asection * s; - int flags; - const struct elf_backend_data *bed = get_elf_backend_data (dynobj); htab = elf_i386_hash_table (info); if (!htab->sgot && !create_got_section (dynobj, info)) @@ -799,17 +819,9 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) || (!info->shared && !htab->srelbss)) abort (); - if (htab->is_vxworks && !info->shared) - { - s = bfd_make_section (dynobj, ".rel.plt.unloaded"); - flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY - | SEC_LINKER_CREATED); - if (s == NULL - || ! bfd_set_section_flags (dynobj, s, flags) - || ! bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) - return FALSE; - htab->srelplt2 = s; - } + if (htab->is_vxworks + && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) + return FALSE; return TRUE; } @@ -1153,7 +1165,7 @@ elf_i386_check_relocs (bfd *abfd, && (sec->flags & SEC_ALLOC) != 0 && (r_type != R_386_PC32 || (h != NULL - && (! info->symbolic + && (! SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS @@ -1180,7 +1192,7 @@ elf_i386_check_relocs (bfd *abfd, if (name == NULL) return FALSE; - if (strncmp (name, ".rel", 4) != 0 + if (! CONST_STRNEQ (name, ".rel") || strcmp (bfd_get_section_name (abfd, sec), name + 4) != 0) { @@ -1258,14 +1270,18 @@ elf_i386_check_relocs (bfd *abfd, /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_386_GNU_VTINHERIT: - if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return FALSE; break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_386_GNU_VTENTRY: - if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return FALSE; break; @@ -1282,38 +1298,20 @@ elf_i386_check_relocs (bfd *abfd, static asection * elf_i386_gc_mark_hook (asection *sec, - struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_386_GNU_VTINHERIT: - case R_386_GNU_VTENTRY: - break; - - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - - return NULL; + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_386_GNU_VTINHERIT: + case R_386_GNU_VTENTRY: + return NULL; + } + + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } /* Update the got entry reference counts for the section being removed. */ @@ -1426,7 +1424,6 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf_i386_link_hash_table *htab; asection *s; - unsigned int power_of_two; /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later, @@ -1546,29 +1543,9 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, h->needs_copy = 1; } - /* We need to figure out the alignment required for this symbol. I - have no idea how ELF linkers handle this. */ - power_of_two = bfd_log2 (h->size); - if (power_of_two > 3) - power_of_two = 3; - - /* Apply the required alignment. */ s = htab->sdynbss; - s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); - if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) - { - if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) - return FALSE; - } - - /* Define the symbol as being at this point in the section. */ - h->root.u.def.section = s; - h->root.u.def.value = s->size; - /* Increment the section size to make room for the symbol. */ - s->size += h->size; - - return TRUE; + return _bfd_elf_adjust_dynamic_copy (h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -1639,7 +1616,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .rel.plt section. */ htab->srelplt->size += sizeof (Elf32_External_Rel); - htab->srelplt->reloc_count++; + htab->next_tls_desc_index++; if (htab->is_vxworks && !info->shared) { @@ -1996,21 +1973,6 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, else htab->tls_ldm_got.offset = -1; - if (htab->is_vxworks) - { - /* Mark the GOT and PLT symbols as having relocations; they might - not, but we won't know for sure until we build the GOT in - finish_dynamic_symbol. */ - if (htab->elf.hgot) - htab->elf.hgot->indx = -2; - if (htab->elf.hplt) - { - htab->elf.hplt->indx = -2; - if (htab->splt->flags & SEC_CODE) - htab->elf.hplt->type = STT_FUNC; - } - } - /* Allocate global sym .plt and .got entries, and space for global sym dynamic relocs. */ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); @@ -2021,7 +1983,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, for them, it suffices to multiply the reloc count by the jump slot size. */ if (htab->srelplt) - htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4; + htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ @@ -2047,15 +2009,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->elf.hplt != NULL) strip_section = FALSE; } - else if (strncmp (bfd_get_section_name (dynobj, s), ".rel", 4) == 0) + else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) { if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2) relocs = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ - if (s != htab->srelplt) - s->reloc_count = 0; + s->reloc_count = 0; } else { @@ -2301,51 +2262,6 @@ elf_i386_relocate_section (bfd *output_bfd, howto = elf_howto_table + indx; r_symndx = ELF32_R_SYM (rel->r_info); - - if (info->relocatable) - { - bfd_vma val; - bfd_byte *where; - - /* This is a relocatable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (r_symndx >= symtab_hdr->sh_info) - continue; - - sym = local_syms + r_symndx; - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) - continue; - - sec = local_sections[r_symndx]; - val = sec->output_offset; - if (val == 0) - continue; - - where = contents + rel->r_offset; - switch (howto->size) - { - /* FIXME: overflow checks. */ - case 0: - val += bfd_get_8 (input_bfd, where); - bfd_put_8 (input_bfd, val, where); - break; - case 1: - val += bfd_get_16 (input_bfd, where); - bfd_put_16 (input_bfd, val, where); - break; - case 2: - val += bfd_get_32 (input_bfd, where); - bfd_put_32 (input_bfd, val, where); - break; - default: - abort (); - } - continue; - } - - /* This is a final link. */ h = NULL; sym = NULL; sec = NULL; @@ -2357,10 +2273,12 @@ elf_i386_relocate_section (bfd *output_bfd, relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION + && ((sec->flags & SEC_MERGE) != 0 + || (info->relocatable + && sec->output_offset != 0))) { - asection *msec; bfd_vma addend; bfd_byte *where = contents + rel->r_offset; @@ -2394,10 +2312,16 @@ elf_i386_relocate_section (bfd *output_bfd, abort (); } - msec = sec; - addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); - addend -= relocation; - addend += msec->output_section->vma + msec->output_offset; + if (info->relocatable) + addend += sec->output_offset; + else + { + asection *msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, + addend); + addend -= relocation; + addend += msec->output_section->vma + msec->output_offset; + } switch (howto->size) { @@ -2430,21 +2354,20 @@ elf_i386_relocate_section (bfd *output_bfd, unresolved_reloc, warned); } - if (r_symndx == 0) + if (sec != NULL && elf_discarded_section (sec)) { - /* r_symndx will be zero only for relocs against symbols from - removed linkonce sections, or sections discarded by a linker - script. For these relocs, we just want the section contents - zeroed. Avoid any special processing in the switch below. */ - r_type = R_386_NONE; - - relocation = 0; - if (howto->pc_relative) - relocation = (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; } + if (info->relocatable) + continue; + switch (r_type) { case R_386_GOT32: @@ -2648,7 +2571,7 @@ elf_i386_relocate_section (bfd *output_bfd, && h->dynindx != -1 && (r_type == R_386_PC32 || !info->shared - || !info->symbolic + || !SYMBOLIC_BIND (info, h) || !h->def_regular)) outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); else @@ -2840,8 +2763,9 @@ elf_i386_relocate_section (bfd *output_bfd, val = bfd_get_8 (input_bfd, contents + roff + 1); BFD_ASSERT (val == 0x10); - /* Now modify the instruction as appropriate. */ - bfd_put_8 (output_bfd, 0x90, contents + roff); + /* Now modify the instruction as appropriate. Use + xchg %ax,%ax instead of 2 nops. */ + bfd_put_8 (output_bfd, 0x66, contents + roff); bfd_put_8 (output_bfd, 0x90, contents + roff + 1); continue; } @@ -2997,8 +2921,8 @@ elf_i386_relocate_section (bfd *output_bfd, + htab->sgotplt_jump_table_size); sreloc = htab->srelplt; loc = sreloc->contents; - loc += sreloc->reloc_count++ - * sizeof (Elf32_External_Rel); + loc += (htab->next_tls_desc_index++ + * sizeof (Elf32_External_Rel)); BFD_ASSERT (loc + sizeof (Elf32_External_Rel) <= sreloc->contents + sreloc->size); bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); @@ -3161,12 +3085,8 @@ elf_i386_relocate_section (bfd *output_bfd, subl $foo@gottpoff(%reg), %eax into: addl $foo@gotntpoff(%reg), %eax. */ - if (r_type == R_386_TLS_GOTIE) - { - contents[roff + 6] = 0x03; - if (tls_type == GOT_TLS_IE_BOTH) - off += 4; - } + if (tls_type == GOT_TLS_IE_POS) + contents[roff + 6] = 0x03; bfd_put_32 (output_bfd, htab->sgot->output_section->vma + htab->sgot->output_offset + off @@ -3250,8 +3170,8 @@ elf_i386_relocate_section (bfd *output_bfd, /* Now modify the instruction as appropriate. */ if (tls_type != GOT_TLS_IE_NEG) { - /* nop; nop */ - bfd_put_8 (output_bfd, 0x90, contents + roff); + /* xchg %ax,%ax */ + bfd_put_8 (output_bfd, 0x66, contents + roff); bfd_put_8 (output_bfd, 0x90, contents + roff + 1); } else @@ -3861,6 +3781,18 @@ elf_i386_plt_sym_val (bfd_vma i, const asection *plt, return plt->vma + (i + 1) * PLT_ENTRY_SIZE; } +/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ + +static bfd_boolean +elf_i386_hash_symbol (struct elf_link_hash_entry *h) +{ + if (h->plt.offset != (bfd_vma) -1 + && !h->def_regular + && !h->pointer_equality_needed) + return FALSE; + + return _bfd_elf_hash_symbol (h); +} #define TARGET_LITTLE_SYM bfd_elf32_i386_vec #define TARGET_LITTLE_NAME "elf32-i386" @@ -3884,6 +3816,7 @@ elf_i386_plt_sym_val (bfd_vma i, const asection *plt, #define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name #define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create #define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup #define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol #define elf_backend_check_relocs elf_i386_check_relocs @@ -3900,7 +3833,10 @@ elf_i386_plt_sym_val (bfd_vma i, const asection *plt, #define elf_backend_relocate_section elf_i386_relocate_section #define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections #define elf_backend_always_size_sections elf_i386_always_size_sections +#define elf_backend_omit_section_dynsym \ + ((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 #include "elf32-target.h" @@ -3910,6 +3846,8 @@ elf_i386_plt_sym_val (bfd_vma i, const asection *plt, #define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-freebsd" +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_FREEBSD /* The kernel recognizes executables as valid only if they carry a "FreeBSD" label in the ELF header. So we put this label on all @@ -3924,7 +3862,7 @@ elf_i386_post_process_headers (bfd *abfd, i_ehdrp = elf_elfheader (abfd); /* Put an ABI label supported by FreeBSD >= 4.1. */ - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; + 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); @@ -3944,7 +3882,7 @@ elf_i386_post_process_headers (bfd *abfd, #define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-vxworks" - +#undef ELF_OSABI /* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */ @@ -3966,23 +3904,6 @@ elf_i386_vxworks_link_hash_table_create (bfd *abfd) } -/* Tweak magic VxWorks symbols as they are written to the output file. */ -static bfd_boolean -elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info - ATTRIBUTE_UNUSED, - const char *name, - Elf_Internal_Sym *sym, - asection *input_sec ATTRIBUTE_UNUSED, - struct elf_link_hash_entry *h - ATTRIBUTE_UNUSED) -{ - /* Ignore the first dummy symbol. */ - if (!name) - return TRUE; - - return elf_vxworks_link_output_symbol_hook (name, sym); -} - #undef elf_backend_post_process_headers #undef bfd_elf32_bfd_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_create \ @@ -3992,7 +3913,7 @@ elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info elf_vxworks_add_symbol_hook #undef elf_backend_link_output_symbol_hook #define elf_backend_link_output_symbol_hook \ - elf_i386_vxworks_link_output_symbol_hook + elf_vxworks_link_output_symbol_hook #undef elf_backend_emit_relocs #define elf_backend_emit_relocs elf_vxworks_emit_relocs #undef elf_backend_final_write_processing