This is the mail archive of the binutils@sourceware.org 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]

RFC: Supporting multiple relocs per section


Hi Guys,

  Traditionally the BFD library has supported a one-to-one relationship
  between relocation sections and the sections that they relocate.  The
  ELF portions of the library do support a two-to-one relationship if
  one of the reloc sections uses REL relocs and the other uses RELA
  relocs, but that is a bit of a hack.  The ELF standard however does
  not prohibit a many-to-one relationship and I now have a need to
  support such a feature[1].

  Initially I looked at reworking the internals of the BFD library to
  accommodate a list of reloc sections attached to a normal section but
  this quickly spiralled out of control and broke far too many things.
  So I have now come up with an implementation that adds a few new
  functions to the elf_backend_data structure, and some hooks to call
  these functions.  This encapsulates the new code and helps separate it
  from the rest of the library.  It does however mean that, currently,
  these extra reloc sections are not processed when linking.  For the
  use case I have in mind however (objcopy/strip) this does not matter.

  As part of this process I also discovered that the BFD library would
  unconditionally convert OS-specific and PROC-specific section indices
  into SHN_ABS indices when writing out symbol tables, so I also added a
  hook to allow backends to override this behaviour if they so desire.

  I am hoping to add the code to the upstream sources, but I would like
  seek out any comments or suggestions that people might have before I
  do so.  So ... any thoughts ?

Cheers
  Nick

PS. During testing I also encountered a build failure with the score
  architecture because that defines target_size=64 during configuration
  but it does not include the 64-bit generic elf functions found in
  elf64.o.  So the patch fixes that as well.

[1] This is to support kernel live patch modules used by Fedora and RHEL
  and possibly other distributions too.

bfd/ChangeLog
2020-02-14  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, symbol_section_index.
	(_bfd_elf_init_secondary_reloc_section): Prototype.
	(_bfd_elf_slurp_secondary_reloc_section): Prototype.
	(_bfd_elf_write_secondary_reloc_section): Prototype.
	(_bfd_elf_symbol_section_index): 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_symbol_section_index): 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.
	(elf_backend_symbol_section_index): 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.

diff --git a/bfd/configure.ac b/bfd/configure.ac
index af4d4b8c13..3426ded094 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -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" ;;
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index cbbba153f4..a930d8278d 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1503,6 +1503,19 @@ struct elf_backend_data
   /* Opcode representing no unwind.  */
   int (*cant_unwind_opcode) (struct bfd_link_info *);
 
+  /* 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 *);
+
+  /* Called to return the value to set in the ST_SHNDX field of an ELF symbol
+     from an iternal symbol which does not map to any known section.  */
+  unsigned int (*symbol_section_index) (bfd *, elf_symbol_type *);
+  
   /* This is non-zero if static TLS segments require a special alignment.  */
   unsigned static_tls_alignment;
 
@@ -2830,6 +2843,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;
 
diff --git a/bfd/elf.c b/bfd/elf.c
index c85face630..2c1b6fe67d 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1619,7 +1619,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);
 	}
     }
 
@@ -2468,13 +2468,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;
@@ -8199,9 +8203,20 @@ error_return:
 		  if (elf_symtab_shndx_list (abfd))
 		    shndx = elf_symtab_shndx_list (abfd)->ndx;
 		  break;
-		default:
+		case SHN_COMMON:
+		case SHN_ABS:
 		  shndx = SHN_ABS;
 		  break;
+		default:
+		  if (bed->symbol_section_index)
+		    shndx = bed->symbol_section_index (abfd, type_ptr);
+		  else
+		    {
+		      _bfd_error_handler (_("%pB: Unable to handle section index %x in ELF symbol.  Using ABS instead. (%x)"),
+					  abfd, shndx, SHN_COMMON);
+		      shndx = SHN_ABS;
+		    }
+		  break;
 		}
 	    }
 	  else
@@ -12289,3 +12304,355 @@ _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);
+
+  BFD_ASSERT (ebd->elf_info_to_howto != NULL);
+
+#ifdef BFD64
+  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;
+
+#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);
+	  internal_relocs = (arelent *) bfd_alloc2 (abfd, reloc_count, sizeof (arelent));
+	  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)
+{
+  if (isection->sh_type != SHT_SECONDARY_RELOC)
+    return TRUE;
+
+  if (isection == NULL)
+    return FALSE;
+
+  asection * isec = isection->bfd_section;
+  if (isec == NULL)
+    return FALSE;
+
+  asection * 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);
+
+#ifdef BFD64
+  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;
+}
+
+/* Preserve any OS or PROCESSOR specific section indicies.  */
+
+unsigned int
+_bfd_elf_symbol_section_index (bfd * abfd ATTRIBUTE_UNUSED,
+			       elf_symbol_type * sym)
+{
+  unsigned int shndx = sym->internal_elf_sym.st_shndx;
+
+  /* Preserve special section indicies.  */
+  return shndx >= SHN_LORESERVE ? shndx : SHN_ABS;
+}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index e1e89cf78f..27f6b81b1e 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -865,6 +865,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;
@@ -980,6 +981,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.  */
@@ -1281,7 +1289,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;
 		}
 	    }
@@ -1509,6 +1520,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;
@@ -1571,6 +1583,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;
 }
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index caca83f5c9..8fe21eb671 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -758,7 +758,7 @@
 #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
@@ -766,7 +766,23 @@
 #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
+#define elf_backend_symbol_section_index _bfd_elf_symbol_section_index
 #endif
 
 #ifndef elf_match_priority
@@ -895,6 +911,10 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_fixup_gnu_properties,
   elf_backend_compact_eh_encoding,
   elf_backend_cant_unwind_opcode,
+  elf_backend_init_secondary_reloc_section,
+  elf_backend_slurp_secondary_reloc_section,
+  elf_backend_write_secondary_reloc_section,
+  elf_backend_symbol_section_index,
   elf_backend_static_tls_alignment,
   elf_backend_stack_align,
   elf_backend_strtab_flags,


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