This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RFC: Supporting multiple relocs per section
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Fri, 14 Feb 2020 10:30:47 +0000
- Subject: 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,