From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20691 invoked by alias); 26 Jul 2011 20:56:45 -0000 Received: (qmail 20673 invoked by uid 22791); 26 Jul 2011 20:56:42 -0000 X-SWARE-Spam-Status: No, hits=-3.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CP,TW_FX X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 26 Jul 2011 20:56:24 +0000 Received: from wpaz29.hot.corp.google.com (wpaz29.hot.corp.google.com [172.24.198.93]) by smtp-out.google.com with ESMTP id p6QKuNtb020371 for ; Tue, 26 Jul 2011 13:56:23 -0700 Received: from pzk6 (pzk6.prod.google.com [10.243.19.134]) by wpaz29.hot.corp.google.com with ESMTP id p6QKtxj8016345 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Tue, 26 Jul 2011 13:56:22 -0700 Received: by pzk6 with SMTP id 6so1355425pzk.26 for ; Tue, 26 Jul 2011 13:56:22 -0700 (PDT) Received: by 10.68.2.200 with SMTP id 8mr3471350pbw.70.1311713782106; Tue, 26 Jul 2011 13:56:22 -0700 (PDT) Received: from frobland.mtv.corp.google.com.google.com ([2620:0:1000:1b01:be30:5bff:fed3:d2a]) by mx.google.com with ESMTPS id i9sm917420pbk.52.2011.07.26.13.56.20 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 26 Jul 2011 13:56:21 -0700 (PDT) Date: Tue, 26 Jul 2011 21:20:00 -0000 Message-Id: From: Roland McGrath To: binutils@sourceware.org Subject: [PATCH] BFD vector for elf32-i386-nacl X-System-Of-Record: true Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2011-07/txt/msg00219.txt.bz2 This patch adds the BFD target vector for the new target elf32-i386-nacl. This is to support Native Client (http://code.google.com/p/nativeclient/), which is a new pseudo-operating system that uses vanilla ELF but has a significantly nonstandard ABI. (It is already known to config.sub as 'nacl'.) This is far from being complete support for this target, but it should be everything that will be needed in BFD proper. It's gotten only the lightest testing, and of course the target-specific details are subject to potential fixes or changes later. I'm floating this early primarily to get feedback about the parameterization I've added to the shared elf32-i386.c code. The approach I took seems pretty clean to me, and moreso than e.g. the way vxworks was handled. I have tested that the i686-linux target still passes check-binutils and check-ld. I'm not sure that tests much about correct PLT generation, which is the only area of the shared code really touched here. If there are other good ways to test that (short of rebuilding a whole OS with this linker), please let me know. Ok for trunk? Thanks, Roland bfd/ 2011-07-25 Roland McGrath * elf32-i386.c (NACL_PLT_ENTRY_SIZE, NACLMASK): New macros. (elf_i386_nacl_plt0_entry): New variable. (elf_i386_plt_entry): New variable. (elf_i386_nacl_pic_plt0_entry): New variable. (elf_i386_nacl_pic_plt_entry): New variable. (elf_i386_nacl_arch_bed): New variable. (elf_backend_arch_data): New macro setting for elf_i386_nacl_vec stanza. (elf_backend_plt_alignment): Likewise. * elf32-i386.c (struct elf_i386_backend_data): New type. (get_elf_i386_backend_data): New macro. (GET_PLT_ENTRY_SIZE): New macro. (elf_i386_arch_bed): New variable. (elf_backend_arch_data): New macro. (elf_i386_allocate_dynrelocs): Use GET_PLT_ENTRY_SIZE. (elf_i386_plt_sym_val): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. Also use other elf_i386_backend_data members for PLT details. (elf_i386_finish_dynamic_sections): Likewise. * elf-bfd.h (elf_backend_data): New member arch_backend_data. * elfxx-target.h (elf_backend_arch_data): New macro. (elfNN_bed): Use it as initializer for the new member. * config.bfd: Handle i[3-7]86-*-nacl*. * elf32-i386.c (bfd_elf32_i386_nacl_vec): New backend vector stanza. * targets.c: Support bfd_elf32_i386_nacl_vec. * configure.in: Likewise. * configure: Regenerated. diff --git a/bfd/config.bfd b/bfd/config.bfd index 3f5b9a1..4cb689d 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -566,6 +566,11 @@ case "${targ}" in targ_selvecs="i386linux_vec i386pei_vec" targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf32_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" ;; + i[3-7]86-*-nacl*) + targ_defvec=bfd_elf32_i386_nacl_vec + targ_selvecs="bfd_elf32_i386_vec" + #XXX targ64_selvecs="bfd_elf64_x86_64_nacl_vec bfd_elf32_x86_64_nacl_vec bfd_elf64_x86_64_vec bfd_elf32_x86_64_vec" + ;; #ifdef BFD64 x86_64-*-darwin*) targ_defvec=mach_o_x86_64_vec diff --git a/bfd/configure b/bfd/configure index 40c17db..06f7839 100755 --- a/bfd/configure +++ b/bfd/configure @@ -15210,6 +15210,7 @@ do bfd_elf32_i370_vec) tb="$tb elf32-i370.lo elf32.lo $elf" ;; bfd_elf32_i386_sol2_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_freebsd_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; + bfd_elf32_i386_nacl_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_vxworks_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i860_little_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; diff --git a/bfd/configure.in b/bfd/configure.in index e1ae5fc..530d4ee 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -709,6 +709,7 @@ do bfd_elf32_i370_vec) tb="$tb elf32-i370.lo elf32.lo $elf" ;; bfd_elf32_i386_sol2_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_freebsd_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; + bfd_elf32_i386_nacl_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_vxworks_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i386_vec) tb="$tb elf32-i386.lo elf-ifunc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_i860_little_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index bf63ee8..e6ea580 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -714,6 +714,10 @@ struct elf_backend_data /* The BFD flags applied to sections created for dynamic linking. */ flagword dynamic_sec_flags; + /* Architecture-specific data for this backend. + This is actually a pointer to some type like struct elf_ARCH_data. */ + const void *arch_data; + /* A function to translate an ELF RELA relocation to a BFD arelent structure. */ void (*elf_info_to_howto) diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index b42e1a2..1b0cbb8 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -614,6 +614,72 @@ static const bfd_byte elf_i386_eh_frame_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; +struct elf_i386_backend_data +{ + /* The first entry in an absolute procedure linkage table looks like this. */ + const bfd_byte *plt0_entry; + unsigned int plt0_entry_size; + + /* That is padded to plt_entry_size with this byte. */ + bfd_byte plt0_pad_byte; + + /* Offsets into plt0_entry that are to be replaced with GOT[1] and GOT[2]. */ + unsigned int plt0_got1_offset; + unsigned int plt0_got2_offset; + + /* Later entries in an absolute procedure linkage table look like this. */ + const bfd_byte *plt_entry; + unsigned int plt_entry_size; + + /* Offsets into plt_entry that are to be replaced with... */ + unsigned int plt_got_offset; /* ... address of this symbol in .got. */ + unsigned int plt_reloc_offset; /* ... offset into relocation table. */ + unsigned int plt_plt_offset; /* ... offset to start of .plt. */ + + /* Offset into plt_entry where the initial value of the GOT entry points. */ + unsigned int plt_lazy_offset; + + /* The first entry in a PIC procedure linkage table look like this. */ + const bfd_byte *pic_plt0_entry; + + /* Subsequent entries in a PIC procedure linkage table look like this. */ + const bfd_byte *pic_plt_entry; + + /* .eh_frame covering the .plt section. */ + const bfd_byte *eh_frame_plt; + unsigned int eh_frame_plt_size; +}; + +#define get_elf_i386_backend_data(abfd) \ + ((const struct elf_i386_backend_data *) \ + get_elf_backend_data (abfd)->arch_data) + +#define GET_PLT_ENTRY_SIZE(abfd) \ + get_elf_i386_backend_data (abfd)->plt_entry_size + +/* These are the standard parameters. */ +static const struct elf_i386_backend_data elf_i386_arch_bed = + { + elf_i386_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_plt0_entry), /* plt0_entry_size */ + 0, /* plt0_pad_byte */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + elf_i386_plt_entry, /* plt_entry */ + PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt_got_offset */ + 7, /* plt_reloc_offset */ + 12, /* plt_plt_offset */ + 6, /* plt_lazy_offset */ + elf_i386_pic_plt0_entry, /* pic_plt0_entry */ + elf_i386_pic_plt_entry, /* pic_plt_entry */ + elf_i386_eh_frame_plt, /* eh_frame_plt */ + sizeof (elf_i386_eh_frame_plt), /* eh_frame_plt_size */ + }; + +#define elf_backend_arch_data &elf_i386_arch_bed + + /* On VxWorks, the .rel.plt.unloaded section has absolute relocations for the PLTResolve stub and then for each PLT entry. */ #define PLTRESOLVE_RELOCS_SHLIB 0 @@ -2140,6 +2206,7 @@ elf_i386_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_dyn_relocs *p; + unsigned plt_entry_size; if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -2151,13 +2218,14 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (htab == NULL) return FALSE; + plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd); + /* 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); + return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, + plt_entry_size, 4); else if (htab->elf.dynamic_sections_created && h->plt.refcount > 0) { @@ -2178,7 +2246,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; @@ -2195,7 +2263,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } /* Make room for this entry. */ - s->size += PLT_ENTRY_SIZE; + 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. */ @@ -2215,7 +2283,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ - if (h->plt.offset == PLT_ENTRY_SIZE) + if (h->plt.offset == plt_entry_size) htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2); /* There are two extra relocations for each subsequent PLT entry: @@ -2942,6 +3010,7 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; bfd_boolean is_vxworks_tls; + unsigned plt_entry_size; BFD_ASSERT (is_i386_elf (input_bfd)); @@ -2960,6 +3029,8 @@ elf_i386_relocate_section (bfd *output_bfd, elf_i386_set_tls_module_base (info); + plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd); + rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) @@ -3226,13 +3297,13 @@ elf_i386_relocate_section (bfd *output_bfd, if (htab->elf.splt != NULL) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; + plt_index = h->plt.offset / plt_entry_size - 1; off = (plt_index + 3) * 4; base_got = htab->elf.sgotplt; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; + plt_index = h->plt.offset / plt_entry_size; off = plt_index * 4; base_got = htab->elf.igotplt; } @@ -4228,11 +4299,16 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Sym *sym) { struct elf_i386_link_hash_table *htab; + unsigned plt_entry_size; + const struct elf_i386_backend_data *abed; htab = elf_i386_hash_table (info); if (htab == NULL) return FALSE; + abed = get_elf_i386_backend_data (output_bfd); + plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd); + if (h->plt.offset != (bfd_vma) -1) { bfd_vma plt_index; @@ -4281,25 +4357,25 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, if (plt == htab->elf.splt) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; + plt_index = h->plt.offset / plt_entry_size - 1; got_offset = (plt_index + 3) * 4; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; + plt_index = h->plt.offset / plt_entry_size; got_offset = plt_index * 4; } /* Fill in the entry in the procedure linkage table. */ if (! info->shared) { - memcpy (plt->contents + h->plt.offset, elf_i386_plt_entry, - PLT_ENTRY_SIZE); + memcpy (plt->contents + h->plt.offset, abed->plt_entry, + abed->plt_entry_size); bfd_put_32 (output_bfd, (gotplt->output_section->vma + gotplt->output_offset + got_offset), - plt->contents + h->plt.offset + 2); + plt->contents + h->plt.offset + abed->plt_got_offset); if (htab->is_vxworks) { @@ -4309,7 +4385,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, for this PLT entry. */ /* S: Current slot number (zero-based). */ - s = (h->plt.offset - PLT_ENTRY_SIZE) / PLT_ENTRY_SIZE; + s = (h->plt.offset - abed->plt_entry_size) / abed->plt_entry_size; /* K: Number of relocations for PLTResolve. */ if (info->shared) k = PLTRESOLVE_RELOCS_SHLIB; @@ -4339,19 +4415,19 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, } else { - memcpy (plt->contents + h->plt.offset, elf_i386_pic_plt_entry, - PLT_ENTRY_SIZE); + memcpy (plt->contents + h->plt.offset, abed->pic_plt_entry, + abed->plt_entry_size); bfd_put_32 (output_bfd, got_offset, - plt->contents + h->plt.offset + 2); + plt->contents + h->plt.offset + abed->plt_got_offset); } /* Don't fill PLT entry for static executables. */ if (plt == htab->elf.splt) { bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), - plt->contents + h->plt.offset + 7); - bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), - plt->contents + h->plt.offset + 12); + plt->contents + h->plt.offset + abed->plt_reloc_offset); + bfd_put_32 (output_bfd, - (h->plt.offset + abed->plt_plt_offset + 4), + plt->contents + h->plt.offset + abed->plt_plt_offset); } /* Fill in the entry in the global offset table. */ @@ -4359,7 +4435,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, (plt->output_section->vma + plt->output_offset + h->plt.offset - + 6), + + abed->plt_lazy_offset), gotplt->contents + got_offset); /* Fill in the entry in the .rel.plt section. */ @@ -4549,6 +4625,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, struct elf_i386_link_hash_table *htab; bfd *dynobj; asection *sdyn; + const struct elf_i386_backend_data *abed; htab = elf_i386_hash_table (info); if (htab == NULL) @@ -4556,6 +4633,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, dynobj = htab->elf.dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + abed = get_elf_i386_backend_data (output_bfd); if (htab->elf.dynamic_sections_created) { @@ -4630,29 +4708,29 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, { if (info->shared) { - memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry, - sizeof (elf_i386_pic_plt0_entry)); - memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry), + memcpy (htab->elf.splt->contents, abed->pic_plt0_entry, + abed->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt0_entry_size, htab->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); + abed->plt_entry_size - abed->plt0_entry_size); } else { - memcpy (htab->elf.splt->contents, elf_i386_plt0_entry, - sizeof(elf_i386_plt0_entry)); - memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry), + memcpy (htab->elf.splt->contents, abed->plt0_entry, + abed->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt0_entry_size, htab->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); + abed->plt_entry_size - abed->plt0_entry_size); bfd_put_32 (output_bfd, (htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset + 4), - htab->elf.splt->contents + 2); + htab->elf.splt->contents + abed->plt0_got1_offset); bfd_put_32 (output_bfd, (htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset + 8), - htab->elf.splt->contents + 8); + htab->elf.splt->contents + abed->plt0_got2_offset); if (htab->is_vxworks) { @@ -4663,14 +4741,14 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, the PLT directly. */ rel.r_offset = (htab->elf.splt->output_section->vma + htab->elf.splt->output_offset - + 2); + + abed->plt0_got1_offset); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, htab->srelplt2->contents); /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ rel.r_offset = (htab->elf.splt->output_section->vma + htab->elf.splt->output_offset - + 8); + + abed->plt0_got2_offset); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, htab->srelplt2->contents + @@ -4686,7 +4764,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, /* Correct the .rel.plt.unloaded relocations. */ if (htab->is_vxworks && !info->shared) { - int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1; + int num_plts = (htab->elf.splt->size / abed->plt_entry_size) - 1; unsigned char *p; p = htab->srelplt2->contents; @@ -4780,7 +4858,7 @@ static bfd_vma elf_i386_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel ATTRIBUTE_UNUSED) { - return plt->vma + (i + 1) * PLT_ENTRY_SIZE; + return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner); } /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ @@ -4930,6 +5008,164 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #include "elf32-target.h" +/* Native Client support. */ + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elf32-i386-nacl" +#undef elf32_bed +#define elf32_bed elf32_i386_nacl_bed + +#undef ELF_MAXPAGESIZE +#define ELF_MAXPAGESIZE 0x10000 + +/* Restore defaults. */ +#undef ELF_OSABI +#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. */ + +#undef elf_backend_plt_alignment +#define elf_backend_plt_alignment 5 +#define NACL_PLT_ENTRY_SIZE 64 +#define NACLMASK 0xe0 /* 32-byte alignment mask. */ + +static const bfd_byte elf_i386_nacl_plt0_entry[] = + { + 0xff, 0x35, /* pushl contents of address */ + 0, 0, 0, 0, /* replaced with address of .got + 4. */ + 0x8b, 0x0d, /* movl contents of address, %ecx */ + 0, 0, 0, 0, /* replaced with address of .got + 8. */ + 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1 /* jmp *%ecx */ + }; + +static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] = + { + 0x8b, 0x0d, /* movl contents of address, %ecx */ + 0, 0, 0, 0, /* replaced with GOT slot address. */ + 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + + /* Lazy GOT entries point here (32-byte aligned). */ + 0x68, /* pushl immediate */ + 0, 0, 0, 0, /* replaced with reloc offset. */ + 0xe9, /* jmp relative */ + 0, 0, 0, 0, /* replaced with offset to .plt. */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90 + }; + +static const bfd_byte +elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] = + { + 0xff, 0x73, 0x04, /* pushl 4(%ebx) */ + 0x8b, 0x4b, 0x08, /* mov 0x8(%ebx), %ecx */ + 0x83, 0xe1, 0xe0, /* and $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + 0x90 /* nop */ + }; + +static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] = + { + 0x8b, 0x8b, /* movl offset(%ebx), %ecx */ + 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ + 0x83, 0xe1, 0xe0, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + + /* Lazy GOT entries point here (32-byte aligned). */ + 0x68, /* pushl immediate */ + 0, 0, 0, 0, /* replaced with offset into relocation table. */ + 0xe9, /* jmp relative */ + 0, 0, 0, 0, /* replaced with offset to start of .plt. */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90 + }; + +static const bfd_byte elf_i386_nacl_eh_frame_plt[] = + { +#if (PLT_CIE_LENGTH != 20 \ + || PLT_FDE_LENGTH != 36 \ + || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8 \ + || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12) +# error "Need elf_i386_backend_data parameters for eh_frame_plt offsets!" +#endif + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x7c, /* Data alignment factor: -4 */ + 8, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */ + DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_386_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */ + DW_CFA_advance_loc + 58, /* DW_CFA_advance_loc: 58 to __PLT__+64 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 13, /* Block length */ + DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */ + DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */ + DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge, + DW_OP_lit2, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop + }; + +static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = + { + elf_i386_nacl_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ + 0x90, /* plt0_pad_byte: nop insn */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + elf_i386_nacl_plt_entry, /* plt_entry */ + NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt_got_offset */ + 33, /* plt_reloc_offset */ + 38, /* plt_plt_offset */ + 32, /* plt_lazy_offset */ + elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */ + elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */ + elf_i386_nacl_eh_frame_plt, /* eh_frame_plt */ + sizeof (elf_i386_nacl_eh_frame_plt),/* eh_frame_plt_size */ + }; + +#undef elf_backend_arch_data +#define elf_backend_arch_data &elf_i386_nacl_arch_bed + +#include "elf32-target.h" + /* VxWorks support. */ #undef TARGET_LITTLE_SYM @@ -4937,6 +5173,10 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-vxworks" #undef ELF_OSABI +#undef elf_backend_plt_alignment +#define elf_backend_plt_alignment 4 +#undef elf_backend_arch_data +#define elf_backend_arch_data &elf_i386_arch_bed /* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */ diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index b51ac9f..96ecce3 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -310,6 +310,10 @@ #define elf_info_to_howto_rel 0 #endif +#ifndef elf_backend_arch_data +#define elf_backend_arch_data NULL +#endif + #ifndef ELF_TARGET_ID #define ELF_TARGET_ID GENERIC_ELF_DATA #endif @@ -668,6 +672,7 @@ static struct elf_backend_data elfNN_bed = ELF_MINPAGESIZE, /* minpagesize */ ELF_COMMONPAGESIZE, /* commonpagesize */ ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */ + elf_backend_arch_data, elf_info_to_howto, elf_info_to_howto_rel, elf_backend_sym_is_global, diff --git a/bfd/targets.c b/bfd/targets.c index 0bfc104..c34ce69 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -1,6 +1,6 @@ /* Generic target-file-type support for the BFD library. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -618,6 +618,7 @@ extern const bfd_target bfd_elf32_hppa_nbsd_vec; extern const bfd_target bfd_elf32_hppa_vec; extern const bfd_target bfd_elf32_i370_vec; extern const bfd_target bfd_elf32_i386_freebsd_vec; +extern const bfd_target bfd_elf32_i386_nacl_vec; extern const bfd_target bfd_elf32_i386_sol2_vec; extern const bfd_target bfd_elf32_i386_vxworks_vec; extern const bfd_target bfd_elf32_i386_vec; @@ -978,6 +979,7 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_hppa_vec, &bfd_elf32_i370_vec, &bfd_elf32_i386_freebsd_vec, + &bfd_elf32_i386_nacl_vec, &bfd_elf32_i386_sol2_vec, &bfd_elf32_i386_vxworks_vec, &bfd_elf32_i386_vec,