Add support for ELF files which contain multiple reloc sections which all target...
authorNick Clifton <nickc@redhat.com>
Thu, 5 Mar 2020 15:47:15 +0000 (15:47 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 5 Mar 2020 15:47:15 +0000 (15:47 +0000)
* elf-bfd.h (struct elf_backend_data): Add new fields:
init_secondary_reloc_section, slurp_secondary_reloc_section,
write_secondary_reloc_section.
(_bfd_elf_init_secondary_reloc_section): Prototype.
(_bfd_elf_slurp_secondary_reloc_section): Prototype.
(_bfd_elf_write_secondary_reloc_section): Prototype.
* elf.c ( bfd_section_from_shdr): Invoke the new
init_secondary_reloc_section backend function, if defined, when a
second reloc section is encountered.
(swap_out_syms): Invoke the new symbol_section_index function, if
defined, when computing the section index of an OS/PROC specific
symbol.
(_bfd_elf_init_secondary_reloc_section): New function.
(_bfd_elf_slurp_secondary_reloc_section): New function.
(_bfd_elf_write_secondary_reloc_section): New function.
(_bfd_elf_copy_special_section_fields): New function.
* elfcode.h (elf_write_relocs): Invoke the new
write_secondary_relocs function, if defined, in order to emit
secondary relocs.
(elf_slurp_reloc_table): Invoke the new slurp_secondary_relocs
function, if defined, in order to read in secondary relocs.
* elfxx-target.h (elf_backend_copy_special_section_fields):
Provide a non-NULL default definition.
(elf_backend_init_secondary_reloc_section): Likewise.
(elf_backend_slurp_secondary_reloc_section): Likewise.
(elf_backend_write_secondary_reloc_section): Likewise.
(struct elf_backend_data elfNN_bed): Add initialisers for the new
fields.
        * configure.ac (score_elf32_[bl]e_vec): Add elf64.lo
        * configure: Regenerate.

bfd/ChangeLog
bfd/configure
bfd/configure.ac
bfd/elf-bfd.h
bfd/elf.c
bfd/elfcode.h
bfd/elfxx-target.h

index 9f1a9424ae490d6998294421b5402352e0ee4fa9..1cfff1c04d77e3f359b71f87d50b98367c6655b9 100644 (file)
@@ -1,3 +1,36 @@
+2020-03-05  Nick Clifton  <nickc@redhat.com>
+
+       * elf-bfd.h (struct elf_backend_data): Add new fields:
+       init_secondary_reloc_section, slurp_secondary_reloc_section,
+       write_secondary_reloc_section.
+       (_bfd_elf_init_secondary_reloc_section): Prototype.
+       (_bfd_elf_slurp_secondary_reloc_section): Prototype.
+       (_bfd_elf_write_secondary_reloc_section): Prototype.
+       * elf.c ( bfd_section_from_shdr): Invoke the new
+       init_secondary_reloc_section backend function, if defined, when a
+       second reloc section is encountered.
+       (swap_out_syms): Invoke the new symbol_section_index function, if
+       defined, when computing the section index of an OS/PROC specific
+       symbol.
+       (_bfd_elf_init_secondary_reloc_section): New function.
+       (_bfd_elf_slurp_secondary_reloc_section): New function.
+       (_bfd_elf_write_secondary_reloc_section): New function.
+       (_bfd_elf_copy_special_section_fields): New function.
+       * elfcode.h (elf_write_relocs): Invoke the new
+       write_secondary_relocs function, if defined, in order to emit
+       secondary relocs.
+       (elf_slurp_reloc_table): Invoke the new slurp_secondary_relocs
+       function, if defined, in order to read in secondary relocs.
+       * elfxx-target.h (elf_backend_copy_special_section_fields):
+       Provide a non-NULL default definition.
+       (elf_backend_init_secondary_reloc_section): Likewise.
+       (elf_backend_slurp_secondary_reloc_section): Likewise.
+       (elf_backend_write_secondary_reloc_section): Likewise.
+       (struct elf_backend_data elfNN_bed): Add initialisers for the new
+       fields.
+        * configure.ac (score_elf32_[bl]e_vec): Add elf64.lo
+        * configure: Regenerate.
+
 2020-03-05  Alan Modra  <amodra@gmail.com>
 
        * archive64.c (_bfd_archive_64_bit_slurp_armap): Check parsed_size
index cca67ee1080eea3076bb42664880062c8886046f..30b80fe27c16173f18368e8bd31146ef4e84cb5b 100755 (executable)
@@ -14887,8 +14887,8 @@ do
     rx_elf32_linux_le_vec)      tb="$tb elf32-rx.lo elf32.lo $elf" ;;
     s390_elf32_vec)             tb="$tb elf32-s390.lo elf32.lo $elf" ;;
     s390_elf64_vec)             tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
-    score_elf32_be_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
-    score_elf32_le_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
+    score_elf32_be_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
+    score_elf32_le_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
     sh_coff_vec)                tb="$tb coff-sh.lo $coff" ;;
     sh_coff_le_vec)             tb="$tb coff-sh.lo $coff" ;;
     sh_coff_small_vec)          tb="$tb coff-sh.lo $coff" ;;
index af4d4b8c1354d7e92a5aa235cd5257f5fb854f41..3426ded094aea651e12733acbb039d95982a658d 100644 (file)
@@ -619,8 +619,8 @@ do
     rx_elf32_linux_le_vec)      tb="$tb elf32-rx.lo elf32.lo $elf" ;;
     s390_elf32_vec)             tb="$tb elf32-s390.lo elf32.lo $elf" ;;
     s390_elf64_vec)             tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
-    score_elf32_be_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
-    score_elf32_le_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
+    score_elf32_be_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
+    score_elf32_le_vec)                 tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
     sh_coff_vec)                tb="$tb coff-sh.lo $coff" ;;
     sh_coff_le_vec)             tb="$tb coff-sh.lo $coff" ;;
     sh_coff_small_vec)          tb="$tb coff-sh.lo $coff" ;;
index 38a9aa060192818dc9f09da0c95051840361ae9f..5d9e0fedcda076a270b89bbfe40ad5c80f960448 100644 (file)
@@ -1509,6 +1509,16 @@ struct elf_backend_data
      emitted symbol.  If not defined, the value is left unchanged.  */
   unsigned int (*symbol_section_index) (bfd *, elf_symbol_type *);
   
+  /* Called when a section has extra reloc sections.  */
+  bfd_boolean (*init_secondary_reloc_section) (bfd *, Elf_Internal_Shdr *,
+                                              const char *, unsigned int);
+
+  /* Called when after loading the normal relocs for a section.  */
+  bfd_boolean (*slurp_secondary_relocs) (bfd *, asection *, asymbol **);
+
+  /* Called after writing the normal relocs for a section.  */
+  bfd_boolean (*write_secondary_relocs) (bfd *, asection *);
+
   /* This is non-zero if static TLS segments require a special alignment.  */
   unsigned static_tls_alignment;
 
@@ -2838,6 +2848,19 @@ extern bfd_vma elf32_r_sym (bfd_vma);
 
 extern bfd_boolean is_debuginfo_file (bfd *);
 
+
+extern bfd_boolean _bfd_elf_init_secondary_reloc_section
+  (bfd *, Elf_Internal_Shdr *, const char *, unsigned int);
+extern bfd_boolean _bfd_elf_slurp_secondary_reloc_section
+  (bfd *, asection *, asymbol **);
+extern bfd_boolean _bfd_elf_copy_special_section_fields
+  (const bfd *, bfd *, const Elf_Internal_Shdr *, Elf_Internal_Shdr *);
+extern bfd_boolean _bfd_elf_write_secondary_reloc_section
+  (bfd *, asection *);
+extern unsigned int _bfd_elf_symbol_section_index
+  (bfd *, elf_symbol_type *);
+
+
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
 
index c4d6718aaa0ea540d4b4724008f4faa6ae4d6250..747d120101fce8d0190ca725f025eea00552b500 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1607,7 +1607,7 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
          /* Final attempt.  Call the backend copy function
             with a NULL input section.  */
          if (bed->elf_backend_copy_special_section_fields != NULL)
-           bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
+           (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
        }
     }
 
@@ -2458,13 +2458,17 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           sections.  */
        if (*p_hdr != NULL)
          {
-           _bfd_error_handler
-             /* xgettext:c-format */
-             (_("%pB: warning: multiple relocation sections for section %pA \
-found - ignoring all but the first"),
-              abfd, target_sect);
+           if (bed->init_secondary_reloc_section == NULL
+               || ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
+             {
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("%pB: warning: secondary relocation section '%s' for section %pA found - ignoring"),
+                  abfd, name, target_sect);
+             }
            goto success;
          }
+
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
        if (hdr2 == NULL)
          goto fail;
@@ -12308,3 +12312,364 @@ _bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec,
     size = 1;
   return size;
 }
+
+/* Set to non-zero to enable some debug messages.  */
+#define DEBUG_SECONDARY_RELOCS  0
+
+/* An internal-to-the-bfd-library only section type
+   used to indicate a cached secondary reloc section.  */
+#define SHT_SECONDARY_RELOC     (SHT_LOOS + SHT_RELA)
+
+/* Create a BFD section to hold a secondary reloc section.  */
+
+bfd_boolean
+_bfd_elf_init_secondary_reloc_section (bfd * abfd,
+                                      Elf_Internal_Shdr *hdr,
+                                      const char * name,
+                                      unsigned int shindex)
+{
+  /* We only support RELA secondary relocs.  */
+  if (hdr->sh_type != SHT_RELA)
+    return FALSE;
+
+#if DEBUG_SECONDARY_RELOCS
+  fprintf (stderr, "secondary reloc section %s encountered\n", name);
+#endif
+  hdr->sh_type = SHT_SECONDARY_RELOC;
+  return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+}
+
+/* Read in any secondary relocs associated with SEC.  */
+
+bfd_boolean
+_bfd_elf_slurp_secondary_reloc_section (bfd *      abfd,
+                                       asection * sec,
+                                       asymbol ** symbols)
+{
+  const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
+  asection * relsec;
+  bfd_boolean result = TRUE;
+  bfd_vma (*r_sym) (bfd_vma);
+
+#if BFD_DEFAULT_TARGET_SIZE > 32
+  if (bfd_arch_bits_per_address (abfd) != 32)
+    r_sym = elf64_r_sym;
+  else
+#endif
+    r_sym = elf32_r_sym;
+  
+  /* Discover if there are any secondary reloc sections
+     associated with SEC.  */
+  for (relsec = abfd->sections; relsec != NULL; relsec = relsec->next)
+    {
+      Elf_Internal_Shdr * hdr = & elf_section_data (relsec)->this_hdr;
+
+      if (hdr->sh_type == SHT_SECONDARY_RELOC
+         && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx)
+       {
+         bfd_byte * native_relocs;
+         bfd_byte * native_reloc;
+         arelent * internal_relocs;
+         arelent * internal_reloc;
+         unsigned int i;
+         unsigned int entsize;
+         unsigned int symcount;
+         unsigned int reloc_count;
+         size_t amt;
+
+         if (ebd->elf_info_to_howto == NULL)
+           return FALSE;
+
+#if DEBUG_SECONDARY_RELOCS
+         fprintf (stderr, "read secondary relocs for %s from %s\n",
+                  sec->name, relsec->name);
+#endif
+         entsize = hdr->sh_entsize;
+
+         native_relocs = bfd_malloc (hdr->sh_size);
+         if (native_relocs == NULL)
+           {
+             result = FALSE;
+             continue;
+           }
+
+         reloc_count = NUM_SHDR_ENTRIES (hdr);
+         if (_bfd_mul_overflow (reloc_count, sizeof (arelent), & amt))
+           {
+             bfd_set_error (bfd_error_file_too_big);
+             result = FALSE;
+             continue;
+           }
+
+         internal_relocs = (arelent *) bfd_alloc (abfd, amt);
+         if (internal_relocs == NULL)
+           {
+             free (native_relocs);
+             result = FALSE;
+             continue;
+           }
+
+         if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+             || (bfd_bread (native_relocs, hdr->sh_size, abfd)
+                 != hdr->sh_size))
+           {
+             free (native_relocs);
+             free (internal_relocs);
+             result = FALSE;
+             continue;
+           }
+
+         symcount = bfd_get_symcount (abfd);
+
+         for (i = 0, internal_reloc = internal_relocs,
+                native_reloc = native_relocs;
+              i < reloc_count;
+              i++, internal_reloc++, native_reloc += entsize)
+           {
+             bfd_boolean res;
+             Elf_Internal_Rela rela;
+
+             ebd->s->swap_reloca_in (abfd, native_reloc, & rela);
+
+             /* The address of an ELF reloc is section relative for an object
+                file, and absolute for an executable file or shared library.
+                The address of a normal BFD reloc is always section relative,
+                and the address of a dynamic reloc is absolute..  */
+             if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+               internal_reloc->address = rela.r_offset;
+             else
+               internal_reloc->address = rela.r_offset - sec->vma;
+
+             if (r_sym (rela.r_info) == STN_UNDEF)
+               {
+                 /* FIXME: This and the error case below mean that we
+                    have a symbol on relocs that is not elf_symbol_type.  */
+                 internal_reloc->sym_ptr_ptr =
+                   bfd_abs_section_ptr->symbol_ptr_ptr;
+               }
+             else if (r_sym (rela.r_info) > symcount)
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB(%pA): relocation %d has invalid symbol index %ld"),
+                    abfd, sec, i, (long) r_sym (rela.r_info));
+                 bfd_set_error (bfd_error_bad_value);
+                 internal_reloc->sym_ptr_ptr =
+                   bfd_abs_section_ptr->symbol_ptr_ptr;
+                 result = FALSE;
+               }
+             else
+               {
+                 asymbol **ps;
+
+                 ps = symbols + r_sym (rela.r_info) - 1;
+
+                 internal_reloc->sym_ptr_ptr = ps;
+                 /* Make sure that this symbol is not removed by strip.  */
+                 (*ps)->flags |= BSF_KEEP;
+               }
+
+             internal_reloc->addend = rela.r_addend;
+
+             res = ebd->elf_info_to_howto (abfd, internal_reloc, & rela);
+             if (! res || internal_reloc->howto == NULL)
+               {
+#if DEBUG_SECONDARY_RELOCS
+                 fprintf (stderr, "there is no howto associated with reloc %lx\n",
+                          rela.r_info);
+#endif
+                 result = FALSE;
+               }
+           }
+
+         free (native_relocs);
+         /* Store the internal relocs.  */
+         elf_section_data (relsec)->sec_info = internal_relocs;
+       }
+    }
+
+  return result;
+}
+
+/* Set the ELF section header fields of an output secondary reloc section.  */
+
+bfd_boolean
+_bfd_elf_copy_special_section_fields (const bfd *   ibfd ATTRIBUTE_UNUSED,
+                                     bfd *         obfd ATTRIBUTE_UNUSED,
+                                     const Elf_Internal_Shdr * isection,
+                                     Elf_Internal_Shdr *       osection)
+{
+  asection * isec;
+  asection * osec;
+
+  if (isection == NULL)
+    return FALSE;
+
+  if (isection->sh_type != SHT_SECONDARY_RELOC)
+    return TRUE;
+
+  isec = isection->bfd_section;
+  if (isec == NULL)
+    return FALSE;
+
+  osec = osection->bfd_section;
+  if (osec == NULL)
+    return FALSE;
+
+  BFD_ASSERT (elf_section_data (osec)->sec_info == NULL);
+  elf_section_data (osec)->sec_info = elf_section_data (isec)->sec_info;
+  osection->sh_type = SHT_RELA;
+  osection->sh_link = elf_onesymtab (obfd);
+  if (osection->sh_link == 0)
+    {
+      /* There is no symbol table - we are hosed...  */
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("%pB(%pA): link section cannot be set because the output file does not have a symbol table"),
+       obfd, osec);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Find the output section that corresponds to the isection's sh_info link.  */
+  BFD_ASSERT (isection->sh_info > 0
+             && isection->sh_info < elf_numsections (ibfd));
+  isection = elf_elfsections (ibfd)[isection->sh_info];
+
+  BFD_ASSERT (isection != NULL);
+  BFD_ASSERT (isection->bfd_section != NULL);
+  BFD_ASSERT (isection->bfd_section->output_section != NULL);
+  osection->sh_info =
+    elf_section_data (isection->bfd_section->output_section)->this_idx;
+
+#if DEBUG_SECONDARY_RELOCS
+  fprintf (stderr, "update header of %s, sh_link = %u, sh_info = %u\n",
+          osec->name, osection->sh_link, osection->sh_info);
+#endif
+
+  return TRUE;
+}
+
+/* Write out a secondary reloc section.  */
+
+bfd_boolean
+_bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
+{
+  const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
+  bfd_vma addr_offset;
+  asection * relsec;
+  bfd_vma (*r_info) (bfd_vma, bfd_vma);
+
+#if BFD_DEFAULT_TARGET_SIZE > 32
+  if (bfd_arch_bits_per_address (abfd) != 32)
+    r_info = elf64_r_info;
+  else
+#endif
+    r_info = elf32_r_info;
+
+  if (sec == NULL)
+    return FALSE;
+
+  /* The address of an ELF reloc is section relative for an object
+     file, and absolute for an executable file or shared library.
+     The address of a BFD reloc is always section relative.  */
+  addr_offset = 0;
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+    addr_offset = sec->vma;
+
+  /* Discover if there are any secondary reloc sections
+     associated with SEC.  */
+  for (relsec = abfd->sections; relsec != NULL; relsec = relsec->next)
+    {
+      const struct bfd_elf_section_data * const esd = elf_section_data (relsec);
+      Elf_Internal_Shdr * const hdr = (Elf_Internal_Shdr *) & esd->this_hdr;
+
+      if (hdr->sh_type == SHT_RELA
+         && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx)
+       {
+         asymbol *    last_sym;
+         int          last_sym_idx;
+         unsigned int reloc_count;
+         unsigned int idx;
+         arelent *    src_irel;
+         bfd_byte *   dst_rela;
+
+         BFD_ASSERT (hdr->contents == NULL);
+
+         reloc_count = hdr->sh_size / hdr->sh_entsize;
+         BFD_ASSERT (reloc_count > 0);
+
+         hdr->contents = bfd_alloc (abfd, hdr->sh_size);
+         if (hdr->contents == NULL)
+           continue;
+
+#if DEBUG_SECONDARY_RELOCS
+         fprintf (stderr, "write %u secondary relocs for %s from %s\n",
+                  reloc_count, sec->name, relsec->name);
+#endif
+         last_sym = NULL;
+         last_sym_idx = 0;
+         dst_rela = hdr->contents;
+         src_irel = (arelent *) esd->sec_info;
+         BFD_ASSERT (src_irel != NULL);
+
+         for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize)
+           {
+             Elf_Internal_Rela src_rela;
+             arelent *ptr;
+             asymbol *sym;
+             int n;
+
+             ptr = src_irel + idx;
+             sym = *ptr->sym_ptr_ptr;
+
+             if (sym == last_sym)
+               n = last_sym_idx;
+             else
+               {
+                 last_sym = sym;
+                 n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym);
+                 if (n < 0)
+                   {
+#if DEBUG_SECONDARY_RELOCS
+                     fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n",
+                              sym->name);
+#endif
+                     /* FIXME: Signal failure somehow.  */
+                     n = 0;
+                   }
+                 last_sym_idx = n;
+               }
+
+             if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
+                 && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+                 && ! _bfd_elf_validate_reloc (abfd, ptr))
+               {
+#if DEBUG_SECONDARY_RELOCS
+                 fprintf (stderr, "symbol %s is not in the output bfd\n",
+                          sym->name);
+#endif
+                 /* FIXME: Signal failure somehow.  */
+                 n = 0;
+               }
+
+             if (ptr->howto == NULL)
+               {
+#if DEBUG_SECONDARY_RELOCS
+                 fprintf (stderr, "reloc for symbol %s does not have a howto associated with it\n",
+                          sym->name);
+#endif
+                 /* FIXME: Signal failure somehow.  */
+                 n = 0;
+               }
+
+             src_rela.r_offset = ptr->address + addr_offset;
+             src_rela.r_info = r_info (n, ptr->howto->type);
+             src_rela.r_addend = ptr->addend;
+             ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela);
+           }
+       }
+    }
+
+  return TRUE;
+}
index 600abfe836e4bafed2a4d66777835da7257277ba..18a6dac64e04a83d62cbe7feec518be693f7ad13 100644 (file)
@@ -869,6 +869,7 @@ elf_object_p (bfd *abfd)
 void
 elf_write_relocs (bfd *abfd, asection *sec, void *data)
 {
+  const struct elf_backend_data * const bed = get_elf_backend_data (abfd);
   bfd_boolean *failedp = (bfd_boolean *) data;
   Elf_Internal_Shdr *rela_hdr;
   bfd_vma addr_offset;
@@ -985,6 +986,13 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
       src_rela.r_addend = ptr->addend;
       (*swap_out) (abfd, &src_rela, dst_rela);
     }
+
+  if (bed->write_secondary_relocs != NULL)
+    if (! bed->write_secondary_relocs (abfd, sec))
+      {
+       *failedp = TRUE;
+       return;
+      }
 }
 
 /* Write out the program headers.  */
@@ -1292,7 +1300,10 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
                {
                  /* This symbol is in a section for which we did not
                     create a BFD section.  Just use bfd_abs_section,
-                    although it is wrong.  FIXME.  */
+                    although it is wrong.  FIXME.  Note - there is
+                    code in elf.c:swap_out_syms that calls
+                    symbol_section_index() in the elf backend for
+                    cases like this.  */
                  sym->symbol.section = bfd_abs_section_ptr;
                }
            }
@@ -1517,6 +1528,7 @@ elf_slurp_reloc_table (bfd *abfd,
                       asymbol **symbols,
                       bfd_boolean dynamic)
 {
+  const struct elf_backend_data * const bed = get_elf_backend_data (abfd);
   struct bfd_elf_section_data * const d = elf_section_data (asect);
   Elf_Internal_Shdr *rel_hdr;
   Elf_Internal_Shdr *rel_hdr2;
@@ -1584,6 +1596,10 @@ elf_slurp_reloc_table (bfd *abfd,
                                              symbols, dynamic))
     return FALSE;
 
+  if (bed->slurp_secondary_relocs != NULL
+      && ! bed->slurp_secondary_relocs (abfd, asect, symbols))
+    return FALSE;
+
   asect->relocation = relents;
   return TRUE;
 }
index e9cac0a5352dd3fc8a355ac0cbf59c890aefceda..1ae17f45ee2ff3e2a27b800f64a874cc6ccd7565 100644 (file)
 #endif
 
 #ifndef elf_backend_copy_special_section_fields
-#define elf_backend_copy_special_section_fields NULL
+#define elf_backend_copy_special_section_fields _bfd_elf_copy_special_section_fields
 #endif
 
 #ifndef elf_backend_compact_eh_encoding
 #endif
 
 #ifndef elf_backend_cant_unwind_opcode
-#define elf_backend_cant_unwind_opcode 0
+#define elf_backend_cant_unwind_opcode NULL
+#endif
+
+#ifndef elf_backend_init_secondary_reloc_section
+#define elf_backend_init_secondary_reloc_section _bfd_elf_init_secondary_reloc_section
+#endif
+
+#ifndef elf_backend_slurp_secondary_reloc_section
+#define elf_backend_slurp_secondary_reloc_section _bfd_elf_slurp_secondary_reloc_section
+#endif
+
+#ifndef elf_backend_write_secondary_reloc_section
+#define elf_backend_write_secondary_reloc_section _bfd_elf_write_secondary_reloc_section
 #endif
 
 #ifndef elf_backend_symbol_section_index
@@ -900,6 +912,9 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_compact_eh_encoding,
   elf_backend_cant_unwind_opcode,
   elf_backend_symbol_section_index,
+  elf_backend_init_secondary_reloc_section,
+  elf_backend_slurp_secondary_reloc_section,
+  elf_backend_write_secondary_reloc_section,
   elf_backend_static_tls_alignment,
   elf_backend_stack_align,
   elf_backend_strtab_flags,