This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb/binutils-2_28-branch] i386/x86-64: Add unwind info for .plt.got section


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=326e3a04a5fa4fbf85b4cc4188a355d2715e5d17

commit 326e3a04a5fa4fbf85b4cc4188a355d2715e5d17
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Jan 10 13:31:59 2017 -0800

    i386/x86-64: Add unwind info for .plt.got section
    
    When there are both PLT and GOT references to the same function symbol,
    linker combines GOTPLT and GOT slots into a single GOT slot and create
    an entry in .plt.got section for PLT access via the GOT slot.  This
    patch adds unwind info for .plt.got section and places .plt.got section
    after .plt section for x32.  .eh_frame section covering PLT sections
    should be aligned to 4 bytes for i386 and x32.
    
    bfd/
    
    2017-01-13  H.J. Lu  <hongjiu.lu@intel.com>
    
    	Backport from master
    	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
    
    	* elf32-i386.c (elf_i386_check_relocs): Align .eh_frame section
    	to 4 bytes.
    	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Align
    	.eh_frame section to 4 bytes for x32.
    	(elf_x86_64_check_relocs): Likewise.
    
    	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
    
    	PR ld/20830
    	* elf32-i386.c (elf_i386_eh_frame_plt_got): New.
    	(PLT_GOT_FDE_LENGTH): Likewise.
    	(elf_i386_plt_layout): Add eh_frame_plt_got and
    	eh_frame_plt_got_size.
    	(elf_i386_plt): Updated.
    	(elf_i386_link_hash_table): Add plt_got_eh_frame.
    	(elf_i386_check_relocs): Create .eh_frame section for .plt.got.
    	(elf_i386_size_dynamic_sections): Allocate and initialize
    	.eh_frame section for .plt.got.
    	(elf_i386_finish_dynamic_sections): Adjust .eh_frame section for
    	.plt.got.
    	(elf_i386_nacl_plt): Add FIXME for eh_frame_plt_got and
    	eh_frame_plt_got_size.
    	* elf64-x86-64.c (elf_x86_64_eh_frame_plt_got): New.
    	(PLT_GOT_FDE_LENGTH): Likewise.
    	(elf_x86_64_backend_data): Add eh_frame_plt_got and
    	eh_frame_plt_got_size.
    	(elf_x86_64_arch_bed): Updated.
    	(elf_x86_64_bnd_arch_bed): Add FIXME for eh_frame_plt_got and
    	eh_frame_plt_got_size.
    	(elf_x86_64_nacl_arch_bed): Likewise.
    	(elf_x86_64_link_hash_table): Add plt_got_eh_frame.
    	(elf_x86_64_check_relocs): Create .eh_frame section for .plt.got.
    	(elf_x86_64_size_dynamic_sections): Allocate and initialize
    	.eh_frame section for .plt.got.
    	(elf_x86_64_finish_dynamic_sections): Adjust .eh_frame section
    	for .plt.got.
    
    ld/
    
    2017-01-13  H.J. Lu  <hongjiu.lu@intel.com>
    
    	Backport from master
    	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
    
    	* testsuite/ld-x86-64/pr20830b.d: Updated.
    
    	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
    
    	* emulparams/elf32_x86_64.sh (TINY_READONLY_SECTION): New.
    	* testsuite/ld-x86-64/pr20830.d: Renamed to ...
    	* testsuite/ld-x86-64/pr20830a.d: This.  Updated.
    	* testsuite/ld-x86-64/pr20830b.d: New file.
    	* testsuite/ld-x86-64/x86-64.exp: Rename pr20830 to pr20830a.
    	Run pr20830b.
    
    	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
    
    	PR ld/20830
    	* testsuite/ld-i386/i386.exp: Run pr20830.
    	* testsuite/ld-x86-64/x86-64.exp: Likewise.
    	* testsuite/ld-i386/pr20830.d: New file.
    	* testsuite/ld-i386/pr20830.s: Likewise.
    	* testsuite/ld-x86-64/pr20830.d: Likewise.
    	* testsuite/ld-x86-64/pr20830.s: Likewise.

Diff:
---
 bfd/ChangeLog                     |  42 ++++++++++++
 bfd/elf32-i386.c                  | 116 ++++++++++++++++++++++++++++++---
 bfd/elf64-x86-64.c                | 131 +++++++++++++++++++++++++++++++++++---
 ld/ChangeLog                      |  26 ++++++++
 ld/emulparams/elf32_x86_64.sh     |   4 ++
 ld/testsuite/ld-i386/i386.exp     |   1 +
 ld/testsuite/ld-i386/pr20830.d    |  60 +++++++++++++++++
 ld/testsuite/ld-i386/pr20830.s    |   8 +++
 ld/testsuite/ld-x86-64/pr20830.s  |   8 +++
 ld/testsuite/ld-x86-64/pr20830a.d |  72 +++++++++++++++++++++
 ld/testsuite/ld-x86-64/pr20830b.d |  60 +++++++++++++++++
 ld/testsuite/ld-x86-64/x86-64.exp |   2 +
 12 files changed, 513 insertions(+), 17 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7f9e4ef..f1fd51f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -3,6 +3,48 @@
 	Backport from master
 	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* elf32-i386.c (elf_i386_check_relocs): Align .eh_frame section
+	to 4 bytes.
+	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Align
+	.eh_frame section to 4 bytes for x32.
+	(elf_x86_64_check_relocs): Likewise.
+
+	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR ld/20830
+	* elf32-i386.c (elf_i386_eh_frame_plt_got): New.
+	(PLT_GOT_FDE_LENGTH): Likewise.
+	(elf_i386_plt_layout): Add eh_frame_plt_got and
+	eh_frame_plt_got_size.
+	(elf_i386_plt): Updated.
+	(elf_i386_link_hash_table): Add plt_got_eh_frame.
+	(elf_i386_check_relocs): Create .eh_frame section for .plt.got.
+	(elf_i386_size_dynamic_sections): Allocate and initialize
+	.eh_frame section for .plt.got.
+	(elf_i386_finish_dynamic_sections): Adjust .eh_frame section for
+	.plt.got.
+	(elf_i386_nacl_plt): Add FIXME for eh_frame_plt_got and
+	eh_frame_plt_got_size.
+	* elf64-x86-64.c (elf_x86_64_eh_frame_plt_got): New.
+	(PLT_GOT_FDE_LENGTH): Likewise.
+	(elf_x86_64_backend_data): Add eh_frame_plt_got and
+	eh_frame_plt_got_size.
+	(elf_x86_64_arch_bed): Updated.
+	(elf_x86_64_bnd_arch_bed): Add FIXME for eh_frame_plt_got and
+	eh_frame_plt_got_size.
+	(elf_x86_64_nacl_arch_bed): Likewise.
+	(elf_x86_64_link_hash_table): Add plt_got_eh_frame.
+	(elf_x86_64_check_relocs): Create .eh_frame section for .plt.got.
+	(elf_x86_64_size_dynamic_sections): Allocate and initialize
+	.eh_frame section for .plt.got.
+	(elf_x86_64_finish_dynamic_sections): Adjust .eh_frame section
+	for .plt.got.
+
+2017-01-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+	Backport from master
+	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* elf32-i386.c (elf_i386_size_dynamic_sections): Set
 	plt_eh_frame->size to eh_frame_plt_size and use eh_frame_plt.
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index a2da987..0860ada 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -648,6 +648,32 @@ static const bfd_byte elf_i386_eh_frame_plt[] =
   DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
 };
 
+/* .eh_frame covering the .plt.got section.  */
+
+static const bfd_byte elf_i386_eh_frame_plt_got[] =
+{
+#define PLT_GOT_FDE_LENGTH		16
+  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 */
+  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_GOT_FDE_LENGTH, 0, 0, 0,	/* FDE length */
+  PLT_CIE_LENGTH + 8, 0, 0, 0,	/* CIE pointer */
+  0, 0, 0, 0,			/* the start of .plt.got goes here */
+  0, 0, 0, 0,			/* .plt.got size goes here */
+  0,				/* Augmentation size */
+  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.  */
@@ -679,6 +705,10 @@ struct elf_i386_plt_layout
   /* .eh_frame covering the .plt section.  */
   const bfd_byte *eh_frame_plt;
   unsigned int eh_frame_plt_size;
+
+  /* .eh_frame covering the .plt.got section.  */
+  const bfd_byte *eh_frame_plt_got;
+  unsigned int eh_frame_plt_got_size;
 };
 
 #define GET_PLT_ENTRY_SIZE(abfd) \
@@ -701,6 +731,8 @@ static const struct elf_i386_plt_layout elf_i386_plt =
     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 */
+    elf_i386_eh_frame_plt_got,          /* eh_frame_plt_got */
+    sizeof (elf_i386_eh_frame_plt_got), /* eh_frame_plt_got_size */
   };
 
 
@@ -850,6 +882,7 @@ struct elf_i386_link_hash_table
   asection *interp;
   asection *plt_eh_frame;
   asection *plt_got;
+  asection *plt_got_eh_frame;
 
   union
   {
@@ -2347,6 +2380,24 @@ do_size:
 					     htab->plt_got,
 					     plt_got_align))
 	    goto error_return;
+
+	  if (!info->no_ld_generated_unwind_info
+	      && htab->plt_got_eh_frame == NULL
+	      && get_elf_i386_backend_data (abfd)->plt->eh_frame_plt_got != NULL)
+	    {
+	      flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+				| SEC_HAS_CONTENTS | SEC_IN_MEMORY
+				| SEC_LINKER_CREATED);
+	      htab->plt_got_eh_frame
+		= bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+						      ".eh_frame",
+						      flags);
+	      if (htab->plt_got_eh_frame == NULL
+		  || !bfd_set_section_alignment (htab->elf.dynobj,
+						 htab->plt_got_eh_frame,
+						 2))
+		goto error_return;
+	    }
 	}
 
       if (r_type == R_386_GOT32X
@@ -3379,14 +3430,22 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 	htab->elf.sgotplt->size = 0;
     }
 
-
-  if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && !bfd_is_abs_section (htab->elf.splt->output_section)
-      && _bfd_elf_eh_frame_present (info))
-    htab->plt_eh_frame->size
-      = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_size;
+  if (_bfd_elf_eh_frame_present (info))
+    {
+      if (htab->plt_eh_frame != NULL
+	  && htab->elf.splt != NULL
+	  && htab->elf.splt->size != 0
+	  && !bfd_is_abs_section (htab->elf.splt->output_section))
+	htab->plt_eh_frame->size
+	  = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_size;
+
+      if (htab->plt_got_eh_frame != NULL
+	  && htab->plt_got != NULL
+	  && htab->plt_got->size != 0
+	  && !bfd_is_abs_section (htab->plt_got->output_section))
+	htab->plt_got_eh_frame->size
+	  = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_got_size;
+    }
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
@@ -3415,6 +3474,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 	       || s == htab->elf.igotplt
 	       || s == htab->plt_got
 	       || s == htab->plt_eh_frame
+	       || s == htab->plt_got_eh_frame
 	       || s == htab->elf.sdynbss
 	       || s == htab->elf.sdynrelro)
 	{
@@ -3476,6 +3536,17 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 		  htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
     }
 
+  if (htab->plt_got_eh_frame != NULL
+      && htab->plt_got_eh_frame->contents != NULL)
+    {
+      memcpy (htab->plt_got_eh_frame->contents,
+	      get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_got,
+	      htab->plt_got_eh_frame->size);
+      bfd_put_32 (dynobj, htab->plt_got->size,
+		  (htab->plt_got_eh_frame->contents
+		   + PLT_FDE_LEN_OFFSET));
+    }
+
   if (htab->elf.dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -5885,6 +5956,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 	}
     }
 
+  /* Adjust .eh_frame for .plt.got section.  */
+  if (htab->plt_got_eh_frame != NULL
+      && htab->plt_got_eh_frame->contents != NULL)
+    {
+      if (htab->plt_got != NULL
+	  && htab->plt_got->size != 0
+	  && (htab->plt_got->flags & SEC_EXCLUDE) == 0
+	  && htab->plt_got->output_section != NULL
+	  && htab->plt_got_eh_frame->output_section != NULL)
+	{
+	  bfd_vma plt_start = htab->plt_got->output_section->vma;
+	  bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
+				   + htab->plt_got_eh_frame->output_offset
+				   + PLT_FDE_START_OFFSET;
+	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+			     htab->plt_got_eh_frame->contents
+			     + PLT_FDE_START_OFFSET);
+	}
+      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+	{
+	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+						 htab->plt_got_eh_frame,
+						 htab->plt_got_eh_frame->contents))
+	    return FALSE;
+	}
+    }
+
   if (htab->elf.sgot && htab->elf.sgot->size > 0)
     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
 
@@ -6428,6 +6526,8 @@ static const struct elf_i386_plt_layout elf_i386_nacl_plt =
     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 */
+    NULL,				/* eh_frame_plt_got */
+    0,					/* eh_frame_plt_got_size */
   };
 
 static const struct elf_i386_backend_data elf_i386_nacl_arch_bed =
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 36630f8..1edab04 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -659,6 +659,33 @@ static const bfd_byte elf_x86_64_eh_frame_plt[] =
   DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
 };
 
+/* .eh_frame covering the .plt.got section.  */
+
+static const bfd_byte elf_x86_64_eh_frame_plt_got[] =
+{
+#define PLT_GOT_FDE_LENGTH		20
+  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 */
+  0x78,				/* Data alignment factor */
+  16,				/* Return address column */
+  1,				/* Augmentation size */
+  DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
+  DW_CFA_def_cfa, 7, 8,		/* DW_CFA_def_cfa: r7 (rsp) ofs 8 */
+  DW_CFA_offset + 16, 1,	/* DW_CFA_offset: r16 (rip) at cfa-8 */
+  DW_CFA_nop, DW_CFA_nop,
+
+  PLT_GOT_FDE_LENGTH, 0, 0, 0,	/* FDE length */
+  PLT_CIE_LENGTH + 8, 0, 0, 0,	/* CIE pointer */
+  0, 0, 0, 0,			/* the start of .plt.got goes here */
+  0, 0, 0, 0,			/* .plt.got size goes here */
+  0,				/* Augmentation size */
+  DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop,
+  DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
+};
+
 /* Architecture-specific backend data for x86-64.  */
 
 struct elf_x86_64_backend_data
@@ -693,6 +720,10 @@ struct elf_x86_64_backend_data
   /* .eh_frame covering the .plt section.  */
   const bfd_byte *eh_frame_plt;
   unsigned int eh_frame_plt_size;
+
+  /* .eh_frame covering the .plt.got section.  */
+  const bfd_byte *eh_frame_plt_got;
+  unsigned int eh_frame_plt_got_size;
 };
 
 #define get_elf_x86_64_arch_data(bed) \
@@ -721,6 +752,8 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
     6,                                  /* plt_lazy_offset */
     elf_x86_64_eh_frame_plt,            /* eh_frame_plt */
     sizeof (elf_x86_64_eh_frame_plt),   /* eh_frame_plt_size */
+    elf_x86_64_eh_frame_plt_got,        /* eh_frame_plt_got */
+    sizeof (elf_x86_64_eh_frame_plt_got), /* eh_frame_plt_got_size */
   };
 
 static const struct elf_x86_64_backend_data elf_x86_64_bnd_arch_bed =
@@ -739,6 +772,9 @@ static const struct elf_x86_64_backend_data elf_x86_64_bnd_arch_bed =
     0,                                  /* plt_lazy_offset */
     elf_x86_64_eh_frame_plt,            /* eh_frame_plt */
     sizeof (elf_x86_64_eh_frame_plt),   /* eh_frame_plt_size */
+    /* FIXME: Needs .eh_frame coverage.  */
+    NULL,                               /* eh_frame_plt_got */
+    0,                                  /* eh_frame_plt_got_size */
   };
 
 #define	elf_backend_arch_data	&elf_x86_64_arch_bed
@@ -865,6 +901,7 @@ struct elf_x86_64_link_hash_table
   asection *plt_eh_frame;
   asection *plt_bnd;
   asection *plt_got;
+  asection *plt_got_eh_frame;
 
   union
   {
@@ -1135,7 +1172,8 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
       htab->plt_eh_frame
 	= bfd_make_section_anyway_with_flags (dynobj, ".eh_frame", flags);
       if (htab->plt_eh_frame == NULL
-	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
+	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame,
+					 ABI_64_P (dynobj) ? 3 : 2))
 	return FALSE;
     }
 
@@ -2744,6 +2782,24 @@ do_size:
 					     htab->plt_got,
 					     plt_got_align))
 	    goto error_return;
+
+	  if (!info->no_ld_generated_unwind_info
+	      && htab->plt_got_eh_frame == NULL
+	      && get_elf_x86_64_backend_data (abfd)->eh_frame_plt_got != NULL)
+	    {
+	      flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+				| SEC_HAS_CONTENTS | SEC_IN_MEMORY
+				| SEC_LINKER_CREATED);
+	      htab->plt_got_eh_frame
+		= bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+						      ".eh_frame",
+						      flags);
+	      if (htab->plt_got_eh_frame == NULL
+		  || !bfd_set_section_alignment (htab->elf.dynobj,
+						 htab->plt_got_eh_frame,
+						 ABI_64_P (htab->elf.dynobj) ? 3 : 2))
+		goto error_return;
+	    }
 	}
 
       if ((r_type == R_X86_64_GOTPCREL
@@ -3788,15 +3844,28 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
 	htab->elf.sgotplt->size = 0;
     }
 
-  if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && !bfd_is_abs_section (htab->elf.splt->output_section)
-      && _bfd_elf_eh_frame_present (info))
+  if (_bfd_elf_eh_frame_present (info))
     {
-      const struct elf_x86_64_backend_data *arch_data
-	= get_elf_x86_64_arch_data (bed);
-      htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+      if (htab->plt_eh_frame != NULL
+	  && htab->elf.splt != NULL
+	  && htab->elf.splt->size != 0
+	  && !bfd_is_abs_section (htab->elf.splt->output_section))
+	{
+	  const struct elf_x86_64_backend_data *arch_data
+	    = get_elf_x86_64_arch_data (bed);
+	  htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+	}
+
+      if (htab->plt_got_eh_frame != NULL
+	  && htab->plt_got != NULL
+	  && htab->plt_got->size != 0
+	  && !bfd_is_abs_section (htab->plt_got->output_section))
+	{
+	  const struct elf_x86_64_backend_data *arch_data
+	    = get_elf_x86_64_arch_data (bed);
+	  htab->plt_got_eh_frame->size
+	    = arch_data->eh_frame_plt_got_size;
+	}
     }
 
   /* We now have determined the sizes of the various dynamic sections.
@@ -3815,6 +3884,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
 	  || s == htab->plt_bnd
 	  || s == htab->plt_got
 	  || s == htab->plt_eh_frame
+	  || s == htab->plt_got_eh_frame
 	  || s == htab->elf.sdynbss
 	  || s == htab->elf.sdynrelro)
 	{
@@ -3878,6 +3948,20 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
 		  htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
     }
 
+  if (htab->plt_got_eh_frame != NULL
+      && htab->plt_got_eh_frame->contents != NULL)
+    {
+      const struct elf_x86_64_backend_data *arch_data
+	= get_elf_x86_64_arch_data (bed);
+
+      memcpy (htab->plt_got_eh_frame->contents,
+	      arch_data->eh_frame_plt_got,
+	      htab->plt_got_eh_frame->size);
+      bfd_put_32 (dynobj, htab->plt_got->size,
+		  (htab->plt_got_eh_frame->contents
+		   + PLT_FDE_LEN_OFFSET));
+    }
+
   if (htab->elf.dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -6343,6 +6427,33 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
 	}
     }
 
+  /* Adjust .eh_frame for .plt.got section.  */
+  if (htab->plt_got_eh_frame != NULL
+      && htab->plt_got_eh_frame->contents != NULL)
+    {
+      if (htab->plt_got != NULL
+	  && htab->plt_got->size != 0
+	  && (htab->plt_got->flags & SEC_EXCLUDE) == 0
+	  && htab->plt_got->output_section != NULL
+	  && htab->plt_got_eh_frame->output_section != NULL)
+	{
+	  bfd_vma plt_start = htab->plt_got->output_section->vma;
+	  bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
+				   + htab->plt_got_eh_frame->output_offset
+				   + PLT_FDE_START_OFFSET;
+	  bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+			     htab->plt_got_eh_frame->contents
+			     + PLT_FDE_START_OFFSET);
+	}
+      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+	{
+	  if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+						 htab->plt_got_eh_frame,
+						 htab->plt_got_eh_frame->contents))
+	    return FALSE;
+	}
+    }
+
   if (htab->elf.sgot && htab->elf.sgot->size > 0)
     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
       = GOT_ENTRY_SIZE;
@@ -7007,6 +7118,8 @@ static const struct elf_x86_64_backend_data elf_x86_64_nacl_arch_bed =
     32,                                      /* plt_lazy_offset */
     elf_x86_64_nacl_eh_frame_plt,            /* eh_frame_plt */
     sizeof (elf_x86_64_nacl_eh_frame_plt),   /* eh_frame_plt_size */
+    NULL,                                    /* eh_frame_plt_got */
+    0,                                       /* eh_frame_plt_got_size */
   };
 
 #undef	elf_backend_arch_data
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 6a61d61..03562de 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,29 @@
+2017-01-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+	Backport from master
+	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* testsuite/ld-x86-64/pr20830b.d: Updated.
+
+	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* emulparams/elf32_x86_64.sh (TINY_READONLY_SECTION): New.
+	* testsuite/ld-x86-64/pr20830.d: Renamed to ...
+	* testsuite/ld-x86-64/pr20830a.d: This.  Updated.
+	* testsuite/ld-x86-64/pr20830b.d: New file.
+	* testsuite/ld-x86-64/x86-64.exp: Rename pr20830 to pr20830a.
+	Run pr20830b.
+
+	2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR ld/20830
+	* testsuite/ld-i386/i386.exp: Run pr20830.
+	* testsuite/ld-x86-64/x86-64.exp: Likewise.
+	* testsuite/ld-i386/pr20830.d: New file.
+	* testsuite/ld-i386/pr20830.s: Likewise.
+	* testsuite/ld-x86-64/pr20830.d: Likewise.
+	* testsuite/ld-x86-64/pr20830.s: Likewise.
+
 2017-01-02  Alan Modra  <amodra@gmail.com>
 
 	Update year range in copyright notice of all files.
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 9050730..9b85239 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -21,6 +21,10 @@ LARGE_SECTIONS=yes
 LARGE_BSS_AFTER_BSS=
 SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0"
 IREL_IN_PLT=
+# Reuse TINY_READONLY_SECTION which is placed right after .plt section.
+TINY_READONLY_SECTION="
+.plt.got      ${RELOCATING-0} : { *(.plt.got) }
+"
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index e748e8b..f439411 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -864,3 +864,4 @@ if { !([istarget "i?86-*-linux*"]
 # Linux only tests
 run_dump_test "pltgot-1"
 run_dump_test "pltgot-2"
+run_dump_test "pr20830"
diff --git a/ld/testsuite/ld-i386/pr20830.d b/ld/testsuite/ld-i386/pr20830.d
new file mode 100644
index 0000000..caaadd7
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20830.d
@@ -0,0 +1,60 @@
+#name: PR ld/20830 (.plt.got)
+#as: --32
+#ld: -melf_i386 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 00000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 8
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r4 \(esp\) ofs 4
+  DW_CFA_offset: r8 \(eip\) at cfa-4
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+18 00000010 0000001c FDE cie=00000000 pc=00000188..00000193
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+2c 00000020 00000030 FDE cie=00000000 pc=00000170..00000180
+  DW_CFA_def_cfa_offset: 8
+  DW_CFA_advance_loc: 6 to 00000176
+  DW_CFA_def_cfa_offset: 12
+  DW_CFA_advance_loc: 10 to 00000180
+  DW_CFA_def_cfa_expression \(DW_OP_breg4 \(esp\): 4; DW_OP_breg8 \(eip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit2; DW_OP_shl; DW_OP_plus\)
+
+0+50 00000010 00000054 FDE cie=00000000 pc=00000180..00000188
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+170 <.plt>:
+ +[a-f0-9]+:	ff b3 04 00 00 00    	pushl  0x4\(%ebx\)
+ +[a-f0-9]+:	ff a3 08 00 00 00    	jmp    \*0x8\(%ebx\)
+ +[a-f0-9]+:	00 00                	add    %al,\(%eax\)
+	...
+
+Disassembly of section .plt.got:
+
+0+180 <.plt.got>:
+ +[a-f0-9]+:	ff a3 fc ff ff ff    	jmp    \*-0x4\(%ebx\)
+ +[a-f0-9]+:	66 90                	xchg   %ax,%ax
+
+Disassembly of section .text:
+
+0+188 <foo>:
+ +[a-f0-9]+:	e8 f3 ff ff ff       	call   180 <.plt.got>
+ +[a-f0-9]+:	8b 83 fc ff ff ff    	mov    -0x4\(%ebx\),%eax
+#pass
diff --git a/ld/testsuite/ld-i386/pr20830.s b/ld/testsuite/ld-i386/pr20830.s
new file mode 100644
index 0000000..344a137
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20830.s
@@ -0,0 +1,8 @@
+	.text
+	.globl foo
+	.type foo, @function
+foo:
+	.cfi_startproc
+	call	func@plt
+	movl	func@GOT(%ebx), %eax
+	.cfi_endproc
diff --git a/ld/testsuite/ld-x86-64/pr20830.s b/ld/testsuite/ld-x86-64/pr20830.s
new file mode 100644
index 0000000..d9a1b4c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830.s
@@ -0,0 +1,8 @@
+	.text
+	.globl foo
+	.type foo, @function
+foo:
+	.cfi_startproc
+	call	func@plt
+	movq	func@GOTPCREL(%rip), %rax
+	.cfi_endproc
diff --git a/ld/testsuite/ld-x86-64/pr20830a.d b/ld/testsuite/ld-x86-64/pr20830a.d
new file mode 100644
index 0000000..87ea25d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830a.d
@@ -0,0 +1,72 @@
+#name: PR ld/20830 (.plt.got)
+#source: pr20830.s
+#as: --64
+#ld: -melf_x86_64 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 0000000000000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: -8
+  Return address column: 16
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+  DW_CFA_offset: r16 \(rip\) at cfa-8
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+18 0000000000000014 0000001c FDE cie=00000000 pc=0000000000000238..0000000000000244
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+30 0000000000000024 00000034 FDE cie=00000000 pc=0000000000000220..0000000000000230
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_advance_loc: 6 to 0000000000000226
+  DW_CFA_def_cfa_offset: 24
+  DW_CFA_advance_loc: 10 to 0000000000000230
+  DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus\)
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+58 0000000000000014 0000005c FDE cie=00000000 pc=0000000000000230..0000000000000238
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+220 <.plt>:
+ +[a-f0-9]+:	ff 35 e2 0d 20 00    	pushq  0x200de2\(%rip\)        # 201008 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 e4 0d 20 00    	jmpq   \*0x200de4\(%rip\)        # 201010 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
+
+Disassembly of section .plt.got:
+
+0+230 <.plt.got>:
+ +[a-f0-9]+:	ff 25 c2 0d 20 00    	jmpq   \*0x200dc2\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	66 90                	xchg   %ax,%ax
+
+Disassembly of section .text:
+
+0+238 <foo>:
+ +[a-f0-9]+:	e8 f3 ff ff ff       	callq  230 <.plt.got>
+ +[a-f0-9]+:	48 8b 05 b4 0d 20 00 	mov    0x200db4\(%rip\),%rax        # 200ff8 <func>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20830b.d b/ld/testsuite/ld-x86-64/pr20830b.d
new file mode 100644
index 0000000..218a56e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830b.d
@@ -0,0 +1,60 @@
+#name: PR ld/20830 (.plt.got)
+#source: pr20830.s
+#as: --x32
+#ld: -melf32_x86_64 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 0000000000000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: -8
+  Return address column: 16
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+  DW_CFA_offset: r16 \(rip\) at cfa-8
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+18 0000000000000010 0000001c FDE cie=00000000 pc=0000000000000188..0000000000000194
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+2c 0000000000000020 00000030 FDE cie=00000000 pc=0000000000000170..0000000000000180
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_advance_loc: 6 to 0000000000000176
+  DW_CFA_def_cfa_offset: 24
+  DW_CFA_advance_loc: 10 to 0000000000000180
+  DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus\)
+
+0+50 0000000000000010 00000054 FDE cie=00000000 pc=0000000000000180..0000000000000188
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+170 <.plt>:
+ +[a-f0-9]+:	ff 35 92 0e 20 00    	pushq  0x200e92\(%rip\)        # 201008 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 94 0e 20 00    	jmpq   \*0x200e94\(%rip\)        # 201010 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
+
+Disassembly of section .plt.got:
+
+0+180 <.plt.got>:
+ +[a-f0-9]+:	ff 25 72 0e 20 00    	jmpq   \*0x200e72\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	66 90                	xchg   %ax,%ax
+
+Disassembly of section .text:
+
+0+188 <foo>:
+ +[a-f0-9]+:	e8 f3 ff ff ff       	callq  180 <.plt.got>
+ +[a-f0-9]+:	48 8b 05 64 0e 20 00 	mov    0x200e64\(%rip\),%rax        # 200ff8 <func>
+#pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index ac63a1d..3a7ba38 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1017,3 +1017,5 @@ if { ![istarget "x86_64-*-linux*"]} {
 run_dump_test "pr17618"
 run_dump_test "pltgot-1"
 run_dump_test "pltgot-2"
+run_dump_test "pr20830a"
+run_dump_test "pr20830b"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]