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]

objdump improvements for mips elf64


This patch fixes two problems in objdump on mips elf64:

- objdump didn't support dumping dynamic relocations at all

- objdump would display only 1/3 of the total number of relocations,
  because it used the external relocation count, but each external
  relocation is brought in as 3 internal relocations.

This patch fixes both problems.  Eric Christopher approved the
mips-specific bits already, but I need approval for the minor (almost
obvious) bit in elfxx-target.h.  Ok to install?

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva at redhat dot com>

	* elfxx-target.h (bfd_elfNN_canonicalize_reloc): Make it
	overridable.
	* elf64-mips.c (mips_elf64_canonicalize_reloc,
	mips_elf64_get_dynamic_reloc_upper_bound,
	mips_elf64_canonicalize_dynamic_reloc): New, adapted from elf.c.
	(bfd_elf64_get_canonicalize_reloc,
	bfd_elf64_get_dynamic_reloc_upper_bound,
	bfd_elf64_canonicalize_dynamic_reloc): Define.
	(mips_elf64_slurp_reloc_table): Support dynamic.
	(mips_elf64_slurp_one_reloc_table): Adjust.

Index: bfd/elf64-mips.c
===================================================================
RCS file: /cvs/uberbaum/bfd/elf64-mips.c,v
retrieving revision 1.44
diff -u -p -r1.44 elf64-mips.c
--- bfd/elf64-mips.c 2 Mar 2003 21:30:14 -0000 1.44
+++ bfd/elf64-mips.c 7 Mar 2003 20:36:54 -0000
@@ -91,8 +91,14 @@ static void mips_elf64_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 static long mips_elf64_get_reloc_upper_bound
   PARAMS ((bfd *, asection *));
+static long mips_elf64_canonicalize_reloc
+  PARAMS ((bfd *, asection *, arelent **, asymbol **));
+static long mips_elf64_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
+static long mips_elf64_canonicalize_dynamic_reloc
+  PARAMS ((bfd *, arelent **, asymbol **));
 static bfd_boolean mips_elf64_slurp_one_reloc_table
-  PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
+  PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type,
+	   arelent *, asymbol **, bfd_boolean));
 static bfd_boolean mips_elf64_slurp_reloc_table
   PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
 static void mips_elf64_write_relocs
@@ -2022,20 +2028,104 @@ mips_elf64_get_reloc_upper_bound (abfd, 
   return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
 }
 
-/* Read the relocations from one reloc section.  */
+static long
+mips_elf64_get_dynamic_reloc_upper_bound (abfd)
+     bfd *abfd;
+{
+  return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
+}
+
+/* We must also copy more relocations than the corresponding functions
+   in elf.c would, so the two following functions are slightly
+   modified from elf.c, that multiply the external relocation count by
+   3 to obtain the internal relocation count.  */
+
+static long
+mips_elf64_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr;
+  unsigned int i;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
+    return -1;
+
+  tblptr = section->relocation;
+  for (i = 0; i < section->reloc_count * 3; i++)
+    *relptr++ = tblptr++;
+
+  *relptr = NULL;
+
+  return section->reloc_count * 3;
+}
+
+static long
+mips_elf64_canonicalize_dynamic_reloc (abfd, storage, syms)
+     bfd *abfd;
+     arelent **storage;
+     asymbol **syms;
+{
+  bfd_boolean (*slurp_relocs)
+    PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
+  asection *s;
+  long ret;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  ret = 0;
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+	  && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+	      || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+	{
+	  arelent *p;
+	  long count, i;
+
+	  if (! (*slurp_relocs) (abfd, s, syms, TRUE))
+	    return -1;
+	  count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize * 3;
+	  p = s->relocation;
+	  for (i = 0; i < count; i++)
+	    *storage++ = p++;
+	  ret += count;
+	}
+    }
+
+  *storage = NULL;
+
+  return ret;
+}
+
+/* Read the relocations from one reloc section.  This is mostly copied
+   from elfcode.h, except for the changes to expand one external
+   relocation to 3 internal ones.  We must unfortunately set
+   reloc_count to the number of external relocations, because a lot of
+   generic code seems to depend on this.  */
 
 static bfd_boolean
-mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
+mips_elf64_slurp_one_reloc_table (abfd, asect, rel_hdr, reloc_count,
+				  relents, symbols, dynamic)
      bfd *abfd;
      asection *asect;
+     Elf_Internal_Shdr *rel_hdr;
+     bfd_size_type reloc_count;
+     arelent *relents;
      asymbol **symbols;
-     const Elf_Internal_Shdr *rel_hdr;
+     bfd_boolean dynamic;
 {
   PTR allocated = NULL;
   bfd_byte *native_relocs;
-  arelent *relents;
   arelent *relent;
-  bfd_vma count;
   bfd_vma i;
   int entsize;
   reloc_howto_type *howto_table;
@@ -2045,26 +2135,24 @@ mips_elf64_slurp_one_reloc_table (abfd, 
     return FALSE;
 
   if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
-      || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
+      || (bfd_bread (allocated, rel_hdr->sh_size, abfd)
+	  != rel_hdr->sh_size))
     goto error_return;
 
   native_relocs = (bfd_byte *) allocated;
 
-  relents = asect->relocation + asect->reloc_count;
-
   entsize = rel_hdr->sh_entsize;
   BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
 	      || entsize == sizeof (Elf64_Mips_External_Rela));
 
-  count = rel_hdr->sh_size / entsize;
-
   if (entsize == sizeof (Elf64_Mips_External_Rel))
     howto_table = mips_elf64_howto_table_rel;
   else
     howto_table = mips_elf64_howto_table_rela;
 
-  relent = relents;
-  for (i = 0; i < count; i++, native_relocs += entsize)
+  for (i = 0, relent = relents;
+       i < reloc_count;
+       i++, native_relocs += entsize)
     {
       Elf64_Mips_Internal_Rela rela;
       bfd_boolean used_sym, used_ssym;
@@ -2166,7 +2254,7 @@ mips_elf64_slurp_one_reloc_table (abfd, 
 	     object file, and absolute for an executable file or
 	     shared library.  The address of a BFD reloc is always
 	     section relative.  */
-	  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+	  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
 	    relent->address = rela.r_offset;
 	  else
 	    relent->address = rela.r_offset - asect->vma;
@@ -2193,7 +2281,10 @@ mips_elf64_slurp_one_reloc_table (abfd, 
 }
 
 /* Read the relocations.  On Irix 6, there can be two reloc sections
-   associated with a single data section.  */
+   associated with a single data section.  This is copied from
+   elfcode.h as well, with changes as small as accounting for 3
+   internal relocs per external reloc and resetting reloc_count to
+   zero before processing the relocs of a section.  */
 
 static bfd_boolean
 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
@@ -2202,39 +2293,72 @@ mips_elf64_slurp_reloc_table (abfd, asec
      asymbol **symbols;
      bfd_boolean dynamic;
 {
-  bfd_size_type amt;
   struct bfd_elf_section_data * const d = elf_section_data (asect);
+  Elf_Internal_Shdr *rel_hdr;
+  Elf_Internal_Shdr *rel_hdr2;
+  bfd_size_type reloc_count;
+  bfd_size_type reloc_count2;
+  arelent *relents;
+  bfd_size_type amt;
 
-  if (dynamic)
+  if (asect->relocation != NULL)
+    return TRUE;
+
+  if (! dynamic)
     {
-      bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
-    }
+      if ((asect->flags & SEC_RELOC) == 0
+	  || asect->reloc_count == 0)
+	return TRUE;
+
+      rel_hdr = &d->rel_hdr;
+      reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
+      rel_hdr2 = d->rel_hdr2;
+      reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
+
+      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
+		  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
-  if (asect->relocation != NULL
-      || (asect->flags & SEC_RELOC) == 0
-      || asect->reloc_count == 0)
-    return TRUE;
+    }
+  else
+    {
+      /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
+	 case because relocations against this section may use the
+	 dynamic symbol table, and in that case bfd_section_from_shdr
+	 in elf.c does not update the RELOC_COUNT.  */
+      if (asect->_raw_size == 0)
+	return TRUE;
+
+      rel_hdr = &d->this_hdr;
+      reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
+      rel_hdr2 = NULL;
+      reloc_count2 = 0;
+    }
 
   /* Allocate space for 3 arelent structures for each Rel structure.  */
-  amt = asect->reloc_count;
-  amt *= 3 * sizeof (arelent);
-  asect->relocation = (arelent *) bfd_alloc (abfd, amt);
-  if (asect->relocation == NULL)
+  amt = (reloc_count + reloc_count2) * 3 * sizeof (arelent);
+  relents = (arelent *) bfd_alloc (abfd, amt);
+  if (relents == NULL)
     return FALSE;
 
   /* The slurp_one_reloc_table routine increments reloc_count.  */
   asect->reloc_count = 0;
 
-  if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
+  if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
+					  rel_hdr, reloc_count,
+					  relents,
+					  symbols, dynamic))
     return FALSE;
   if (d->rel_hdr2 != NULL)
     {
-      if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
-					      d->rel_hdr2))
+      if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
+					      rel_hdr2, reloc_count2,
+					      relents + reloc_count * 3,
+					      symbols, dynamic))
 	return FALSE;
     }
 
+  asect->relocation = relents;
   return TRUE;
 }
 
@@ -2764,6 +2888,9 @@ const struct elf_size_info mips_elf64_si
 				_bfd_mips_elf_print_private_bfd_data
 
 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
+#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
+#define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
+#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
 
 /* MIPS ELF64 archive functions.  */
 #define bfd_elf64_archive_functions
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/uberbaum/bfd/elfxx-target.h,v
retrieving revision 1.49
diff -u -p -r1.49 elfxx-target.h
--- bfd/elfxx-target.h 23 Jan 2003 11:51:33 -0000 1.49
+++ bfd/elfxx-target.h 7 Mar 2003 20:36:54 -0000
@@ -33,7 +33,9 @@
 #endif
 
 #define bfd_elfNN_canonicalize_dynamic_symtab _bfd_elf_canonicalize_dynamic_symtab
+#ifndef bfd_elfNN_canonicalize_reloc
 #define bfd_elfNN_canonicalize_reloc	_bfd_elf_canonicalize_reloc
+#endif
 #ifndef bfd_elfNN_find_nearest_line
 #define bfd_elfNN_find_nearest_line	_bfd_elf_find_nearest_line
 #endif

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva at {redhat dot com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva at {lsd dot ic dot unicamp dot br, gnu.org}
Free Software Evangelist                Professional serial bug killer

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