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

[PATCH] Fix objdump -d on ppc64 without dot syms (take 2)


On Sat, Aug 14, 2004 at 09:13:41AM +0930, Alan Modra wrote:
> On Fri, Aug 13, 2004 at 05:16:32PM +0200, Jakub Jelinek wrote:
> > This patch synthetizes the function symbols from opd.
> > Ok to commit?
> 
> Yes, thanks very much!  Before committing, please move the new code
> above the comment that says
> "The following functions are specific to the ELF linker, while
> functions above are used generally."

The previous patch unfortunately did not work for ET_REL objects,
so here is new extended version of the patch which touches even objdump.c
and various files in bfd/.

BTW: with this and also
http://sources.redhat.com/ml/binutils/2004-08/msg00030.html
patch in the tree I'm getting a bunch of failres with gcc 3.4 on ppc64.
With unpatched gcc 3.4.1 I'm getting:
FAIL: visibility (hidden_undef_def) (non PIC)
FAIL: visibility (hidden_undef_def) (non PIC, load offset)
FAIL: visibility (hidden_undef_def)
FAIL: visibility (hidden_undef_def) (PIC main, non PIC so)
FAIL: visibility (hidden_undef_def) (PIC main)
(see the above URL for details), when using gcc 3.4.1 with your dot syms
patch these failures go away, but there are 4 new ones:
FAIL: NOCROSSREFS 1
FAIL: selective1
FAIL: selective2
FAIL: S-records

2004-08-14  Jakub Jelinek  <jakub@redhat.com>

bfd/
	* elfxx-target.h (bfd_elfNN_get_synthetic_symtab): Only define
	if not yet defined.
	* elf64-ppc.c (bfd_elf64_get_synthetic_symtab): Define.
	(synthetic_opd, synthetic_relocatable): New variables.
	(compare_symbols, compare_relocs): New helper routines.
	(ppc64_elf_get_synthetic_symtab): New function.
	* bfd.c (bfd_get_synthetic_symtab): Rename dynsyms argument
	to relsyms.
	* bfd-in2.h: Regenerated.
	* elf.c (_bfd_elf_get_synthetic_symtab): Rename dynsyms argument
	to relsyms.  Return 0 if abfd is relocatable.
binutils/
	* objdump.c (dump_bfd): For relocatable objects, pass syms instead
	of dynsyms to bfd_get_synthetic_symtab.

--- bfd/elfxx-target.h.jj	2004-08-09 10:51:28.000000000 +0200
+++ bfd/elfxx-target.h	2004-08-13 13:55:48.000000000 +0200
@@ -34,8 +34,10 @@
 
 #define bfd_elfNN_canonicalize_dynamic_symtab \
   _bfd_elf_canonicalize_dynamic_symtab
+#ifndef bfd_elfNN_get_synthetic_symtab
 #define bfd_elfNN_get_synthetic_symtab \
   _bfd_elf_get_synthetic_symtab
+#endif
 #ifndef bfd_elfNN_canonicalize_reloc
 #define bfd_elfNN_canonicalize_reloc	_bfd_elf_canonicalize_reloc
 #endif
--- bfd/elf64-ppc.c.jj	2004-08-13 14:15:37.000000000 +0200
+++ bfd/elf64-ppc.c	2004-08-14 17:41:16.889771077 +0200
@@ -76,6 +76,7 @@ static bfd_reloc_status_type ppc64_elf_u
 #define bfd_elf64_new_section_hook	      ppc64_elf_new_section_hook
 #define bfd_elf64_bfd_link_hash_table_create  ppc64_elf_link_hash_table_create
 #define bfd_elf64_bfd_link_hash_table_free    ppc64_elf_link_hash_table_free
+#define bfd_elf64_get_synthetic_symtab	      ppc64_elf_get_synthetic_symtab
 
 #define elf_backend_object_p		      ppc64_elf_object_p
 #define elf_backend_grok_prstatus	      ppc64_elf_grok_prstatus
@@ -2505,6 +2506,389 @@ get_opd_info (asection * sec)
   return NULL;
 }
 
+/* Parameters for the qsort hook.  */
+static asection *synthetic_opd;
+static bfd_boolean synthetic_relocatable;
+
+/* Helper routine for ppc64_elf_get_synthetic_symtab.  */
+
+static int
+compare_symbols (const void *ap, const void *bp)
+{
+  const asymbol *a = * (const asymbol **) ap;
+  const asymbol *b = * (const asymbol **) bp;
+
+  if ((a->flags & BSF_SECTION_SYM) == 0 && (b->flags & BSF_SECTION_SYM))
+    return -1;
+  if ((a->flags & BSF_SECTION_SYM) && (b->flags & BSF_SECTION_SYM) == 0)
+    return 1;
+
+  if (a->section == synthetic_opd && b->section != synthetic_opd)
+    return -1;
+  if (a->section != synthetic_opd && b->section == synthetic_opd)
+    return 1;
+
+  if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+      == (SEC_CODE | SEC_ALLOC)
+      && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+	 != (SEC_CODE | SEC_ALLOC))
+    return -1;
+
+  if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+      != (SEC_CODE | SEC_ALLOC)
+      && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+	 == (SEC_CODE | SEC_ALLOC))
+    return 1;
+
+  if (synthetic_relocatable)
+    {
+      if (a->section->id < b->section->id)
+	return -1;
+
+      if (a->section->id > b->section->id)
+	return 1;
+    }
+
+  if (a->value + a->section->vma < b->value + b->section->vma)
+    return -1;
+
+  if (a->value + a->section->vma > b->value + b->section->vma)
+    return 1;
+
+  return 0;
+}
+
+/* Helper routine for ppc64_elf_get_synthetic_symtab.  */
+
+static int
+compare_relocs (const void *ap, const void *bp)
+{
+  const arelent *a = * (const arelent **) ap;
+  const arelent *b = * (const arelent **) bp;
+
+  if (a->address < b->address)
+    return -1;
+
+  if (a->address > b->address)
+    return 1;
+
+  return 0;
+}
+
+/* Create synthetic symbols.  */
+
+static long
+ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
+{
+  asymbol *s;
+  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+  arelent **relocs, **r;
+  long count, i;
+  size_t size;
+  char *names;
+  asymbol **syms = NULL;
+  long symcount = 0, opdsymcount, relcount;
+  asection *relopd, *opd;
+  bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
+
+  *ret = NULL;
+
+  opd = bfd_get_section_by_name (abfd, ".opd");
+  if (opd == NULL)
+    return 0;
+
+  if ((bfd_get_file_flags (abfd) & HAS_SYMS))
+    {
+      long storage;
+      storage = bfd_get_symtab_upper_bound (abfd);
+      if (storage < 0)
+	return 0;
+
+      if (storage)
+	{
+	  syms = bfd_malloc (storage);
+	  if (syms == NULL)
+	    return 0;
+	}
+
+      symcount = bfd_canonicalize_symtab (abfd, syms);
+      if (symcount < 0)
+	{
+	  free (syms);
+	  return 0;
+	}
+
+      if (symcount == 0)
+	{
+	  free (syms);
+	  syms = NULL;
+	}
+    }
+
+  if (symcount == 0)
+    {
+      long storage;
+
+      storage = bfd_get_dynamic_symtab_upper_bound (abfd);
+      if (storage < 0)
+	return 0;
+
+      if (storage)
+	{
+	  syms = bfd_malloc (storage);
+	  if (syms == NULL)
+	    return 0;
+	}
+
+      symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
+      if (symcount < 0)
+	{
+	  free (syms);
+	  return 0;
+	}
+    }
+
+  synthetic_opd = opd;
+  synthetic_relocatable = relocatable;
+  qsort (syms, symcount, sizeof (asymbol *), compare_symbols);
+
+  opdsymcount = symcount;
+  for (i = 0; i < symcount; ++i)
+    {
+      if (syms[i]->flags & BSF_SECTION_SYM)
+	{
+	  if (opdsymcount == symcount)
+	    opdsymcount = i;
+	  symcount = i;
+	  break;
+	}
+
+      if (syms[i]->section == opd)
+	continue;
+
+      if (opdsymcount == symcount)
+	opdsymcount = i;
+
+      if ((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+	  != (SEC_CODE | SEC_ALLOC))
+	{
+	  symcount = i;
+	  break;
+	}
+    }
+
+  if (opdsymcount == 0)
+    {
+      free (syms);
+      return 0;
+    }
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  if (! relocatable)
+    {
+      relopd = bfd_get_section_by_name (abfd, ".rela.opd");
+      if (relopd == NULL)
+	{
+	  relopd = bfd_get_section_by_name (abfd, ".rela.dyn");
+	  if (relopd == NULL)
+	    {
+	      free (syms);
+	      return 0;
+	    }
+	}
+      relcount = relopd->size / 24;
+
+      if (! relcount
+	  || ! (*slurp_relocs) (abfd, relopd, relsyms, TRUE))
+	{
+	  free (syms);
+	  return 0;
+	}
+    }
+  else
+    {
+      relopd = opd;
+      relcount = (opd->flags & SEC_RELOC) ? opd->reloc_count : 0;
+
+      if (! relcount
+	  || ! (*slurp_relocs) (abfd, relopd, relsyms, FALSE))
+	{
+	  free (syms);
+	  return 0;
+	}
+    }
+
+  relocs = bfd_malloc (relcount * sizeof (arelent **));
+  if (relocs == NULL)
+    {
+      free (syms);
+      return 0;
+    }
+
+  for (i = 0; i < relcount; ++i)
+    relocs[i] = &relopd->relocation[i];
+
+  qsort (relocs, relcount, sizeof (*relocs), compare_relocs);
+
+  size = 0;
+  count = 0;
+  for (i = 0, r = relocs; i < opdsymcount; ++i)
+    {
+      long lo, hi, mid;
+      asymbol *sym;
+
+      while (r < relocs + relcount
+	     && (*r)->address < syms[i]->value + opd->vma)
+	++r;
+
+      if (r == relocs + relcount)
+	continue;
+
+      if ((*r)->address != syms[i]->value + opd->vma)
+	continue;
+
+      if ((*r)->howto->type != (relocatable
+				? R_PPC64_ADDR64 : R_PPC64_RELATIVE))
+	continue;
+
+      lo = opdsymcount;
+      hi = symcount;
+      sym = *((*r)->sym_ptr_ptr);
+      if (relocatable)
+	while (lo < hi)
+	  {
+	    mid = (lo + hi) >> 1;
+	    if (syms[mid]->section->id < sym->section->id)
+	      lo = mid + 1;
+	    else if (syms[mid]->section->id > sym->section->id)
+	      hi = mid;
+	    else if (syms[mid]->value < sym->value + (*r)->addend)
+	      lo = mid + 1;
+	    else if (syms[mid]->value > sym->value + (*r)->addend)
+	      hi = mid;
+	    else
+	      break;
+	  }
+      else
+	while (lo < hi)
+	  {
+	    mid = (lo + hi) >> 1;
+	    if (syms[mid]->value + syms[mid]->section->vma < (*r)->addend)
+	      lo = mid + 1;
+	    else if (syms[mid]->value + syms[mid]->section->vma > (*r)->addend)
+	      hi = mid;
+	    else
+	      break;
+	  }
+
+      if (lo >= hi)
+	{
+	  ++count;
+	  size += sizeof (asymbol);
+	  size += strlen (syms[i]->name) + 1;
+	}
+    }
+
+  s = *ret = bfd_malloc (size);
+  if (s == NULL)
+    {
+      free (syms);
+      free (relocs);
+      return 0;
+    }
+
+  names = (char *) (s + count);
+
+  for (i = 0, r = relocs; i < opdsymcount; ++i)
+    {
+      long lo, hi, mid;
+      asymbol *sym;
+
+      while (r < relocs + relcount
+	     && (*r)->address < syms[i]->value + opd->vma)
+	++r;
+
+      if (r == relocs + relcount)
+	continue;
+
+      if ((*r)->address != syms[i]->value + opd->vma)
+	continue;
+
+      if ((*r)->howto->type != (relocatable
+				? R_PPC64_ADDR64 : R_PPC64_RELATIVE))
+	continue;
+
+      lo = opdsymcount;
+      hi = symcount;
+      sym = *((*r)->sym_ptr_ptr);
+      if (relocatable)
+	while (lo < hi)
+	  {
+	    mid = (lo + hi) >> 1;
+	    if (syms[mid]->section->id < sym->section->id)
+	      lo = mid + 1;
+	    else if (syms[mid]->section->id > sym->section->id)
+	      hi = mid;
+	    else if (syms[mid]->value < sym->value + (*r)->addend)
+	      lo = mid + 1;
+	    else if (syms[mid]->value > sym->value + (*r)->addend)
+	      hi = mid;
+	    else
+	      break;
+	  }
+      else
+	while (lo < hi)
+	  {
+	    mid = (lo + hi) >> 1;
+	    if (syms[mid]->value + syms[mid]->section->vma < (*r)->addend)
+	      lo = mid + 1;
+	    else if (syms[mid]->value + syms[mid]->section->vma > (*r)->addend)
+	      hi = mid;
+	    else
+	      break;
+	  }
+
+      if (lo >= hi)
+	{
+	  size_t len;
+
+	  *s = *syms[i];
+	  
+	  if (! relocatable)
+	    {
+	      asection *sec;
+
+	      s->section = &bfd_abs_section;
+	      for (sec = abfd->sections; sec; sec = sec->next)
+		if ((sec->flags & (SEC_ALLOC | SEC_CODE))
+		    == (SEC_ALLOC | SEC_CODE)
+		    && (*r)->addend >= sec->vma
+		    && (*r)->addend < sec->vma + sec->size)
+		  {
+		    s->section = sec;
+		    break;
+		  }
+	      s->value = (*r)->addend - sec->vma;
+	    }
+	  else
+	    {
+	      s->section = sym->section;
+	      s->value = sym->value + (*r)->addend;
+	    }
+	  s->name = names;
+	  len = strlen (syms[i]->name);
+	  memcpy (names, syms[i]->name, len + 1);
+	  names += len + 1;
+	  s++;
+	}
+    }
+
+  free (syms);
+  free (relocs);
+  return count;
+}
+
+
 /* The following functions are specific to the ELF linker, while
    functions above are used generally.  Those named ppc64_elf_* are
    called by the main ELF linker code.  They appear in this file more
--- bfd/bfd.c.jj	2004-08-13 13:23:04.000000000 +0200
+++ bfd/bfd.c	2004-08-14 17:31:22.121576931 +0200
@@ -1216,8 +1216,8 @@ DESCRIPTION
 .#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
 .	BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
 .
-.#define bfd_get_synthetic_symtab(abfd, dynsyms, ret) \
-.	BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, dynsyms, ret))
+.#define bfd_get_synthetic_symtab(abfd, relsyms, ret) \
+.	BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, relsyms, ret))
 .
 .#define bfd_get_dynamic_reloc_upper_bound(abfd) \
 .	BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
--- bfd/bfd-in2.h.jj	2004-08-13 13:23:04.000000000 +0200
+++ bfd/bfd-in2.h	2004-08-14 17:31:43.146907570 +0200
@@ -4109,8 +4109,8 @@ bfd_boolean bfd_set_private_flags (bfd *
 #define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
        BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
 
-#define bfd_get_synthetic_symtab(abfd, dynsyms, ret) \
-       BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, dynsyms, ret))
+#define bfd_get_synthetic_symtab(abfd, relsyms, ret) \
+       BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, relsyms, ret))
 
 #define bfd_get_dynamic_reloc_upper_bound(abfd) \
        BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
--- bfd/elf.c.jj	2004-08-13 13:23:08.000000000 +0200
+++ bfd/elf.c	2004-08-14 17:35:59.187221827 +0200
@@ -7744,7 +7744,7 @@ bfd_elf_bfd_from_remote_memory
 }
 
 long
-_bfd_elf_get_synthetic_symtab (bfd *abfd, asymbol **dynsyms, asymbol **ret)
+_bfd_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   asection *relplt;
@@ -7758,6 +7758,9 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd
   char *names;
   asection *plt;
 
+  if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+    return 0;
+
   *ret = NULL;
   if (!bed->plt_sym_val)
     return 0;
@@ -7779,7 +7782,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd
     return 0;
 
   slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
-  if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
+  if (! (*slurp_relocs) (abfd, relplt, relsyms, TRUE))
     return -1;
 
   count = relplt->size / hdr->sh_entsize;
--- binutils/objdump.c.jj	2004-07-30 11:42:03.000000000 +0200
+++ binutils/objdump.c	2004-08-14 14:06:21.217852998 +0200
@@ -2564,9 +2564,19 @@ dump_bfd (bfd *abfd)
   if (dump_dynamic_symtab || dump_dynamic_reloc_info
       || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
     dynsyms = slurp_dynamic_symtab (abfd);
-  if (disassemble && dynsymcount > 0)
+  if (disassemble)
     {
-      synthcount = bfd_get_synthetic_symtab (abfd, dynsyms, &synthsyms);
+      synthcount = 0;
+      if (bfd_get_file_flags (abfd) & (DYNAMIC | EXEC_P))
+	{
+	  if (dynsymcount > 0)
+	    synthcount = bfd_get_synthetic_symtab (abfd, dynsyms, &synthsyms);
+	}
+      else
+	{
+	  if (symcount > 0)
+	    synthcount = bfd_get_synthetic_symtab (abfd, syms, &synthsyms);
+	}
       if (synthcount < 0) synthcount = 0;
     }
 


	Jakub


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