public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PowerPC64: stub debug dump
@ 2022-06-22  3:08 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2022-06-22  3:08 UTC (permalink / raw)
  To: binutils

powerpc64le-linux-ld is failing the assertion in ppc_build_one_stub,
again apparently, which means a stub will overwrite the tail of a
previous stub.  The difficulty with debugging these issues is that
it's not a problem with the stub that triggers the assertion, but the
previous stub in that section.  This patch keeps track of the last
stub and adds a debug dump.  Hopefully that will help.

	* elf64-ppc.c (enum _ppc64_sec_type): Add sec_stub.
	(struct _ppc64_elf_section_data): Add u.last_ent.
	(dump_previous_stub): New function.
	(ppc_build_one_stub): Keep track of previous stub, and dump it
	when finding an overlapping stub.

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 6e2016c150d..c69b07435a1 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -1996,7 +1996,8 @@ static const struct bfd_elf_special_section ppc64_elf_special_sections[] =
 enum _ppc64_sec_type {
   sec_normal = 0,
   sec_opd = 1,
-  sec_toc = 2
+  sec_toc = 2,
+  sec_stub = 3
 };
 
 struct _ppc64_elf_section_data
@@ -2026,6 +2027,9 @@ struct _ppc64_elf_section_data
       /* And the relocation addend.  */
       bfd_vma *add;
     } toc;
+
+    /* Stub debugging.  */
+    struct ppc_stub_hash_entry *last_ent;
   } u;
 
   enum _ppc64_sec_type sec_type:2;
@@ -11636,6 +11640,47 @@ get_r2off (struct bfd_link_info *info,
   return r2off;
 }
 
+/* Debug dump.  */
+
+static void
+dump_previous_stub (struct ppc_stub_hash_entry *stub_entry)
+{
+  asection *stub_sec = stub_entry->group->stub_sec;
+  struct _ppc64_elf_section_data *esd = ppc64_elf_section_data (stub_sec);
+  if (esd->sec_type == sec_stub)
+    {
+      fprintf (stderr, "Previous stub: type = ");
+      switch (esd->u.last_ent->type.main)
+	{
+	case ppc_stub_none: fprintf (stderr, "none"); break;
+	case ppc_stub_long_branch: fprintf (stderr, "long_branch"); break;
+	case ppc_stub_plt_branch: fprintf (stderr, "plt_branch"); break;
+	case ppc_stub_plt_call: fprintf (stderr, "plt_call"); break;
+	case ppc_stub_global_entry: fprintf (stderr, "global_entry"); break;
+	case ppc_stub_save_res: fprintf (stderr, "save_res"); break;
+	default: fprintf (stderr, "???"); break;
+	}
+      switch (esd->u.last_ent->type.sub)
+	{
+	case ppc_stub_toc: fprintf (stderr, ":toc"); break;
+	case ppc_stub_notoc: fprintf (stderr, ":notoc"); break;
+	case ppc_stub_p9notoc: fprintf (stderr, ":p9notoc"); break;
+	default: fprintf (stderr, ":???"); break;
+	}
+      if (esd->u.last_ent->type.r2save)
+	fprintf (stderr, ":r2save");
+      fprintf (stderr, "\nname = %s", esd->u.last_ent->root.string);
+      fprintf (stderr, "\noffset = %#lx:", esd->u.last_ent->stub_offset);
+      for (size_t i = esd->u.last_ent->stub_offset;
+	   i < stub_entry->stub_offset; i += 4)
+	{
+	  uint32_t *p = (uint32_t *) (stub_sec->contents + i);
+	  fprintf (stderr, " %08x", *p);
+	}
+      fprintf (stderr, "\n");
+    }
+}
+
 static bool
 ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
@@ -11680,7 +11725,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab == NULL)
     return false;
 
-  BFD_ASSERT (stub_entry->stub_offset >= stub_entry->group->stub_sec->size);
+  if (stub_entry->stub_offset < stub_entry->group->stub_sec->size)
+    {
+      BFD_ASSERT (0);
+      dump_previous_stub (stub_entry);
+    }
   loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
 
   htab->stub_count[stub_entry->type.main - 1] += 1;
@@ -12122,6 +12171,12 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     }
 
   stub_entry->group->stub_sec->size = stub_entry->stub_offset + (p - loc);
+  struct _ppc64_elf_section_data *esd
+    = ppc64_elf_section_data (stub_entry->group->stub_sec);
+  if (esd->sec_type == sec_normal)
+    esd->sec_type = sec_stub;
+  if (esd->sec_type == sec_stub)
+    esd->u.last_ent = stub_entry;
 
   if (htab->params->emit_stub_syms)
     {

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: PowerPC64: stub debug dump
@ 2022-06-23  8:34 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2022-06-23  8:34 UTC (permalink / raw)
  To: binutils

Let's show the current stub as well as the previous one.  Of interest
is the current offset and a new field, id.  Check that the build
hash table traversal is in the same order as sizing traversal too.

	* elf64-ppc.c (struct ppc_stub_hash_entry): Add id.
	(struct ppc_link_hash_table): Add stub_id.
	(stub_hash_newfunc): Init id and symtype.
	(dump_stub): New function, extracted from..
	(dump_previous_stub): ..here.  Deleted.
	(ppc_build_one_stub): Sanity check stub id as well as offset.
	Show current stub as well as previous.
	(ppc_size_one_stub): Set stub id.
	(ppc64_elf_size_stubs): Init stub_id before traversal.
	(ppc64_elf_build_stubs): Likewise.

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index c69b07435a1..6af33d883b3 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -3083,6 +3083,9 @@ struct ppc_stub_hash_entry
 
   /* Symbol st_other.  */
   unsigned char other;
+
+  /* Debug: Track hash table traversal.  */
+  unsigned int id;
 };
 
 struct ppc_branch_hash_entry
@@ -3321,6 +3324,9 @@ struct ppc_link_hash_table
   /* Whether any code linked seems to be Power10.  */
   unsigned int has_power10_relocs:1;
 
+  /* Incremented once for each stub sized.  */
+  unsigned int stub_id;
+
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
 
@@ -3401,7 +3407,9 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       eh->target_section = NULL;
       eh->h = NULL;
       eh->plt_ent = NULL;
+      eh->symtype = 0;
       eh->other = 0;
+      eh->id = 0;
     }
 
   return entry;
@@ -11643,42 +11651,40 @@ get_r2off (struct bfd_link_info *info,
 /* Debug dump.  */
 
 static void
-dump_previous_stub (struct ppc_stub_hash_entry *stub_entry)
+dump_stub (const char *header,
+	   struct ppc_stub_hash_entry *stub_entry,
+	   size_t end_offset)
 {
-  asection *stub_sec = stub_entry->group->stub_sec;
-  struct _ppc64_elf_section_data *esd = ppc64_elf_section_data (stub_sec);
-  if (esd->sec_type == sec_stub)
+  const char *t1, *t2, *t3;
+  switch (stub_entry->type.main)
     {
-      fprintf (stderr, "Previous stub: type = ");
-      switch (esd->u.last_ent->type.main)
-	{
-	case ppc_stub_none: fprintf (stderr, "none"); break;
-	case ppc_stub_long_branch: fprintf (stderr, "long_branch"); break;
-	case ppc_stub_plt_branch: fprintf (stderr, "plt_branch"); break;
-	case ppc_stub_plt_call: fprintf (stderr, "plt_call"); break;
-	case ppc_stub_global_entry: fprintf (stderr, "global_entry"); break;
-	case ppc_stub_save_res: fprintf (stderr, "save_res"); break;
-	default: fprintf (stderr, "???"); break;
-	}
-      switch (esd->u.last_ent->type.sub)
-	{
-	case ppc_stub_toc: fprintf (stderr, ":toc"); break;
-	case ppc_stub_notoc: fprintf (stderr, ":notoc"); break;
-	case ppc_stub_p9notoc: fprintf (stderr, ":p9notoc"); break;
-	default: fprintf (stderr, ":???"); break;
-	}
-      if (esd->u.last_ent->type.r2save)
-	fprintf (stderr, ":r2save");
-      fprintf (stderr, "\nname = %s", esd->u.last_ent->root.string);
-      fprintf (stderr, "\noffset = %#lx:", esd->u.last_ent->stub_offset);
-      for (size_t i = esd->u.last_ent->stub_offset;
-	   i < stub_entry->stub_offset; i += 4)
-	{
-	  uint32_t *p = (uint32_t *) (stub_sec->contents + i);
-	  fprintf (stderr, " %08x", *p);
-	}
-      fprintf (stderr, "\n");
+    case ppc_stub_none:		t1 = "none";		break;
+    case ppc_stub_long_branch:	t1 = "long_branch";	break;
+    case ppc_stub_plt_branch:	t1 = "plt_branch";	break;
+    case ppc_stub_plt_call:	t1 = "plt_call";	break;
+    case ppc_stub_global_entry:	t1 = "global_entry";	break;
+    case ppc_stub_save_res:	t1 = "save_res";	break;
+    default:			t1 = "???";		break;
+    }
+  switch (stub_entry->type.sub)
+    {
+    case ppc_stub_toc:		t2 = "toc";		break;
+    case ppc_stub_notoc:	t2 = "notoc";		break;
+    case ppc_stub_p9notoc:	t2 = "p9notoc";		break;
+    default:			t2 = "???";		break;
+    }
+  t3 = stub_entry->type.r2save ? "r2save" : "";
+  fprintf (stderr, "%s id = %u type = %s:%s:%s\n",
+	   header, stub_entry->id, t1, t2, t3);
+  fprintf (stderr, "name = %s\n", stub_entry->root.string);
+  fprintf (stderr, "offset = %#lx:", stub_entry->stub_offset);
+  for (size_t i = stub_entry->stub_offset; i < end_offset; i += 4)
+    {
+      asection *stub_sec = stub_entry->group->stub_sec;
+      uint32_t *p = (uint32_t *) (stub_sec->contents + i);
+      fprintf (stderr, " %08x", (uint32_t) bfd_get_32 (stub_sec->owner, p));
     }
+  fprintf (stderr, "\n");
 }
 
 static bool
@@ -11725,11 +11731,28 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab == NULL)
     return false;
 
-  if (stub_entry->stub_offset < stub_entry->group->stub_sec->size)
+  struct _ppc64_elf_section_data *esd
+    = ppc64_elf_section_data (stub_entry->group->stub_sec);
+  ++htab->stub_id;
+  if (stub_entry->id != htab->stub_id
+      || stub_entry->stub_offset < stub_entry->group->stub_sec->size)
     {
       BFD_ASSERT (0);
-      dump_previous_stub (stub_entry);
+      if (stub_entry->id != htab->stub_id)
+	fprintf (stderr, "Expected id %u, got %u\n",
+		 htab->stub_id, stub_entry->id);
+      if (stub_entry->stub_offset < stub_entry->group->stub_sec->size)
+	fprintf (stderr, "Expected offset >= %" BFD_VMA_FMT "x, got %"
+		 BFD_VMA_FMT "x\n", stub_entry->group->stub_sec->size,
+		 stub_entry->stub_offset);
+      if (esd->sec_type == sec_stub)
+	dump_stub ("Previous:", esd->u.last_ent, stub_entry->stub_offset);
+      dump_stub ("Current:", stub_entry, 0);
     }
+  if (esd->sec_type == sec_normal)
+    esd->sec_type = sec_stub;
+  if (esd->sec_type == sec_stub)
+    esd->u.last_ent = stub_entry;
   loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
 
   htab->stub_count[stub_entry->type.main - 1] += 1;
@@ -12171,12 +12194,6 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     }
 
   stub_entry->group->stub_sec->size = stub_entry->stub_offset + (p - loc);
-  struct _ppc64_elf_section_data *esd
-    = ppc64_elf_section_data (stub_entry->group->stub_sec);
-  if (esd->sec_type == sec_normal)
-    esd->sec_type = sec_stub;
-  if (esd->sec_type == sec_stub)
-    esd->u.last_ent = stub_entry;
 
   if (htab->params->emit_stub_syms)
     {
@@ -12262,6 +12279,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab->stub_iteration > STUB_SHRINK_ITER
       && stub_entry->stub_offset > stub_offset)
     stub_offset = stub_entry->stub_offset;
+  stub_entry->id = ++htab->stub_id;
 
   if (stub_entry->h != NULL
       && stub_entry->h->save_res
@@ -14218,6 +14236,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 	}
 
       htab->stub_changed = false;
+      htab->stub_id = 0;
       bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
 
       for (group = htab->group; group != NULL; group = group->next)
@@ -15153,6 +15172,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
     }
 
   /* Build the stubs as directed by the stub hash table.  */
+  htab->stub_id = 0;
   bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
 
   for (group = htab->group; group != NULL; group = group->next)

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-06-23  8:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-22  3:08 PowerPC64: stub debug dump Alan Modra
2022-06-23  8:34 Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).