From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10179 invoked by alias); 27 Jul 2011 22:35:11 -0000 Received: (qmail 9844 invoked by uid 22791); 27 Jul 2011 22:35:08 -0000 X-SWARE-Spam-Status: No, hits=-3.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CP 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; Wed, 27 Jul 2011 22:34:50 +0000 Received: from kpbe12.cbf.corp.google.com (kpbe12.cbf.corp.google.com [172.25.105.76]) by smtp-out.google.com with ESMTP id p6RMYnb4011303 for ; Wed, 27 Jul 2011 15:34:49 -0700 Received: from gyb11 (gyb11.prod.google.com [10.243.49.75]) by kpbe12.cbf.corp.google.com with ESMTP id p6RMXxjw002023 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Wed, 27 Jul 2011 15:34:48 -0700 Received: by gyb11 with SMTP id 11so2102724gyb.35 for ; Wed, 27 Jul 2011 15:34:48 -0700 (PDT) Received: by 10.142.52.8 with SMTP id z8mr212037wfz.76.1311806087776; Wed, 27 Jul 2011 15:34:47 -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 z6sm296366pbc.94.2011.07.27.15.34.46 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 27 Jul 2011 15:34:47 -0700 (PDT) Date: Thu, 28 Jul 2011 09:16:00 -0000 Message-Id: From: Roland McGrath To: binutils@sourceware.org Subject: [PATCH] parameterize elf32-i386 PLT generation 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/msg00248.txt.bz2 This patch must follow the "clean up elf32-i386-vxworks hooking mechanism" change I just posted, not yet committed. This parameterizes the elf32-i386 PLT generation code to be table-driven. This is preparatory to a reworked addition of the elf32-i386-nacl backend, which I first posted yesterday. That target uses different PLT code sequences and a different PLT entry size. Ok for trunk? Thanks, Roland bfd/ * elf32-i386.c (struct elf_i386_plt_layout): New type. (GET_PLT_ENTRY_SIZE): New macro. (elf_i386_plt): New variable. (struct elf_i386_backend_data): New member `plt'. (elf_i386_arch_bed): Add initializer for it. (elf_i386_vxworks_arch_bed): Likewise. (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_plt_layout members for PLT details. (elf_i386_finish_dynamic_sections): Likewise. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 39050ec..cb16faf 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -614,6 +614,62 @@ static const bfd_byte elf_i386_eh_frame_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; +struct elf_i386_plt_layout +{ + /* The first entry in an absolute procedure linkage table looks like this. */ + const bfd_byte *plt0_entry; + unsigned int plt0_entry_size; + + /* 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 looks 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_PLT_ENTRY_SIZE(abfd) \ + get_elf_i386_backend_data (abfd)->plt->plt_entry_size + +/* These are the standard parameters. */ +static const struct elf_i386_plt_layout elf_i386_plt = + { + elf_i386_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_plt0_entry), /* plt0_entry_size */ + 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 */ + }; + + /* 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 @@ -624,6 +680,9 @@ static const bfd_byte elf_i386_eh_frame_plt[] = struct elf_i386_backend_data { + /* Parameters describing PLT generation. */ + const struct elf_i386_plt_layout *plt; + /* Value used to fill the unused bytes of the first PLT entry. */ bfd_byte plt0_pad_byte; @@ -638,6 +697,7 @@ struct elf_i386_backend_data /* These are the standard parameters. */ static const struct elf_i386_backend_data elf_i386_arch_bed = { + &elf_i386_plt, /* plt */ 0, /* plt0_pad_byte */ 0, /* is_vxworks */ }; @@ -2157,6 +2217,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; @@ -2168,13 +2229,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) { @@ -2195,7 +2257,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; @@ -2212,7 +2274,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. */ @@ -2233,7 +2295,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: @@ -2959,6 +3021,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)); @@ -2978,6 +3041,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++) @@ -3244,13 +3309,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; } @@ -4246,11 +4311,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; @@ -4299,27 +4369,28 @@ 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->plt_entry, + abed->plt->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->plt_got_offset); - if (get_elf_i386_backend_data (output_bfd)->is_vxworks) + if (abed->is_vxworks) { int s, k, reloc_index; @@ -4327,7 +4398,8 @@ 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->plt_entry_size) + / abed->plt->plt_entry_size); /* K: Number of relocations for PLTResolve. */ if (info->shared) k = PLTRESOLVE_RELOCS_SHLIB; @@ -4357,19 +4429,23 @@ 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->plt->pic_plt_entry, + abed->plt->plt_entry_size); bfd_put_32 (output_bfd, got_offset, - plt->contents + h->plt.offset + 2); + plt->contents + h->plt.offset + + abed->plt->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->plt_reloc_offset); + bfd_put_32 (output_bfd, - (h->plt.offset + + abed->plt->plt_plt_offset + 4), + plt->contents + h->plt.offset + + abed->plt->plt_plt_offset); } /* Fill in the entry in the global offset table. */ @@ -4377,7 +4453,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, (plt->output_section->vma + plt->output_offset + h->plt.offset - + 6), + + abed->plt->plt_lazy_offset), gotplt->contents + got_offset); /* Fill in the entry in the .rel.plt section. */ @@ -4518,7 +4594,7 @@ do_glob_dat: is relative to the ".got" section. */ if (sym != NULL && (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || (!get_elf_i386_backend_data (output_bfd)->is_vxworks + || (!abed->is_vxworks && h == htab->elf.hgot))) sym->st_shndx = SHN_ABS; @@ -4568,6 +4644,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) @@ -4575,6 +4652,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) { @@ -4595,8 +4673,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { default: - if (get_elf_i386_backend_data (output_bfd)->is_vxworks - && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) + if (abed->is_vxworks + && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) break; continue; @@ -4649,31 +4727,33 @@ 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), - get_elf_i386_backend_data (output_bfd)->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); + memcpy (htab->elf.splt->contents, abed->plt->pic_plt0_entry, + abed->plt->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt->plt0_entry_size, + abed->plt0_pad_byte, + abed->plt->plt_entry_size - abed->plt->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), - get_elf_i386_backend_data (output_bfd)->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); + memcpy (htab->elf.splt->contents, abed->plt->plt0_entry, + abed->plt->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt->plt0_entry_size, + abed->plt0_pad_byte, + abed->plt->plt_entry_size - abed->plt->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->plt->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->plt->plt0_got2_offset); - if (get_elf_i386_backend_data (output_bfd)->is_vxworks) + if (abed->is_vxworks) { Elf_Internal_Rela rel; @@ -4682,14 +4762,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->plt->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->plt->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 + @@ -4703,10 +4783,10 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, ->this_hdr.sh_entsize = 4; /* Correct the .rel.plt.unloaded relocations. */ - if (get_elf_i386_backend_data (output_bfd)->is_vxworks - && !info->shared) + if (abed->is_vxworks && !info->shared) { - int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1; + int num_plts = (htab->elf.splt->size + / abed->plt->plt_entry_size) - 1; unsigned char *p; p = htab->srelplt2->contents; @@ -4800,7 +4880,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. */ @@ -4960,6 +5040,7 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed = { + &elf_i386_plt, /* plt */ 0x90, /* plt0_pad_byte */ 1, /* is_vxworks */ };