X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=d7f59e5e2545a75b3653f82b205f950cc3a52d06;hb=d1ec1e40b5b457c92aaa23f7af40e026e4596a99;hp=4ca25f22dafae4bc4d14937498874442e388809e;hpb=13ca314985e8d50c15a7f147e768581737847f3c;p=platform%2Fupstream%2Fbinutils.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 4ca25f2..d7f59e5 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,6 +1,6 @@ /* Intel 80386/80486-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -133,7 +133,9 @@ static reloc_howto_type elf_howto_table[]= HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", TRUE, 0xffffffff, 0xffffffff, FALSE), - EMPTY_HOWTO (38), + HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_386_SIZE32", + TRUE, 0xffffffff, 0xffffffff, FALSE), HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", TRUE, 0xffffffff, 0xffffffff, FALSE), @@ -312,6 +314,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, TRACE ("BFD_RELOC_386_TLS_TPOFF32"); return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset]; + case BFD_RELOC_SIZE32: + TRACE ("BFD_RELOC_SIZE32"); + return &elf_howto_table[R_386_SIZE32 - R_386_tls_offset]; + case BFD_RELOC_386_TLS_GOTDESC: TRACE ("BFD_RELOC_386_TLS_GOTDESC"); return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset]; @@ -419,10 +425,10 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) return FALSE; /* pr_cursig */ - elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20); + elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 20); /* pr_pid */ - elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 28; @@ -437,10 +443,10 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) case 144: /* Linux/i386 */ /* pr_cursig */ - elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 72; @@ -465,9 +471,9 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) if (pr_version != 1) return FALSE; - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, note->descdata + 8, 17); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 25, 81); } else @@ -478,11 +484,11 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return FALSE; case 124: /* Linux/i386 elf_prpsinfo. */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 12); - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); } } @@ -491,7 +497,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) onto the end of the args in some (at least one anyway) implementations, so strip it off if it exists. */ { - char *command = elf_tdata (abfd)->core_command; + char *command = elf_tdata (abfd)->core->command; int n = strlen (command); if (0 < n && command[n - 1] == ' ') @@ -931,7 +937,7 @@ elf_i386_link_hash_table_create (bfd *abfd) struct elf_i386_link_hash_table *ret; bfd_size_type amt = sizeof (struct elf_i386_link_hash_table); - ret = (struct elf_i386_link_hash_table *) bfd_malloc (amt); + ret = (struct elf_i386_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) return NULL; @@ -944,18 +950,6 @@ elf_i386_link_hash_table_create (bfd *abfd) return NULL; } - ret->sdynbss = NULL; - ret->srelbss = NULL; - ret->plt_eh_frame = NULL; - ret->tls_ldm_got.refcount = 0; - ret->next_tls_desc_index = 0; - ret->sgotplt_jump_table_size = 0; - ret->sym_cache.abfd = NULL; - ret->srelplt2 = NULL; - ret->tls_module_base = NULL; - ret->next_jump_slot_index = 0; - ret->next_irelative_index = 0; - ret->loc_hash_table = htab_try_create (1024, elf_i386_local_htab_hash, elf_i386_local_htab_eq, @@ -982,7 +976,7 @@ elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash) htab_delete (htab->loc_hash_table); if (htab->loc_hash_memory) objalloc_free ((struct objalloc *) htab->loc_hash_memory); - _bfd_generic_link_hash_table_free (hash); + _bfd_elf_link_hash_table_free (hash); } /* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and @@ -1448,6 +1442,7 @@ elf_i386_check_relocs (bfd *abfd, struct elf_link_hash_entry *h; Elf_Internal_Sym *isym; const char *name; + bfd_boolean size_reloc; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1519,6 +1514,7 @@ elf_i386_check_relocs (bfd *abfd, /* It is referenced by a non-shared object. */ h->ref_regular = 1; + h->root.non_ir_ref = 1; } if (! elf_i386_tls_transition (info, abfd, sec, NULL, @@ -1550,6 +1546,10 @@ elf_i386_check_relocs (bfd *abfd, h->plt.refcount += 1; break; + case R_386_SIZE32: + size_reloc = TRUE; + goto do_size; + case R_386_TLS_IE_32: case R_386_TLS_IE: case R_386_TLS_GOTIE: @@ -1642,6 +1642,7 @@ elf_i386_check_relocs (bfd *abfd, (_("%B: `%s' accessed both as normal and " "thread local symbol"), abfd, name); + bfd_set_error (bfd_error_bad_value); return FALSE; } } @@ -1696,6 +1697,8 @@ elf_i386_check_relocs (bfd *abfd, h->pointer_equality_needed = 1; } + size_reloc = FALSE; +do_size: /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc against a local symbol, then we need to copy the reloc @@ -1792,7 +1795,8 @@ elf_i386_check_relocs (bfd *abfd, } p->count += 1; - if (r_type == R_386_PC32) + /* Count size relocation as PC-relative relocation. */ + if (r_type == R_386_PC32 || size_reloc) p->pc_count += 1; } break; @@ -1958,6 +1962,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, case R_386_32: case R_386_PC32: + case R_386_SIZE32: if (info->shared && (h == NULL || h->type != STT_GNU_IFUNC)) break; @@ -2031,8 +2036,11 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, if (pc_count || count) { h->needs_plt = 1; - h->plt.refcount += 1; h->non_got_ref = 1; + if (h->plt.refcount <= 0) + h->plt.refcount = 1; + else + h->plt.refcount += 1; } } @@ -2189,7 +2197,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (h->type == STT_GNU_IFUNC && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, - plt_entry_size, 4); + plt_entry_size, + plt_entry_size, 4); else if (htab->elf.dynamic_sections_created && h->plt.refcount > 0) { @@ -2210,7 +2219,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* If this is the first .plt entry, make room for the special first entry. */ if (s->size == 0) - s->size += plt_entry_size; + s->size = plt_entry_size; h->plt.offset = s->size; @@ -2359,8 +2368,13 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) { - p->count -= p->pc_count; - p->pc_count = 0; + /* Don't update reloc count if there are any non + pc-relative relocs. */ + if (!h->pointer_equality_needed) + { + p->count -= p->pc_count; + p->pc_count = 0; + } if (p->count == 0) *pp = p->next; else @@ -3181,6 +3195,7 @@ elf_i386_relocate_section (bfd *output_bfd, bfd_reloc_status_type r; unsigned int indx; int tls_type; + bfd_vma st_size; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == R_386_GNU_VTINHERIT @@ -3213,6 +3228,7 @@ elf_i386_relocate_section (bfd *output_bfd, relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); + st_size = sym->st_size; if (ELF_ST_TYPE (sym->st_info) == STT_SECTION && ((sec->flags & SEC_MERGE) != 0 @@ -3300,11 +3316,13 @@ elf_i386_relocate_section (bfd *output_bfd, else { bfd_boolean warned ATTRIBUTE_UNUSED; + bfd_boolean ignored ATTRIBUTE_UNUSED; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, - unresolved_reloc, warned); + unresolved_reloc, warned, ignored); + st_size = h->size; } if (sec != NULL && discarded_section (sec)) @@ -3365,7 +3383,6 @@ elf_i386_relocate_section (bfd *output_bfd, if (info->shared && h->non_got_ref) { Elf_Internal_Rela outrel; - bfd_byte *loc; asection *sreloc; bfd_vma offset; @@ -3399,10 +3416,7 @@ elf_i386_relocate_section (bfd *output_bfd, outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); sreloc = htab->elf.irelifunc; - loc = sreloc->contents; - loc += (sreloc->reloc_count++ - * sizeof (Elf32_External_Rel)); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, @@ -3556,7 +3570,6 @@ elf_i386_relocate_section (bfd *output_bfd, { asection *s; Elf_Internal_Rela outrel; - bfd_byte *loc; s = htab->elf.srelgot; if (s == NULL) @@ -3566,9 +3579,7 @@ elf_i386_relocate_section (bfd *output_bfd, + htab->elf.sgot->output_offset + off); outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); - loc = s->contents; - loc += s->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, s, &outrel); } local_got_offsets[r_symndx] |= 1; @@ -3673,6 +3684,11 @@ elf_i386_relocate_section (bfd *output_bfd, unresolved_reloc = FALSE; break; + case R_386_SIZE32: + /* Set to symbol size. */ + relocation = st_size; + /* Fall through. */ + case R_386_32: case R_386_PC32: if ((input_section->flags & SEC_ALLOC) == 0 @@ -3683,7 +3699,7 @@ elf_i386_relocate_section (bfd *output_bfd, && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (r_type != R_386_PC32 + && ((r_type != R_386_PC32 && r_type != R_386_SIZE32) || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared @@ -3696,7 +3712,6 @@ elf_i386_relocate_section (bfd *output_bfd, || h->root.type == bfd_link_hash_undefined))) { Elf_Internal_Rela outrel; - bfd_byte *loc; bfd_boolean skip, relocate; asection *sreloc; @@ -3741,10 +3756,7 @@ elf_i386_relocate_section (bfd *output_bfd, goto check_relocation_error; } - loc = sreloc->contents; - loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); - - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -3759,7 +3771,6 @@ elf_i386_relocate_section (bfd *output_bfd, if (!info->executable) { Elf_Internal_Rela outrel; - bfd_byte *loc; asection *sreloc; outrel.r_offset = rel->r_offset @@ -3769,9 +3780,7 @@ elf_i386_relocate_section (bfd *output_bfd, sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) abort (); - loc = sreloc->contents; - loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); } /* Fall through */ @@ -3997,7 +4006,6 @@ elf_i386_relocate_section (bfd *output_bfd, else { Elf_Internal_Rela outrel; - bfd_byte *loc; int dr_type; asection *sreloc; @@ -4008,6 +4016,7 @@ elf_i386_relocate_section (bfd *output_bfd, if (GOT_TLS_GDESC_P (tls_type)) { + bfd_byte *loc; outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 <= htab->elf.sgotplt->size); @@ -4065,11 +4074,7 @@ elf_i386_relocate_section (bfd *output_bfd, htab->elf.sgot->contents + off); outrel.r_info = ELF32_R_INFO (indx, dr_type); - loc = sreloc->contents; - loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); - BFD_ASSERT (loc + sizeof (Elf32_External_Rel) - <= sreloc->contents + sreloc->size); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); if (GOT_TLS_GD_P (tls_type)) { @@ -4087,11 +4092,7 @@ elf_i386_relocate_section (bfd *output_bfd, outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DTPOFF32); outrel.r_offset += 4; - sreloc->reloc_count++; - loc += sizeof (Elf32_External_Rel); - BFD_ASSERT (loc + sizeof (Elf32_External_Rel) - <= sreloc->contents + sreloc->size); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); } } else if (tls_type == GOT_TLS_IE_BOTH) @@ -4103,9 +4104,7 @@ elf_i386_relocate_section (bfd *output_bfd, htab->elf.sgot->contents + off + 4); outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); outrel.r_offset += 4; - sreloc->reloc_count++; - loc += sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); } dr_done: @@ -4287,7 +4286,6 @@ elf_i386_relocate_section (bfd *output_bfd, else { Elf_Internal_Rela outrel; - bfd_byte *loc; if (htab->elf.srelgot == NULL) abort (); @@ -4300,9 +4298,7 @@ elf_i386_relocate_section (bfd *output_bfd, bfd_put_32 (output_bfd, 0, htab->elf.sgot->contents + off + 4); outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32); - loc = htab->elf.srelgot->contents; - loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, htab->elf.srelgot, &outrel); htab->tls_ldm_got.offset |= 1; } relocation = htab->elf.sgot->output_section->vma @@ -4326,7 +4322,6 @@ elf_i386_relocate_section (bfd *output_bfd, { Elf_Internal_Rela outrel; asection *sreloc; - bfd_byte *loc; outrel.r_offset = rel->r_offset + input_section->output_section->vma @@ -4342,9 +4337,7 @@ elf_i386_relocate_section (bfd *output_bfd, sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) abort (); - loc = sreloc->contents; - loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + elf_append_rel (output_bfd, sreloc, &outrel); if (indx) continue; else if (r_type == R_386_TLS_LE_32) @@ -4632,7 +4625,6 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0) { Elf_Internal_Rela rel; - bfd_byte *loc; /* This symbol has an entry in the global offset table. Set it up. */ @@ -4690,15 +4682,12 @@ do_glob_dat: rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); } - loc = htab->elf.srelgot->contents; - loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + elf_append_rel (output_bfd, htab->elf.srelgot, &rel); } if (h->needs_copy) { Elf_Internal_Rela rel; - bfd_byte *loc; /* This symbol needs a copy reloc. Set it up. */ @@ -4712,9 +4701,7 @@ do_glob_dat: + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY); - loc = htab->srelbss->contents; - loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel); - bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + elf_append_rel (output_bfd, htab->srelbss, &rel); } return TRUE; @@ -4739,7 +4726,9 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf) dynamic linker, before writing them out. */ static enum elf_reloc_type_class -elf_i386_reloc_type_class (const Elf_Internal_Rela *rela) +elf_i386_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela) { switch (ELF32_R_TYPE (rela->r_info)) { @@ -5084,8 +5073,6 @@ elf_i386_add_symbol_hook (bfd * abfd, #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" @@ -5105,7 +5092,7 @@ elf_i386_add_symbol_hook (bfd * abfd, static void elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) { - _bfd_elf_set_osabi (abfd, info); + _bfd_elf_post_process_headers (abfd, info); #ifdef OLD_FREEBSD_ABI_LABEL /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ @@ -5167,7 +5154,6 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #undef elf_backend_want_plt_sym #define elf_backend_want_plt_sym 0 #undef elf_backend_post_process_headers -#define elf_backend_post_process_headers _bfd_elf_set_osabi #undef elf_backend_static_tls_alignment /* NaCl uses substantially different PLT entries for the same effects. */ @@ -5312,19 +5298,33 @@ static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = 0, /* is_vxworks */ }; +static bfd_boolean +elf32_i386_nacl_elf_object_p (bfd *abfd) +{ + /* Set the right machine number for a NaCl i386 ELF32 file. */ + bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386_nacl); + return TRUE; +} + #undef elf_backend_arch_data #define elf_backend_arch_data &elf_i386_nacl_arch_bed +#undef elf_backend_object_p +#define elf_backend_object_p elf32_i386_nacl_elf_object_p #undef elf_backend_modify_segment_map #define elf_backend_modify_segment_map nacl_modify_segment_map #undef elf_backend_modify_program_headers #define elf_backend_modify_program_headers nacl_modify_program_headers +#undef elf_backend_final_write_processing +#define elf_backend_final_write_processing nacl_final_write_processing #include "elf32-target.h" /* Restore defaults. */ +#undef elf_backend_object_p #undef elf_backend_modify_segment_map #undef elf_backend_modify_program_headers +#undef elf_backend_final_write_processing /* VxWorks support. */ @@ -5347,7 +5347,6 @@ static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed = #define elf_backend_arch_data &elf_i386_vxworks_arch_bed #undef elf_backend_relocs_compatible -#undef elf_backend_post_process_headers #undef elf_backend_add_symbol_hook #define elf_backend_add_symbol_hook \ elf_vxworks_add_symbol_hook