* elfxx-target.h (bfd_elfNN_canonicalize_reloc): Make it
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 12 Mar 2003 22:52:12 +0000 (22:52 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Wed, 12 Mar 2003 22:52:12 +0000 (22:52 +0000)
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.

bfd/ChangeLog
bfd/elf64-mips.c
bfd/elfxx-target.h

index d2209f4c5cbb5bec02b247ea3c0768536acd600a..b64fd709631b43adfed27aebb5bb5cc991f2c68a 100644 (file)
@@ -1,3 +1,16 @@
+2003-03-12  Alexandre Oliva  <aoliva@redhat.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.
+
 2003-03-12  Nick Clifton  <nickc@redhat.com>
 
        * xsym.c (bfd_sym_fetch_type_information_table_entry): Change
index 807ddf5f22fd7997bb62f179fa4a7764c5d18ac1..404504ae3d609c15a7f11f768462a5d2dcc5d705 100644 (file)
@@ -91,8 +91,14 @@ static void mips_elf64_info_to_howto_rela
   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, sec)
   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, asect, symbols, rel_hdr)
     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, asect, symbols, rel_hdr)
             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, asect, symbols, rel_hdr)
 }
 
 /* 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, asect, symbols, dynamic)
      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 (asect->relocation != NULL)
+    return TRUE;
 
-  if (dynamic)
+  if (dynamic)
     {
-      bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
-    }
+      if ((asect->flags & SEC_RELOC) == 0
+         || asect->reloc_count == 0)
+       return TRUE;
 
-  if (asect->relocation != NULL
-      || (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));
+
+    }
+  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_size_info =
                                _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 69e3782b1bc0257ca5dc79ea0580bba85cf331a6..734d78bb75e8a29b056d20326fd618837219d9ea 100644 (file)
@@ -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