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]

PowerPC64 EH info for _notoc linkage stubs


This patch generates EH info for the new _notoc linkage stubs, to
support unwinding from asynchronous signal handlers.  Unwinding
through the __tls_get_addr_opt stub was already supported, but that
was just a single stub.  With multiple stubs the EH opcodes need to be
emitted and sized when iterating over stubs, so this is done when
emitting and sizing the stub code.  Emitting the CIEs and FDEs is done
when sizing the stubs, as we did before in order to have the linker
generated FDEs indexed in .eh_frame_hdr.  I moved the final tweaks to
FDEs from ppc64_elf_finish_dynamic_sections to ppc64_elf_build_stubs
simply because it's tidier to be done with them at that point.

bfd/
	* elf64-ppc.c (struct map_stub): Delete tls_get_addr_opt_bctrl.
	Add lr_restore, eh_size and eh_base.
	(eh_advance, eh_advance_size): New functions.
	(build_tls_get_addr_stub): Emit EH info for stub.
	(ppc_build_one_stub): Likewise for _notoc stubs.
	(ppc_size_one_stub): Size EH info for stub.
	(group_sections): Init new map_stub fields.
	(stub_eh_frame_size): Delete.
	(ppc64_elf_size_stubs): Size EH info for stubs.  Set up dummy EH
	program for stubs.
	(ppc64_elf_build_stubs): Reinit new map_stub fields.  Set FDE
	offset to stub section here..
	(ppc64_elf_finish_dynamic_sections): ..rather than here.
ld/
	* testsuite/ld-powerpc/notoc.s: Generate some cfi.
	* testsuite/ld-powerpc/notoc.d: Adjust.
	* testsuite/ld-powerpc/notoc.wf: New file.
	* testsuite/ld-powerpc/powerpc.exp: Run "ext" and "notoc" tests
	as run_ld_link_tests rather than run_dump_test.

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 5e20bbd971..c9ac8e9aac 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -4113,9 +4113,15 @@ struct map_stub
   /* Whether to emit a copy of register save/restore functions in this
      group.  */
   int needs_save_res;
-  /* The offset of the __tls_get_addr_opt plt stub bctrl in this group,
-     or -1u if no such stub with bctrl exists.  */
-  unsigned int tls_get_addr_opt_bctrl;
+  /* Current offset within stubs after the insn restoring lr in a
+     _notoc or _both stub using bcl for pc-relative addressing, or
+     after the insn restoring lr in a __tls_get_addr_opt plt stub.  */
+  unsigned int lr_restore;
+  /* Accumulated size of EH info emitted to describe return address
+     if stubs modify lr.  Does not include 17 byte FDE header.  */
+  unsigned int eh_size;
+  /* Offset in glink_eh_frame to the start of EH info for this group.  */
+  unsigned int eh_base;
 };
 
 struct ppc_stub_hash_entry {
@@ -10965,6 +10971,52 @@ size_offset (bfd_vma off)
   return size;
 }
 
+/* Emit .eh_frame opcode to advance pc by DELTA.  */
+
+static bfd_byte *
+eh_advance (bfd *abfd, bfd_byte *eh, unsigned int delta)
+{
+  delta /= 4;
+  if (delta < 64)
+    *eh++ = DW_CFA_advance_loc + delta;
+  else if (delta < 256)
+    {
+      *eh++ = DW_CFA_advance_loc1;
+      *eh++ = delta;
+    }
+  else if (delta < 65536)
+    {
+      *eh++ = DW_CFA_advance_loc2;
+      bfd_put_16 (abfd, delta, eh);
+      eh += 2;
+    }
+  else
+    {
+      *eh++ = DW_CFA_advance_loc4;
+      bfd_put_32 (abfd, delta, eh);
+      eh += 4;
+    }
+  return eh;
+}
+
+/* Size of required .eh_frame opcode to advance pc by DELTA.  */
+
+static unsigned int
+eh_advance_size (unsigned int delta)
+{
+  if (delta < 64 * 4)
+    /* DW_CFA_advance_loc+[1..63].  */
+    return 1;
+  if (delta < 256 * 4)
+    /* DW_CFA_advance_loc1, byte.  */
+    return 2;
+  if (delta < 65536 * 4)
+    /* DW_CFA_advance_loc2, 2 bytes.  */
+    return 3;
+  /* DW_CFA_advance_loc4, 4 bytes.  */
+  return 5;
+}
+
 /* With power7 weakly ordered memory model, it is possible for ld.so
    to update a plt entry in one thread and have another thread see a
    stale zero toc entry.  To avoid this we need some sort of acquire
@@ -11262,6 +11314,7 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
 			 bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
 {
   bfd *obfd = htab->params->stub_bfd;
+  bfd_byte *loc = p;
 
   bfd_put_32 (obfd, LD_R11_0R3 + 0, p),		p += 4;
   bfd_put_32 (obfd, LD_R12_0R3 + 8, p),		p += 4;
@@ -11288,6 +11341,26 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
   bfd_put_32 (obfd, MTLR_R11, p),		p += 4;
   bfd_put_32 (obfd, BLR, p),			p += 4;
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_byte *base, *eh;
+      unsigned int lr_used, delta;
+
+      base = htab->glink_eh_frame->contents + stub_entry->group->eh_base + 17;
+      eh = base + stub_entry->group->eh_size;
+      lr_used = stub_entry->stub_offset + (p - 20 - loc);
+      delta = lr_used - stub_entry->group->lr_restore;
+      stub_entry->group->lr_restore = lr_used + 16;
+      eh = eh_advance (htab->elf.dynobj, eh, delta);
+      *eh++ = DW_CFA_offset_extended_sf;
+      *eh++ = 65;
+      *eh++ = -(STK_LINKER (htab) / 8) & 0x7f;
+      *eh++ = DW_CFA_advance_loc + 4;
+      *eh++ = DW_CFA_restore_extended;
+      *eh++ = 65;
+      stub_entry->group->eh_size = eh - base;
+    }
   return p;
 }
 
@@ -11707,6 +11780,32 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  bfd_put_32 (htab->params->stub_bfd, BCTR, p);
 	}
       p += 4;
+
+      if (htab->glink_eh_frame != NULL
+	&& htab->glink_eh_frame->size != 0)
+	{
+	  bfd_byte *base, *eh;
+	  unsigned int lr_used, delta;
+
+	  base = (htab->glink_eh_frame->contents
+		  + stub_entry->group->eh_base + 17);
+	  eh = base + stub_entry->group->eh_size;
+	  lr_used = stub_entry->stub_offset + 8;
+	  if (stub_entry->stub_type == ppc_stub_long_branch_both
+	      || stub_entry->stub_type == ppc_stub_plt_branch_both
+	      || stub_entry->stub_type == ppc_stub_plt_call_both)
+	    lr_used += 4;
+	  delta = lr_used - stub_entry->group->lr_restore;
+	  stub_entry->group->lr_restore = lr_used + 8;
+	  eh = eh_advance (htab->elf.dynobj, eh, delta);
+	  *eh++ = DW_CFA_register;
+	  *eh++ = 65;
+	  *eh++ = 12;
+	  *eh++ = DW_CFA_advance_loc + 2;
+	  *eh++ = DW_CFA_restore_extended;
+	  *eh++ = 65;
+	  stub_entry->group->eh_size = eh - base;
+	}
       break;
 
     case ppc_stub_plt_call:
@@ -11920,15 +12019,45 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       off = targ - off;
       size = plt_stub_size (htab, stub_entry, off);
 
-      if (stub_entry->stub_type < ppc_stub_plt_call_notoc)
+      if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
+	{
+	  /* After the bcl, lr has been modified so we need to emit
+	     .eh_frame info saying the return address is in r12.  */
+	  unsigned int lr_used = stub_entry->stub_offset + 8;
+	  unsigned int delta;
+	  if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
+	    lr_used += 4;
+	  /* The eh_frame info will consist of a DW_CFA_advance_loc or
+	     variant, DW_CFA_register, 65, 12, DW_CFA_advance_loc+2,
+	     DW_CFA_restore_extended 65.  */
+	  delta = lr_used - stub_entry->group->lr_restore;
+	  stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+	  stub_entry->group->lr_restore = lr_used + 8;
+	}
+      else
 	{
 	  if (stub_entry->h != NULL
 	      && (stub_entry->h == htab->tls_get_addr_fd
 		  || stub_entry->h == htab->tls_get_addr)
 	      && htab->params->tls_get_addr_opt
 	      && stub_entry->stub_type == ppc_stub_plt_call_r2save)
-	    stub_entry->group->tls_get_addr_opt_bctrl
-	      = stub_entry->stub_offset + size - 5 * 4;
+	    {
+	      /* After the bctrl, lr has been modified so we need to
+		 emit .eh_frame info saying the return address is
+		 on the stack.  In fact we put the EH info specifying
+		 that the return address is on the stack *at* the
+		 call rather than after it, because the EH info for a
+		 call needs to be specified by that point.
+		 See libgcc/unwind-dw2.c execute_cfa_program.  */
+	      unsigned int lr_used = stub_entry->stub_offset + size - 20;
+	      unsigned int delta;
+	      /* The eh_frame info will consist of a DW_CFA_advance_loc
+		 or variant, DW_CFA_offset_externed_sf, 65, -stackoff,
+		 DW_CFA_advance_loc+4, DW_CFA_restore_extended, 65.  */
+	      delta = lr_used - stub_entry->group->lr_restore;
+	      stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+	      stub_entry->group->lr_restore = size - 4;
+	    }
 
 	  if (info->emitrelocations)
 	    {
@@ -11988,6 +12117,19 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (stub_entry->stub_type >= ppc_stub_long_branch_notoc)
 	{
+	  /* After the bcl, lr has been modified so we need to emit
+	     .eh_frame info saying the return address is in r12.  */
+	  unsigned int lr_used = stub_entry->stub_offset + 8;
+	  unsigned int delta;
+	  if (stub_entry->stub_type > ppc_stub_long_branch_notoc)
+	    lr_used += 4;
+	  /* The eh_frame info will consist of a DW_CFA_advance_loc or
+	     variant, DW_CFA_register, 65, 12, DW_CFA_advance_loc+2,
+	     DW_CFA_restore_extended 65.  */
+	  delta = lr_used - stub_entry->group->lr_restore;
+	  stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+	  stub_entry->group->lr_restore = lr_used + 8;
+
 	  if (off + (1 << 25) >= (bfd_vma) (1 << 26))
 	    {
 	      stub_entry->stub_type += (ppc_stub_plt_branch_notoc
@@ -12821,7 +12963,9 @@ group_sections (struct bfd_link_info *info,
 	  group->link_sec = curr;
 	  group->stub_sec = NULL;
 	  group->needs_save_res = 0;
-	  group->tls_get_addr_opt_bctrl = -1u;
+	  group->lr_restore = 0;
+	  group->eh_size = 0;
+	  group->eh_base = 0;
 	  group->next = htab->group;
 	  htab->group = group;
 	  do
@@ -12872,27 +13016,6 @@ static const unsigned char glink_eh_frame_cie[] =
   DW_CFA_def_cfa, 1, 0			/* def_cfa: r1 offset 0.  */
 };
 
-static size_t
-stub_eh_frame_size (struct map_stub *group, size_t align)
-{
-  size_t this_size = 17;
-  if (group->tls_get_addr_opt_bctrl != -1u)
-    {
-      unsigned int to_bctrl = group->tls_get_addr_opt_bctrl / 4;
-      if (to_bctrl < 64)
-	this_size += 1;
-      else if (to_bctrl < 256)
-	this_size += 2;
-      else if (to_bctrl < 65536)
-	this_size += 3;
-      else
-	this_size += 5;
-      this_size += 6;
-    }
-  this_size = (this_size + align - 1) & -align;
-  return this_size;
-}
-
 /* Stripping output sections is normally done before dynamic section
    symbols have been allocated.  This function is called later, and
    handles cases like htab->brlt which is mapped to its own output
@@ -13394,18 +13517,22 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       /* We may have added some stubs.  Find out the new size of the
 	 stub sections.  */
       for (group = htab->group; group != NULL; group = group->next)
-	if (group->stub_sec != NULL)
-	  {
-	    asection *stub_sec = group->stub_sec;
-
-	    if (htab->stub_iteration <= STUB_SHRINK_ITER
-		|| stub_sec->rawsize < stub_sec->size)
-	      /* Past STUB_SHRINK_ITER, rawsize is the max size seen.  */
-	      stub_sec->rawsize = stub_sec->size;
-	    stub_sec->size = 0;
-	    stub_sec->reloc_count = 0;
-	    stub_sec->flags &= ~SEC_RELOC;
-	  }
+	{
+	  group->lr_restore = 0;
+	  group->eh_size = 0;
+	  if (group->stub_sec != NULL)
+	    {
+	      asection *stub_sec = group->stub_sec;
+
+	      if (htab->stub_iteration <= STUB_SHRINK_ITER
+		  || stub_sec->rawsize < stub_sec->size)
+		/* Past STUB_SHRINK_ITER, rawsize is the max size seen.  */
+		stub_sec->rawsize = stub_sec->size;
+	      stub_sec->size = 0;
+	      stub_sec->reloc_count = 0;
+	      stub_sec->flags &= ~SEC_RELOC;
+	    }
+	}
 
       if (htab->stub_iteration <= STUB_SHRINK_ITER
 	  || htab->brlt->rawsize < htab->brlt->size)
@@ -13436,8 +13563,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 	  size_t size = 0, align = 4;
 
 	  for (group = htab->group; group != NULL; group = group->next)
-	    if (group->stub_sec != NULL)
-	      size += stub_eh_frame_size (group, align);
+	    if (group->eh_size != 0)
+	      size += (group->eh_size + 17 + align - 1) & -align;
 	  if (htab->glink != NULL && htab->glink->size != 0)
 	    size += (24 + align - 1) & -align;
 	  if (size != 0)
@@ -13484,6 +13611,10 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       size_t last_fde_len, size, align, pad;
       struct map_stub *group;
 
+      /* It is necessary to at least have a rough outline of the
+	 linker generated CIEs and FDEs written before
+	 bfd_elf_discard_info is run, in order for these FDEs to be
+	 indexed in .eh_frame_hdr.  */
       p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
       if (p == NULL)
 	return FALSE;
@@ -13498,10 +13629,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       p += last_fde_len + 4;
 
       for (group = htab->group; group != NULL; group = group->next)
-	if (group->stub_sec != NULL)
+	if (group->eh_size != 0)
 	  {
+	    group->eh_base = p - htab->glink_eh_frame->contents;
 	    last_fde = p;
-	    last_fde_len = stub_eh_frame_size (group, align) - 4;
+	    last_fde_len = ((group->eh_size + 17 + align - 1) & -align) - 4;
 	    /* FDE length.  */
 	    bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
 	    p += 4;
@@ -13516,39 +13648,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 	    p += 4;
 	    /* Augmentation.  */
 	    p += 1;
-	    if (group->tls_get_addr_opt_bctrl != -1u)
-	      {
-		unsigned int to_bctrl = group->tls_get_addr_opt_bctrl / 4;
-
-		/* This FDE needs more than just the default.
-		   Describe __tls_get_addr_opt stub LR.  */
-		if (to_bctrl < 64)
-		  *p++ = DW_CFA_advance_loc + to_bctrl;
-		else if (to_bctrl < 256)
-		  {
-		    *p++ = DW_CFA_advance_loc1;
-		    *p++ = to_bctrl;
-		  }
-		else if (to_bctrl < 65536)
-		  {
-		    *p++ = DW_CFA_advance_loc2;
-		    bfd_put_16 (htab->elf.dynobj, to_bctrl, p);
-		    p += 2;
-		  }
-		else
-		  {
-		    *p++ = DW_CFA_advance_loc4;
-		    bfd_put_32 (htab->elf.dynobj, to_bctrl, p);
-		    p += 4;
-		  }
-		*p++ = DW_CFA_offset_extended_sf;
-		*p++ = 65;
-		*p++ = -(STK_LINKER (htab) / 8) & 0x7f;
-		*p++ = DW_CFA_advance_loc + 4;
-		*p++ = DW_CFA_restore_extended;
-		*p++ = 65;
-	      }
-	    /* Pad.  */
+	    /* Make sure we don't have all nops.  This is enough for
+	       elf-eh-frame.c to detect the last non-nop opcode.  */
+	    p[group->eh_size - 1] = DW_CFA_advance_loc + 1;
 	    p = last_fde + last_fde_len + 4;
 	  }
       if (htab->glink != NULL && htab->glink->size != 0)
@@ -14023,14 +14125,19 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
 
   /* Allocate memory to hold the linker stubs.  */
   for (group = htab->group; group != NULL; group = group->next)
-    if ((stub_sec = group->stub_sec) != NULL
-	&& stub_sec->size != 0)
-      {
-	stub_sec->contents = bfd_zalloc (htab->params->stub_bfd, stub_sec->size);
-	if (stub_sec->contents == NULL)
-	  return FALSE;
-	stub_sec->size = 0;
-      }
+    {
+      group->eh_size = 0;
+      group->lr_restore = 0;
+      if ((stub_sec = group->stub_sec) != NULL
+	  && stub_sec->size != 0)
+	{
+	  stub_sec->contents = bfd_zalloc (htab->params->stub_bfd,
+					   stub_sec->size);
+	  if (stub_sec->contents == NULL)
+	    return FALSE;
+	  stub_sec->size = 0;
+	}
+    }
 
   if (htab->glink != NULL && htab->glink->size != 0)
     {
@@ -14213,6 +14320,55 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
 	  }
       }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      size_t align = 4;
+
+      p = htab->glink_eh_frame->contents;
+      p += (sizeof (glink_eh_frame_cie) + align - 1) & -align;
+
+      for (group = htab->group; group != NULL; group = group->next)
+	if (group->eh_size != 0)
+	  {
+	    /* Offset to stub section.  */
+	    val = (group->stub_sec->output_section->vma
+		   + group->stub_sec->output_offset);
+	    val -= (htab->glink_eh_frame->output_section->vma
+		    + htab->glink_eh_frame->output_offset
+		    + (p + 8 - htab->glink_eh_frame->contents));
+	    if (val + 0x80000000 > 0xffffffff)
+	      {
+		_bfd_error_handler
+		  (_("%s offset too large for .eh_frame sdata4 encoding"),
+		   group->stub_sec->name);
+		return FALSE;
+	      }
+	    bfd_put_32 (htab->elf.dynobj, val, p + 8);
+	    p += (group->eh_size + 17 + 3) & -4;
+	  }
+      if (htab->glink != NULL && htab->glink->size != 0)
+	{
+	  /* Offset to .glink.  */
+	  val = (htab->glink->output_section->vma
+		 + htab->glink->output_offset
+		 + 8);
+	  val -= (htab->glink_eh_frame->output_section->vma
+		  + htab->glink_eh_frame->output_offset
+		  + (p + 8 - htab->glink_eh_frame->contents));
+	  if (val + 0x80000000 > 0xffffffff)
+	    {
+	      _bfd_error_handler
+		(_("%s offset too large for .eh_frame sdata4 encoding"),
+		 htab->glink->name);
+	      return FALSE;
+	    }
+	  bfd_put_32 (htab->elf.dynobj, val, p + 8);
+	  p += (24 + align - 1) & -align;
+	}
+    }
+
   for (group = htab->group; group != NULL; group = group->next)
     if ((stub_sec = group->stub_sec) != NULL)
       {
@@ -16745,62 +16901,14 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
 				       NULL))
     return FALSE;
 
-  if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->size != 0)
-    {
-      bfd_vma val;
-      bfd_byte *p;
-      struct map_stub *group;
-      size_t align = 4;
-
-      p = htab->glink_eh_frame->contents;
-      p += (sizeof (glink_eh_frame_cie) + align - 1) & -align;
-
-      for (group = htab->group; group != NULL; group = group->next)
-	if (group->stub_sec != NULL)
-	  {
-	    /* Offset to stub section.  */
-	    val = (group->stub_sec->output_section->vma
-		   + group->stub_sec->output_offset);
-	    val -= (htab->glink_eh_frame->output_section->vma
-		    + htab->glink_eh_frame->output_offset
-		    + (p + 8 - htab->glink_eh_frame->contents));
-	    if (val + 0x80000000 > 0xffffffff)
-	      {
-		_bfd_error_handler
-		  (_("%s offset too large for .eh_frame sdata4 encoding"),
-		   group->stub_sec->name);
-		return FALSE;
-	      }
-	    bfd_put_32 (dynobj, val, p + 8);
-	    p += stub_eh_frame_size (group, align);
-	  }
-      if (htab->glink != NULL && htab->glink->size != 0)
-	{
-	  /* Offset to .glink.  */
-	  val = (htab->glink->output_section->vma
-		 + htab->glink->output_offset
-		 + 8);
-	  val -= (htab->glink_eh_frame->output_section->vma
-		  + htab->glink_eh_frame->output_offset
-		  + (p + 8 - htab->glink_eh_frame->contents));
-	  if (val + 0x80000000 > 0xffffffff)
-	    {
-	      _bfd_error_handler
-		(_("%s offset too large for .eh_frame sdata4 encoding"),
-		 htab->glink->name);
-	      return FALSE;
-	    }
-	  bfd_put_32 (dynobj, val, p + 8);
-	  p += (24 + align - 1) & -align;
-	}
 
-      if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-	  && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-					       htab->glink_eh_frame,
-					       htab->glink_eh_frame->contents))
-	return FALSE;
-    }
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0
+      && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+					   htab->glink_eh_frame,
+					   htab->glink_eh_frame->contents))
+    return FALSE;
 
   /* We need to handle writing out multiple GOT sections ourselves,
      since we didn't add them to DYNOBJ.  We know dynobj is the first
diff --git a/ld/testsuite/ld-powerpc/notoc.d b/ld/testsuite/ld-powerpc/notoc.d
index 97e7274bee..eaafd01390 100644
--- a/ld/testsuite/ld-powerpc/notoc.d
+++ b/ld/testsuite/ld-powerpc/notoc.d
@@ -1,7 +1,7 @@
 #source: notoc.s
 #as: -a64
 #ld: --no-plt-localentry -T ext.lnk
-#objdump: -dr
+#objdump: -d
 #target: powerpc64*-*-*
 
 .*
@@ -63,8 +63,8 @@ Disassembly of section \.text:
 .*:	(20 00 80 4e|4e 80 00 20) 	blr
 
 .* <f2>:
-.*:	(02 10 40 3c|3c 40 10 02) 	lis     r2,4098
-.*:	(00 90 42 38|38 42 90 00) 	addi    r2,r2,-28672
+.*:	(01 10 40 3c|3c 40 10 01) 	lis     r2,4097
+.*:	(00 80 42 38|38 42 80 00) 	addi    r2,r2,-32768
 .*:	(4d ff ff 4b|4b ff ff 4d) 	bl      .* <.*\.long_branch\.f1>
 .*:	(18 00 41 e8|e8 41 00 18) 	ld      r2,24\(r1\)
 .*:	(f9 ff ff 4b|4b ff ff f9) 	bl      .* <f2\+0x8>
@@ -78,8 +78,8 @@ Disassembly of section \.text:
 .*:	(20 00 80 4e|4e 80 00 20) 	blr
 
 .* <g2>:
-.*:	(02 10 40 3c|3c 40 10 02) 	lis     r2,4098
-.*:	(00 90 42 38|38 42 90 00) 	addi    r2,r2,-28672
+.*:	(01 10 40 3c|3c 40 10 01) 	lis     r2,4097
+.*:	(00 80 42 38|38 42 80 00) 	addi    r2,r2,-32768
 .*:	(cd ff ff 4b|4b ff ff cd) 	bl      .* <f2\+0x8>
 .*:	(00 00 00 60|60 00 00 00) 	nop
 .*:	(11 ff ff 4b|4b ff ff 11) 	bl      .* <.*\.long_branch\.f1>
@@ -96,7 +96,7 @@ Disassembly of section \.text:
 Disassembly of section \.text\.ext:
 
 8000000000000000 <ext>:
-8000000000000000:	(02 10 40 3c|3c 40 10 02) 	lis     r2,4098
-8000000000000004:	(00 90 42 38|38 42 90 00) 	addi    r2,r2,-28672
+8000000000000000:	(01 10 40 3c|3c 40 10 01) 	lis     r2,4097
+8000000000000004:	(00 80 42 38|38 42 80 00) 	addi    r2,r2,-32768
 8000000000000008:	(00 00 00 60|60 00 00 00) 	nop
 800000000000000c:	(20 00 80 4e|4e 80 00 20) 	blr
diff --git a/ld/testsuite/ld-powerpc/notoc.s b/ld/testsuite/ld-powerpc/notoc.s
index 8c620df3b4..eb881c865e 100644
--- a/ld/testsuite/ld-powerpc/notoc.s
+++ b/ld/testsuite/ld-powerpc/notoc.s
@@ -53,4 +53,6 @@ g2:
  blr
 
 _start:
+ .cfi_startproc
  b _start
+ .cfi_endproc
diff --git a/ld/testsuite/ld-powerpc/notoc.wf b/ld/testsuite/ld-powerpc/notoc.wf
new file mode 100644
index 0000000000..208d676f44
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/notoc.wf
@@ -0,0 +1,33 @@
+Contents of the \.eh_frame section:
+
+
+00000000 0000000000000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 65
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r1 ofs 0
+
+00000014 0000000000000024 00000018 FDE cie=00000000 pc=00000000100000c0\.\.0000000010000140
+  DW_CFA_advance_loc: 24 to 00000000100000d8
+  DW_CFA_register: r65 in r12
+  DW_CFA_advance_loc: 8 to 00000000100000e0
+  DW_CFA_restore_extended: r65
+  DW_CFA_advance_loc: 40 to 0000000010000108
+  DW_CFA_register: r65 in r12
+  DW_CFA_advance_loc: 8 to 0000000010000110
+  DW_CFA_restore_extended: r65
+  DW_CFA_advance_loc: 16 to 0000000010000120
+  DW_CFA_register: r65 in r12
+  DW_CFA_advance_loc: 8 to 0000000010000128
+  DW_CFA_restore_extended: r65
+  DW_CFA_nop
+  DW_CFA_nop
+
+0000003c 0000000000000010 00000040 FDE cie=00000000 pc=00000000100001cc\.\.00000000100001d0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index c4ab3decb8..12590f1817 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -257,6 +257,9 @@ set ppc64elftests {
 	{{objdump -dr tocsave2a.d}} "tocsave2a"}
     {"ambig shared v1" "-shared -melf64ppc" "" "-a64" {funv1.s} {} "funv1.so"}
     {"ambig shared v2" "-shared -melf64ppc" "" "-a64" {funv2.s} {} "funv2.so"}
+    {"notoc ext" "" "" "-a64" {ext.s} {} ""}
+    {"notoc" "-melf64ppc --no-plt-localentry -T ext.lnk" "" "-a64" {notoc.s}
+	{{objdump -d notoc.d} {readelf {-wf -W} notoc.wf}} "notoc"}
 }
 
 set ppceabitests {
@@ -331,8 +334,6 @@ if [ supports_ppc64 ] then {
     run_dump_test "dotsym2"
     run_dump_test "dotsym3"
     run_dump_test "dotsym4"
-    run_dump_test "ext"
-    run_dump_test "notoc"
 }
 
 run_dump_test "tlsld32"

-- 
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]