This is the mail archive of the binutils@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]

pr14158, hole in powerpc64 .eh_frame


PowerPC64 linker generated .eh_frame for PLT call stubs uses
DW_EH_PE_pcrel | DW_EH_PE_sdata4 encoding for addresses, and thus
aligns .eh_frame to 4 bytes.  Current gcc uses the same encoding, but
probably because gcc hasn't changed its .eh_frame alignment from the
days it generated 8-byte addresses, aligns to 8 bytes.  This means ld
will insert padding between the linker generated .eh_frame and user
.eh_frame sections.  The padding is seen as a terminator, which breaks
exception handling for anyone not reading the FDEs via .eh_frame_hdr.
The common case of course is to call ld with --eh-frame-hdr, which is
why I hadn't seen this problem until now.

	PR ld/14158
	* elf64-ppc.c (ppc64_elf_size_stubs): Round up glink_eh_frame
	size to output section alignment.
	(ppc64_elf_build_stubs): Likewise, and extend last FDE to cover.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.383
diff -u -p -r1.383 elf64-ppc.c
--- bfd/elf64-ppc.c	17 May 2012 02:43:34 -0000	1.383
+++ bfd/elf64-ppc.c	24 May 2012 04:49:55 -0000
@@ -11664,7 +11664,7 @@ ppc64_elf_size_stubs (struct bfd_link_in
 	  && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
 	  && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0)
 	{
-	  bfd_size_type size = 0;
+	  size_t size = 0, align;
 
 	  for (stub_sec = htab->stub_bfd->sections;
 	       stub_sec != NULL;
@@ -11675,6 +11675,10 @@ ppc64_elf_size_stubs (struct bfd_link_in
 	    size += 24;
 	  if (size != 0)
 	    size += sizeof (glink_eh_frame_cie);
+	  align = 1;
+	  align <<= htab->glink_eh_frame->output_section->alignment_power;
+	  align -= 1;
+	  size = (size + align) & ~align;
 	  htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
 	  htab->glink_eh_frame->size = size;
 	}
@@ -11916,17 +11920,21 @@ ppc64_elf_build_stubs (bfd_boolean emit_
       && htab->glink_eh_frame->size != 0)
     {
       bfd_vma val;
+      bfd_byte *last_fde;
+      size_t last_fde_len, size, align, pad;
 
       p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
       if (p == NULL)
 	return FALSE;
       htab->glink_eh_frame->contents = p;
+      last_fde = p;
 
       htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
 
       memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
       /* CIE length (rewrite in case little-endian).  */
-      bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
+      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
       p += sizeof (glink_eh_frame_cie);
 
       for (stub_sec = htab->stub_bfd->sections;
@@ -11934,6 +11942,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_
 	   stub_sec = stub_sec->next)
 	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
 	  {
+	    last_fde = p;
+	    last_fde_len = 16;
 	    /* FDE length.  */
 	    bfd_put_32 (htab->elf.dynobj, 16, p);
 	    p += 4;
@@ -11966,6 +11976,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_
 	  }
       if (htab->glink != NULL && htab->glink->size != 0)
 	{
+	  last_fde = p;
+	  last_fde_len = 20;
 	  /* FDE length.  */
 	  bfd_put_32 (htab->elf.dynobj, 20, p);
 	  p += 4;
@@ -12003,7 +12015,16 @@ ppc64_elf_build_stubs (bfd_boolean emit_
 	  *p++ = DW_CFA_restore_extended;
 	  *p++ = 65;
 	}
-      htab->glink_eh_frame->size = p - htab->glink_eh_frame->contents;
+      /* Subsume any padding into the last FDE if user .eh_frame
+	 sections are aligned more than glink_eh_frame.  Otherwise any
+	 zero padding will be seen as a terminator.  */
+      size = p - htab->glink_eh_frame->contents;
+      align = 1;
+      align <<= htab->glink_eh_frame->output_section->alignment_power;
+      align -= 1;
+      pad = ((size + align) & ~align) - size;
+      htab->glink_eh_frame->size = size + pad;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
     }
 
   /* Build the stubs as directed by the stub hash table.  */

-- 
Alan Modra
Australia Development Lab, IBM


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