X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=439538e233d4f8a1a000f7a28e6a862cc587dd5f;hb=3cd0754799953aae30394173c0545c52c5f17481;hp=1b04a6ef1f156d9ae9d815987eb15d37e2cbc787;hpb=9d4b2dba0e5f61cbec871f70e0a20c4b8a5d4ba9;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 1b04a6ef1f..439538e233 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,7 +1,5 @@ /* 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 - Free Software Foundation, Inc. + Copyright (C) 1993-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -39,7 +37,7 @@ static reloc_howto_type elf_howto_table[]= { - HOWTO(R_386_NONE, 0, 0, 0, FALSE, 0, complain_overflow_bitfield, + HOWTO(R_386_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_NONE", TRUE, 0x00000000, 0x00000000, FALSE), HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, @@ -133,7 +131,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 +312,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]; @@ -375,7 +379,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type) abfd, (int) r_type); indx = R_386_NONE; } - BFD_ASSERT (elf_howto_table [indx].type == r_type); + /* PR 17512: file: 0f67f69d. */ + if (elf_howto_table [indx].type != r_type) + return NULL; return &elf_howto_table[indx]; } @@ -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] == ' ') @@ -576,6 +582,24 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] = 0, 0, 0, 0 /* replaced with offset to start of .plt. */ }; +/* Entries in the GOT procedure linkage table look like this. */ + +static const bfd_byte elf_i386_got_plt_entry[8] = +{ + 0xff, 0x25, /* jmp indirect */ + 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ + 0x66, 0x90 /* xchg %ax,%ax */ +}; + +/* Entries in the PIC GOT procedure linkage table look like this. */ + +static const bfd_byte elf_i386_pic_got_plt_entry[8] = +{ + 0xff, 0xa3, /* jmp *offset(%ebx) */ + 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ + 0x66, 0x90 /* xchg %ax,%ax */ +}; + /* .eh_frame covering the .plt section. */ static const bfd_byte elf_i386_eh_frame_plt[] = @@ -732,6 +756,10 @@ struct elf_i386_link_hash_entry (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) unsigned char tls_type; + /* Information about the GOT PLT entry. Filled when there are both + GOT and PLT relocations against the same function. */ + union gotplt_union plt_got; + /* Offset of the GOTPLT entry reserved for the TLS descriptor, starting at the end of the jump table. */ bfd_vma tlsdesc_got; @@ -781,6 +809,7 @@ struct elf_i386_link_hash_table asection *sdynbss; asection *srelbss; asection *plt_eh_frame; + asection *plt_got; union { @@ -822,7 +851,7 @@ struct elf_i386_link_hash_table == I386_ELF_DATA ? ((struct elf_i386_link_hash_table *) ((p)->hash)) : NULL) #define elf_i386_compute_jump_table_size(htab) \ - ((htab)->next_tls_desc_index * 4) + ((htab)->elf.srelplt->reloc_count * 4) /* Create an entry in an i386 ELF linker hash table. */ @@ -850,6 +879,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry, eh = (struct elf_i386_link_hash_entry *) entry; eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; + eh->plt_got.offset = (bfd_vma) -1; eh->tlsdesc_got = (bfd_vma) -1; } @@ -918,11 +948,27 @@ elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab, ret->elf.indx = sec->id; ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info); ret->elf.dynindx = -1; + ret->plt_got.offset = (bfd_vma) -1; *slot = ret; } return &ret->elf; } +/* Destroy an i386 ELF linker hash table. */ + +static void +elf_i386_link_hash_table_free (bfd *obfd) +{ + struct elf_i386_link_hash_table *htab + = (struct elf_i386_link_hash_table *) obfd->link.hash; + + if (htab->loc_hash_table) + htab_delete (htab->loc_hash_table); + if (htab->loc_hash_memory) + objalloc_free ((struct objalloc *) htab->loc_hash_memory); + _bfd_elf_link_hash_table_free (obfd); +} + /* Create an i386 ELF linker hash table. */ static struct bfd_link_hash_table * @@ -931,7 +977,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 +990,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, @@ -963,28 +997,14 @@ elf_i386_link_hash_table_create (bfd *abfd) ret->loc_hash_memory = objalloc_create (); if (!ret->loc_hash_table || !ret->loc_hash_memory) { - free (ret); + elf_i386_link_hash_table_free (abfd); return NULL; } + ret->elf.root.hash_table_free = elf_i386_link_hash_table_free; return &ret->elf.root; } -/* Destroy an i386 ELF linker hash table. */ - -static void -elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash) -{ - struct elf_i386_link_hash_table *htab - = (struct elf_i386_link_hash_table *) hash; - - if (htab->loc_hash_table) - 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); -} - /* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and .rel.bss sections in DYNOBJ, and set up shortcuts to them in our hash table. */ @@ -1425,6 +1445,7 @@ elf_i386_check_relocs (bfd *abfd, const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; asection *sreloc; + bfd_boolean use_plt_got; if (info->relocatable) return TRUE; @@ -1435,6 +1456,10 @@ elf_i386_check_relocs (bfd *abfd, if (htab == NULL) return FALSE; + use_plt_got = (!get_elf_i386_backend_data (abfd)->is_vxworks + && (get_elf_i386_backend_data (abfd) + == &elf_i386_arch_bed)); + symtab_hdr = &elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); @@ -1448,6 +1473,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); @@ -1517,73 +1543,9 @@ elf_i386_check_relocs (bfd *abfd, break; } - /* Since STT_GNU_IFUNC symbol must go through PLT, we handle - it here if it is defined in a non-shared object. */ - if (h->type == STT_GNU_IFUNC - && h->def_regular) - { - /* It is referenced by a non-shared object. */ - h->ref_regular = 1; - h->needs_plt = 1; - - /* STT_GNU_IFUNC symbol must go through PLT. */ - h->plt.refcount += 1; - - /* STT_GNU_IFUNC needs dynamic sections. */ - if (htab->elf.dynobj == NULL) - htab->elf.dynobj = abfd; - - switch (r_type) - { - default: - if (h->root.root.string) - name = h->root.root.string; - else - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, - NULL); - (*_bfd_error_handler) - (_("%B: relocation %s against STT_GNU_IFUNC " - "symbol `%s' isn't handled by %s"), abfd, - elf_howto_table[r_type].name, - name, __FUNCTION__); - bfd_set_error (bfd_error_bad_value); - return FALSE; - - case R_386_32: - h->non_got_ref = 1; - h->pointer_equality_needed = 1; - if (info->shared) - { - /* We must copy these reloc types into the - output file. Create a reloc section in - dynobj and make room for this reloc. */ - sreloc = _bfd_elf_create_ifunc_dyn_reloc - (abfd, info, sec, sreloc, - &((struct elf_i386_link_hash_entry *) h)->dyn_relocs); - if (sreloc == NULL) - return FALSE; - } - break; - - case R_386_PC32: - h->non_got_ref = 1; - break; - - case R_386_PLT32: - break; - - case R_386_GOT32: - case R_386_GOTOFF: - h->got.refcount += 1; - if (htab->elf.sgot == NULL - && !_bfd_elf_create_got_section (htab->elf.dynobj, - info)) - return FALSE; - break; - } - - continue; - } + /* 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, @@ -1615,6 +1577,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: @@ -1707,6 +1673,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; } } @@ -1761,6 +1728,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 @@ -1857,7 +1826,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; @@ -1881,6 +1851,39 @@ elf_i386_check_relocs (bfd *abfd, default: break; } + + if (use_plt_got + && h != NULL + && h->plt.refcount > 0 + && h->got.refcount > 0 + && htab->plt_got == NULL) + { + /* Create the GOT procedure linkage table. */ + unsigned int plt_got_align; + const struct elf_backend_data *bed; + + bed = get_elf_backend_data (info->output_bfd); + BFD_ASSERT (sizeof (elf_i386_got_plt_entry) == 8 + && (sizeof (elf_i386_got_plt_entry) + == sizeof (elf_i386_pic_got_plt_entry))); + plt_got_align = 3; + + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + htab->plt_got + = bfd_make_section_anyway_with_flags (htab->elf.dynobj, + ".plt.got", + (bed->dynamic_sec_flags + | SEC_ALLOC + | SEC_CODE + | SEC_LOAD + | SEC_READONLY)); + if (htab->plt_got == NULL + || !bfd_set_section_alignment (htab->elf.dynobj, + htab->plt_got, + plt_got_align)) + return FALSE; + } } return TRUE; @@ -2023,6 +2026,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; @@ -2066,10 +2070,44 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf_i386_link_hash_table *htab; asection *s; + struct elf_i386_link_hash_entry *eh; + struct elf_dyn_relocs *p; /* STT_GNU_IFUNC symbol must go through PLT. */ if (h->type == STT_GNU_IFUNC) { + /* All local STT_GNU_IFUNC references must be treate as local + calls via local PLT. */ + if (h->ref_regular + && SYMBOL_CALLS_LOCAL (info, h)) + { + bfd_size_type pc_count = 0, count = 0; + struct elf_dyn_relocs **pp; + + eh = (struct elf_i386_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + pc_count += p->pc_count; + p->count -= p->pc_count; + p->pc_count = 0; + count += p->count; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + + if (pc_count || count) + { + h->needs_plt = 1; + h->non_got_ref = 1; + if (h->plt.refcount <= 0) + h->plt.refcount = 1; + else + h->plt.refcount += 1; + } + } + if (h->plt.refcount <= 0) { h->plt.offset = (bfd_vma) -1; @@ -2155,9 +2193,6 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS && !get_elf_i386_backend_data (info->output_bfd)->is_vxworks) { - struct elf_i386_link_hash_entry * eh; - struct elf_dyn_relocs *p; - eh = (struct elf_i386_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { @@ -2194,7 +2229,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, s = htab->sdynbss; - return _bfd_elf_adjust_dynamic_copy (h, s); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -2221,15 +2256,36 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd); + /* We can't use the GOT PLT if pointer equality is needed since + finish_dynamic_symbol won't clear symbol value and the dynamic + linker won't update the GOT slot. We will get into an infinite + loop at run-time. */ + if (htab->plt_got != NULL + && h->type != STT_GNU_IFUNC + && !h->pointer_equality_needed + && h->plt.refcount > 0 + && h->got.refcount > 0) + { + /* Don't use the regular PLT if there are both GOT and GOTPLT + reloctions. */ + h->plt.offset = (bfd_vma) -1; + + /* Use the GOT PLT. */ + eh->plt_got.refcount = 1; + } + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ 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) + && (h->plt.refcount > 0 || eh->plt_got.refcount > 0)) { + bfd_boolean use_plt_got = eh->plt_got.refcount > 0; + /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 @@ -2243,13 +2299,17 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { asection *s = htab->elf.splt; + asection *got_s = htab->plt_got; /* 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; + if (use_plt_got) + eh->plt_got.offset = got_s->size; + else + h->plt.offset = s->size; /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this @@ -2259,20 +2319,36 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (! info->shared && !h->def_regular) { - h->root.u.def.section = s; - h->root.u.def.value = h->plt.offset; + if (use_plt_got) + { + /* We need to make a call to the entry of the GOT PLT + instead of regular PLT entry. */ + h->root.u.def.section = got_s; + h->root.u.def.value = eh->plt_got.offset; + } + else + { + h->root.u.def.section = s; + h->root.u.def.value = h->plt.offset; + } } /* Make room for this entry. */ - s->size += plt_entry_size; + if (use_plt_got) + got_s->size += sizeof (elf_i386_got_plt_entry); + else + { + s->size += plt_entry_size; - /* We also need to make an entry in the .got.plt section, which - will be placed in the .got section by the linker script. */ - htab->elf.sgotplt->size += 4; + /* We also need to make an entry in the .got.plt section, + which will be placed in the .got section by the linker + script. */ + htab->elf.sgotplt->size += 4; - /* We also need to make an entry in the .rel.plt section. */ - htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - htab->elf.srelplt->reloc_count++; + /* We also need to make an entry in the .rel.plt section. */ + htab->elf.srelplt->size += sizeof (Elf32_External_Rel); + htab->elf.srelplt->reloc_count++; + } if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks && !info->shared) @@ -2562,7 +2638,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, /* Nothing to do if there are no codes, no relocations or no output. */ if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) || sec->reloc_count == 0 - || discarded_section (sec)) + || bfd_is_abs_section (sec->output_section)) return TRUE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; @@ -2609,6 +2685,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */ if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC + && irel->r_offset >= 2 && bfd_get_8 (input_bfd, contents + irel->r_offset - 2) == 0x8b) { @@ -2638,6 +2715,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, && h->type != STT_GNU_IFUNC && h != htab->elf.hdynamic && SYMBOL_REFERENCES_LOCAL (link_info, h) + && irel->r_offset >= 2 && bfd_get_8 (input_bfd, contents + irel->r_offset - 2) == 0x8b) { @@ -2716,7 +2794,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) /* Set up .got offsets for local syms, and space for local dynamic relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; @@ -2913,6 +2991,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) else if (s == htab->elf.sgotplt || s == htab->elf.iplt || s == htab->elf.igotplt + || s == htab->plt_got || s == htab->plt_eh_frame || s == htab->sdynbss) { @@ -3210,14 +3289,17 @@ elf_i386_relocate_section (bfd *output_bfd, reloc_howto_type *howto; unsigned long r_symndx; struct elf_link_hash_entry *h; + struct elf_i386_link_hash_entry *eh; Elf_Internal_Sym *sym; asection *sec; - bfd_vma off, offplt; + bfd_vma off, offplt, plt_offset; bfd_vma relocation; bfd_boolean unresolved_reloc; bfd_reloc_status_type r; unsigned int indx; int tls_type; + bfd_vma st_size; + asection *resolved_plt; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == R_386_GNU_VTINHERIT @@ -3250,6 +3332,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 @@ -3337,11 +3420,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)) @@ -3402,7 +3487,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; @@ -3436,10 +3520,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, @@ -3593,7 +3674,6 @@ elf_i386_relocate_section (bfd *output_bfd, { asection *s; Elf_Internal_Rela outrel; - bfd_byte *loc; s = htab->elf.srelgot; if (s == NULL) @@ -3603,9 +3683,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; @@ -3695,7 +3773,9 @@ elf_i386_relocate_section (bfd *output_bfd, if (h == NULL) break; - if (h->plt.offset == (bfd_vma) -1 + eh = (struct elf_i386_link_hash_entry *) h; + if ((h->plt.offset == (bfd_vma) -1 + && eh->plt_got.offset == (bfd_vma) -1) || htab->elf.splt == NULL) { /* We didn't make a PLT entry for this symbol. This @@ -3704,12 +3784,28 @@ elf_i386_relocate_section (bfd *output_bfd, break; } - relocation = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset - + h->plt.offset); + if (h->plt.offset != (bfd_vma) -1) + { + resolved_plt = htab->elf.splt; + plt_offset = h->plt.offset; + } + else + { + resolved_plt = htab->plt_got; + plt_offset = eh->plt_got.offset; + } + + relocation = (resolved_plt->output_section->vma + + resolved_plt->output_offset + + plt_offset); 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 @@ -3720,7 +3816,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 @@ -3733,7 +3829,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; @@ -3778,10 +3873,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 @@ -3796,7 +3888,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 @@ -3806,9 +3897,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 */ @@ -4034,7 +4123,6 @@ elf_i386_relocate_section (bfd *output_bfd, else { Elf_Internal_Rela outrel; - bfd_byte *loc; int dr_type; asection *sreloc; @@ -4045,6 +4133,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); @@ -4102,11 +4191,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)) { @@ -4124,11 +4209,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) @@ -4140,9 +4221,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: @@ -4324,7 +4403,6 @@ elf_i386_relocate_section (bfd *output_bfd, else { Elf_Internal_Rela outrel; - bfd_byte *loc; if (htab->elf.srelgot == NULL) abort (); @@ -4337,9 +4415,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 @@ -4363,7 +4439,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 @@ -4379,9 +4454,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) @@ -4475,6 +4548,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, struct elf_i386_link_hash_table *htab; unsigned plt_entry_size; const struct elf_i386_backend_data *abed; + struct elf_i386_link_hash_entry *eh; htab = elf_i386_hash_table (info); if (htab == NULL) @@ -4483,6 +4557,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, abed = get_elf_i386_backend_data (output_bfd); plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd); + eh = (struct elf_i386_link_hash_entry *) h; + if (h->plt.offset != (bfd_vma) -1) { bfd_vma plt_index; @@ -4586,7 +4662,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + got_offset); rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, - loc + sizeof (Elf32_External_Rel)); + loc + sizeof (Elf32_External_Rel)); } } else @@ -4647,21 +4723,65 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, plt->contents + h->plt.offset + abed->plt->plt_plt_offset); } + } + else if (eh->plt_got.offset != (bfd_vma) -1) + { + bfd_vma got_offset, plt_offset; + asection *plt, *got, *gotplt; + const bfd_byte *got_plt_entry; + + /* Offset of displacement of the indirect jump. */ + bfd_vma plt_got_offset = 2; + + /* Set the entry in the GOT procedure linkage table. */ + plt = htab->plt_got; + got = htab->elf.sgot; + gotplt = htab->elf.sgotplt; + got_offset = h->got.offset; - if (!h->def_regular) + if (got_offset == (bfd_vma) -1 + || plt == NULL + || got == NULL + || gotplt == NULL) + abort (); + + /* Fill in the entry in the GOT procedure linkage table. */ + if (! info->shared) + { + got_plt_entry = elf_i386_got_plt_entry; + got_offset += got->output_section->vma + got->output_offset; + } + else { - /* Mark the symbol as undefined, rather than as defined in - the .plt section. Leave the value if there were any - relocations where pointer equality matters (this is a clue - for the dynamic linker, to make function pointer - comparisons work between an application and shared - library), otherwise set it to zero. If a function is only - called from a binary, there is no need to slow down - shared libraries because of that. */ - sym->st_shndx = SHN_UNDEF; - if (!h->pointer_equality_needed) - sym->st_value = 0; + got_plt_entry = elf_i386_pic_got_plt_entry; + got_offset += (got->output_section->vma + + got->output_offset + - gotplt->output_section->vma + - gotplt->output_offset); } + + plt_offset = eh->plt_got.offset; + memcpy (plt->contents + plt_offset, got_plt_entry, + sizeof (elf_i386_got_plt_entry)); + bfd_put_32 (output_bfd, got_offset, + plt->contents + plt_offset + plt_got_offset); + } + + if (!h->def_regular + && (h->plt.offset != (bfd_vma) -1 + || eh->plt_got.offset != (bfd_vma) -1)) + { + /* Mark the symbol as undefined, rather than as defined in + the .plt section. Leave the value if there were any + relocations where pointer equality matters (this is a clue + for the dynamic linker, to make function pointer + comparisons work between an application and shared + library), otherwise set it to zero. If a function is only + called from a binary, there is no need to slow down + shared libraries because of that. */ + sym->st_shndx = SHN_UNDEF; + if (!h->pointer_equality_needed) + sym->st_value = 0; } if (h->got.offset != (bfd_vma) -1 @@ -4669,7 +4789,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. */ @@ -4727,15 +4846,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. */ @@ -4749,9 +4865,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; @@ -4776,7 +4890,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)) { @@ -5030,14 +5146,91 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, return TRUE; } -/* Return address for Ith PLT stub in section PLT, for relocation REL - or (bfd_vma) -1 if it should not be included. */ +/* Return an array of PLT entry symbol values. */ -static bfd_vma -elf_i386_plt_sym_val (bfd_vma i, const asection *plt, - const arelent *rel ATTRIBUTE_UNUSED) +static bfd_vma * +elf_i386_get_plt_sym_val (bfd *abfd, asymbol **dynsyms, asection *plt, + asection *relplt) { - return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner); + bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); + arelent *p; + long count, i; + bfd_vma *plt_sym_val; + bfd_vma plt_offset; + bfd_byte *plt_contents; + const struct elf_i386_backend_data *bed + = get_elf_i386_backend_data (abfd); + Elf_Internal_Shdr *hdr; + + /* Get the .plt section contents. */ + plt_contents = (bfd_byte *) bfd_malloc (plt->size); + if (plt_contents == NULL) + return NULL; + if (!bfd_get_section_contents (abfd, (asection *) plt, + plt_contents, 0, plt->size)) + { +bad_return: + free (plt_contents); + return NULL; + } + + slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; + if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE)) + goto bad_return; + + hdr = &elf_section_data (relplt)->this_hdr; + count = relplt->size / hdr->sh_entsize; + + plt_sym_val = (bfd_vma *) bfd_malloc (sizeof (bfd_vma) * count); + if (plt_sym_val == NULL) + goto bad_return; + + for (i = 0; i < count; i++, p++) + plt_sym_val[i] = -1; + + plt_offset = bed->plt->plt_entry_size; + p = relplt->relocation; + for (i = 0; i < count; i++, p++) + { + long reloc_index; + + /* Skip unknown relocation. PR 17512: file: bc9d6cf5. */ + if (p->howto == NULL) + continue; + + if (p->howto->type != R_386_JUMP_SLOT + && p->howto->type != R_386_IRELATIVE) + continue; + + reloc_index = H_GET_32 (abfd, (plt_contents + plt_offset + + bed->plt->plt_reloc_offset)); + reloc_index /= sizeof (Elf32_External_Rel); + if (reloc_index >= count) + abort (); + plt_sym_val[reloc_index] = plt->vma + plt_offset; + plt_offset += bed->plt->plt_entry_size; + } + + free (plt_contents); + + return plt_sym_val; +} + +/* Similar to _bfd_elf_get_synthetic_symtab. */ + +static long +elf_i386_get_synthetic_symtab (bfd *abfd, + long symcount, + asymbol **syms, + long dynsymcount, + asymbol **dynsyms, + asymbol **ret) +{ + asection *plt = bfd_get_section_by_name (abfd, ".plt"); + return _bfd_elf_ifunc_get_synthetic_symtab (abfd, symcount, syms, + dynsymcount, dynsyms, ret, + plt, + elf_i386_get_plt_sym_val); } /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ @@ -5058,22 +5251,23 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h) static bfd_boolean elf_i386_add_symbol_hook (bfd * abfd, - struct bfd_link_info * info ATTRIBUTE_UNUSED, + struct bfd_link_info * info, Elf_Internal_Sym * sym, const char ** namep ATTRIBUTE_UNUSED, flagword * flagsp ATTRIBUTE_UNUSED, asection ** secp ATTRIBUTE_UNUSED, bfd_vma * valp ATTRIBUTE_UNUSED) { - if ((abfd->flags & DYNAMIC) == 0 - && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; return TRUE; } -#define TARGET_LITTLE_SYM bfd_elf32_i386_vec +#define TARGET_LITTLE_SYM i386_elf32_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 #define ELF_TARGET_ID I386_ELF_DATA @@ -5096,9 +5290,9 @@ elf_i386_add_symbol_hook (bfd * abfd, #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_link_hash_table_free elf_i386_link_hash_table_free #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 bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab #define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol #define elf_backend_relocs_compatible _bfd_elf_relocs_compatible @@ -5118,18 +5312,15 @@ elf_i386_add_symbol_hook (bfd * abfd, #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 #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" /* FreeBSD support. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec +#define TARGET_LITTLE_SYM i386_elf32_fbsd_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-freebsd" #undef ELF_OSABI @@ -5142,11 +5333,14 @@ 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. */ - memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); + { + /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ + Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); + memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); + } #endif } @@ -5162,7 +5356,7 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) /* Solaris 2. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_i386_sol2_vec +#define TARGET_LITTLE_SYM i386_elf32_sol2_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-sol2" @@ -5190,7 +5384,7 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) /* Native Client support. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec +#define TARGET_LITTLE_SYM i386_elf32_nacl_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-nacl" #undef elf32_bed @@ -5204,7 +5398,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. */ @@ -5349,24 +5542,38 @@ 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. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec +#define TARGET_LITTLE_SYM i386_elf32_vxworks_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-vxworks" #undef ELF_OSABI @@ -5384,7 +5591,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