/* ELF linking support for BFD.
- Copyright (C) 1995-2022 Free Software Foundation, Inc.
+ Copyright (C) 1995-2023 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
const struct elf_backend_data *bed;
char *new_version;
bool default_sym = *matched;
+ struct elf_link_hash_table *htab;
*skip = false;
*override = NULL;
symbols. */
bfd_elf_link_mark_dynamic_symbol (info, h, sym);
+ htab = elf_hash_table (info);
+
/* NEWDYN and OLDDYN indicate whether the new or old symbol,
respectively, is from a dynamic object. */
olddyn = (oldsec->symbol->flags & BSF_DYNAMIC) != 0;
}
- if (oldbfd != NULL
+ /* Set non_ir_ref_dynamic only when not handling DT_NEEDED entries. */
+ if (!htab->handling_dt_needed
+ && oldbfd != NULL
&& (oldbfd->flags & BFD_PLUGIN) != (abfd->flags & BFD_PLUGIN))
{
if (newdyn != olddyn)
h->root.non_ir_ref_dynamic = true;
hi->root.non_ir_ref_dynamic = true;
}
-
- if ((oldbfd->flags & BFD_PLUGIN) != 0
- && hi->root.type == bfd_link_hash_indirect)
+ else if ((oldbfd->flags & BFD_PLUGIN) != 0
+ && hi->root.type == bfd_link_hash_indirect)
{
/* Change indirect symbol from IR to undefined. */
hi->root.type = bfd_link_hash_undefined;
return true;
}
\f
+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
+ dependencies successfully. GLIBC_ABI_DT_RELR will be put into the
+ .gnu.version_r section. */
+
+static bool
+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
+{
+ bfd *glibc_bfd = NULL;
+ Elf_Internal_Verneed *t;
+ Elf_Internal_Vernaux *a;
+ size_t amt;
+ const char *relr = "GLIBC_ABI_DT_RELR";
+
+ /* See if we already know about GLIBC_PRIVATE_DT_RELR. */
+ for (t = elf_tdata (rinfo->info->output_bfd)->verref;
+ t != NULL;
+ t = t->vn_nextref)
+ {
+ const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
+ /* Skip the shared library if it isn't libc.so. */
+ if (!soname || !startswith (soname, "libc.so."))
+ continue;
+
+ for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ {
+ /* Return if GLIBC_PRIVATE_DT_RELR dependency has been
+ added. */
+ if (a->vna_nodename == relr
+ || strcmp (a->vna_nodename, relr) == 0)
+ return true;
+
+ /* Check if libc.so provides GLIBC_2.XX version. */
+ if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
+ glibc_bfd = t->vn_bfd;
+ }
+
+ break;
+ }
+
+ /* Skip if it isn't linked against glibc. */
+ if (glibc_bfd == NULL)
+ return true;
+
+ /* This is a new version. Add it to tree we are building. */
+ if (t == NULL)
+ {
+ amt = sizeof *t;
+ t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd,
+ amt);
+ if (t == NULL)
+ {
+ rinfo->failed = true;
+ return false;
+ }
+
+ t->vn_bfd = glibc_bfd;
+ t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
+ elf_tdata (rinfo->info->output_bfd)->verref = t;
+ }
+
+ amt = sizeof *a;
+ a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
+ if (a == NULL)
+ {
+ rinfo->failed = true;
+ return false;
+ }
+
+ a->vna_nodename = relr;
+ a->vna_flags = 0;
+ a->vna_nextptr = t->vn_auxptr;
+ a->vna_other = rinfo->vers + 1;
+ ++rinfo->vers;
+
+ t->vn_auxptr = a;
+
+ return true;
+}
+
/* Look through the symbols which are defined in other shared
libraries and referenced here. Update the list of version
dependencies. This will be put into the .gnu.version_r section.
return false;
/* Read the relocations. */
- if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
+ if (bfd_read (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
return false;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
abfd = abfd->plugin_dummy_bfd;
hdr = &elf_tdata (abfd)->symtab_hdr;
}
- else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
- hdr = &elf_tdata (abfd)->symtab_hdr;
else
- hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ {
+ if (elf_use_dt_symtab_p (abfd))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ else
+ hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ }
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
htab = elf_hash_table (info);
bed = get_elf_backend_data (abfd);
+ if (elf_use_dt_symtab_p (abfd))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
if ((abfd->flags & DYNAMIC) == 0)
dynamic = false;
else
| DYN_NO_NEEDED)) == 0;
s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL && s->size != 0)
+ if (s != NULL && s->size != 0 && (s->flags & SEC_HAS_CONTENTS) != 0)
{
bfd_byte *dynbuf;
bfd_byte *extdyn;
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
for (extdyn = dynbuf;
- extdyn <= dynbuf + s->size - bed->s->sizeof_dyn;
+ (size_t) (dynbuf + s->size - extdyn) >= bed->s->sizeof_dyn;
extdyn += bed->s->sizeof_dyn)
{
Elf_Internal_Dyn dyn;
else
_bfd_error_handler
/* xgettext:c-format */
- (_("warning: alignment %u of symbol `%s' in %pB"
- " is smaller than %u in %pB"),
+ (_("warning: alignment %u of normal symbol `%s' in %pB"
+ " is smaller than %u used by the common definition in %pB"),
1 << normal_align, name, normal_bfd,
1 << common_align, common_bfd);
+
+ /* PR 30499: make sure that users understand that this warning is serious. */
+ _bfd_error_handler
+ (_("warning: NOTE: alignment discrepancies can cause real problems. Investigation is advised."));
}
}
if (h->size != 0
&& h->size != isym->st_size
&& ! size_change_ok)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: size of symbol `%s' changed"
- " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
- name, (uint64_t) h->size, old_bfd,
- (uint64_t) isym->st_size, abfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("warning: size of symbol `%s' changed"
+ " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
+ name, (uint64_t) h->size, old_bfd,
+ (uint64_t) isym->st_size, abfd);
+
+ /* PR 30499: make sure that users understand that this warning is serious. */
+ _bfd_error_handler
+ (_("warning: NOTE: size discrepancies can cause real problems. Investigation is advised."));
+ }
h->size = isym->st_size;
}
h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
}
- if (definition && !dynamic)
+ /* Don't add indirect symbols for .symver x, x@FOO aliases
+ in IR. Since all data or text symbols in IR have the
+ same type, value and section, we can't tell if a symbol
+ is an alias of another symbol by their types, values and
+ sections. */
+ if (definition
+ && !dynamic
+ && (abfd->flags & BFD_PLUGIN) == 0)
{
char *p = strchr (name, ELF_VER_CHR);
if (p != NULL && p[1] != ELF_VER_CHR)
size_t best_size = 0;
unsigned long int i;
- /* We have a problem here. The following code to optimize the table
- size requires an integer type with more the 32 bits. If
- BFD_HOST_U_64_BIT is set we know about such a type. */
-#ifdef BFD_HOST_U_64_BIT
if (info->optimize)
{
size_t minsize;
size_t maxsize;
- BFD_HOST_U_64_BIT best_chlen = ~((BFD_HOST_U_64_BIT) 0);
+ uint64_t best_chlen = ~((uint64_t) 0);
bfd *dynobj = elf_hash_table (info)->dynobj;
size_t dynsymcount = elf_hash_table (info)->dynsymcount;
const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
for (i = minsize; i < maxsize; ++i)
{
/* Walk through the array of hashcodes and count the collisions. */
- BFD_HOST_U_64_BIT max;
+ uint64_t max;
unsigned long int j;
unsigned long int fact;
free (counts);
}
else
-#endif /* defined (BFD_HOST_U_64_BIT) */
{
- /* This is the fallback solution if no 64bit type is available or if we
- are not supposed to spend much time on optimizations. We select the
- bucket count using a fixed set of numbers. */
for (i = 0; elf_buckets[i] != 0; i++)
{
best_size = elf_buckets[i];
if (sinfo.failed)
return false;
+ if (info->enable_dt_relr)
+ {
+ elf_link_add_dt_relr_dependency (&sinfo);
+ if (sinfo.failed)
+ return false;
+ }
+
if (elf_tdata (output_bfd)->verref == NULL)
s->flags |= SEC_EXCLUDE;
else
/* Determine any GNU_STACK segment requirements, after the backend
has had a chance to set a default segment size. */
if (info->execstack)
- elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
+ {
+ /* If the user has explicitly requested warnings, then generate one even
+ though the choice is the result of another command line option. */
+ if (info->warn_execstack == 1)
+ _bfd_error_handler
+ (_("\
+warning: enabling an executable stack because of -z execstack command line option"));
+ elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
+ }
else if (info->noexecstack)
elf_stack_flags (output_bfd) = PF_R | PF_W;
else
{
bfd *inputobj;
asection *notesec = NULL;
+ bfd *noteobj = NULL;
+ bfd *emptyobj = NULL;
int exec = 0;
for (inputobj = info->input_bfds;
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
if (s)
{
- if (s->flags & SEC_CODE)
- exec = PF_X;
notesec = s;
+ if (s->flags & SEC_CODE)
+ {
+ noteobj = inputobj;
+ exec = PF_X;
+ /* There is no point in scanning the remaining bfds. */
+ break;
+ }
+ }
+ else if (bed->default_execstack && info->default_execstack)
+ {
+ exec = PF_X;
+ emptyobj = inputobj;
}
- else if (bed->default_execstack)
- exec = PF_X;
}
+
if (notesec || info->stacksize > 0)
- elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
+ {
+ if (exec)
+ {
+ if (info->warn_execstack != 0)
+ {
+ /* PR 29072: Because an executable stack is a serious
+ security risk, make sure that the user knows that it is
+ being enabled despite the fact that it was not requested
+ on the command line. */
+ if (noteobj)
+ _bfd_error_handler (_("\
+warning: %s: requires executable stack (because the .note.GNU-stack section is executable)"),
+ bfd_get_filename (noteobj));
+ else if (emptyobj)
+ {
+ _bfd_error_handler (_("\
+warning: %s: missing .note.GNU-stack section implies executable stack"),
+ bfd_get_filename (emptyobj));
+ _bfd_error_handler (_("\
+NOTE: This behaviour is deprecated and will be removed in a future version of the linker"));
+ }
+ }
+ }
+ elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
+ }
+
if (notesec && exec && bfd_link_relocatable (info)
&& notesec->output_section != bfd_abs_section_ptr)
notesec->output_section->flags |= SEC_CODE;
return true;
s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s == NULL || s->size == 0)
+ if (s == NULL || s->size == 0 || (s->flags & SEC_HAS_CONTENTS) == 0)
return true;
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
- extdyn = dynbuf;
- extdynend = extdyn + s->size;
- for (; extdyn < extdynend; extdyn += extdynsize)
+ for (extdyn = dynbuf, extdynend = dynbuf + s->size;
+ (size_t) (extdynend - extdyn) >= extdynsize;
+ extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
ssymhead->count++;
}
BFD_ASSERT ((size_t) (ssymhead - ssymbuf) == shndx_count
- && (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf)
- == total_size));
+ && (uintptr_t) ssym - (uintptr_t) ssymbuf == total_size);
free (indbuf);
return ssymbuf;
return aval;
}
-#ifdef BFD_HOST_64_BIT
static bfd_vma
ext64l_r_offset (const void *p)
{
| (uint64_t) a->c[7]);
return aval;
}
-#endif
/* When performing a relocatable link, the input relocations are
preserved. But, if they reference global symbols, the indices
}
else
{
-#ifdef BFD_HOST_64_BIT
if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
ext_r_off = ext64l_r_offset;
else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
ext_r_off = ext64b_r_offset;
else
-#endif
abort ();
}
size_t sortlen = p - loc;
bfd_vma r_off2 = (*ext_r_off) (loc);
size_t runlen = elt_size;
+ bfd_vma r_off_runend = r_off;
+ bfd_vma r_off_runend_next;
size_t buf_size = 96 * 1024;
while (p + runlen < end
&& (sortlen <= buf_size
|| runlen + elt_size <= buf_size)
- && r_off2 > (*ext_r_off) (p + runlen))
- runlen += elt_size;
+ /* run must not break the ordering of base..loc+1 */
+ && r_off2 > (r_off_runend_next = (*ext_r_off) (p + runlen))
+ /* run must be already sorted */
+ && r_off_runend_next >= r_off_runend)
+ {
+ runlen += elt_size;
+ r_off_runend = r_off_runend_next;
+ }
if (buf == NULL)
{
buf = bfd_malloc (buf_size);
if (ELF_ST_BIND (elfsym->st_info) == STB_GNU_UNIQUE)
elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_unique;
- if (name == NULL
- || *name == '\0'
- || (input_sec->flags & SEC_EXCLUDE))
+ if (name == NULL || *name == '\0')
elfsym->st_name = (unsigned long) -1;
else
{
pos = hdr->sh_offset + hdr->sh_size;
amt = bed->s->sizeof_sym * flinfo->output_bfd->symcount;
if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) == 0
- && bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt)
+ && bfd_write (symbuf, amt, flinfo->output_bfd) == amt)
{
hdr->sh_size += amt;
ret = true;
case SEC_INFO_TYPE_STABS:
case SEC_INFO_TYPE_EH_FRAME:
case SEC_INFO_TYPE_EH_FRAME_ENTRY:
+ case SEC_INFO_TYPE_SFRAME:
return true;
default:
break;
unsigned int
_bfd_elf_default_action_discarded (asection *sec)
{
+ const struct elf_backend_data *bed;
+ bed = get_elf_backend_data (sec->owner);
+
if (sec->flags & SEC_DEBUGGING)
return PRETEND;
if (strcmp (".eh_frame", sec->name) == 0)
return 0;
+ if (bed->elf_backend_can_make_multiple_eh_frame
+ && strncmp (sec->name, ".eh_frame.", 10) == 0)
+ return 0;
+
+ if (strcmp (".sframe", sec->name) == 0)
+ return 0;
+
if (strcmp (".gcc_except_table", sec->name) == 0)
return 0;
/* If this symbol is defined in a section which we are
discarding, we don't need to keep it. */
- if (isym->st_shndx != SHN_UNDEF
- && isym->st_shndx < SHN_LORESERVE
- && isec->output_section == NULL
- && flinfo->info->non_contiguous_regions
- && flinfo->info->non_contiguous_regions_warnings)
- {
- _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
- "discards section `%s' from '%s'\n"),
- isec->name, bfd_get_filename (isec->owner));
- continue;
- }
-
- if (isym->st_shndx != SHN_UNDEF
- && isym->st_shndx < SHN_LORESERVE
- && bfd_section_removed_from_list (output_bfd,
- isec->output_section))
+ if (isym->st_shndx < SHN_LORESERVE
+ && (isec->output_section == NULL
+ || bfd_section_removed_from_list (output_bfd,
+ isec->output_section)))
continue;
/* Get the name of the symbol. */
contents = flinfo->contents;
}
}
+ else if (!(o->flags & SEC_RELOC)
+ && !bed->elf_backend_write_section
+ && o->sec_info_type == SEC_INFO_TYPE_MERGE)
+ /* A MERGE section that has no relocations doesn't need the
+ contents anymore, they have been recorded earlier. Except
+ if the backend has special provisions for writing sections. */
+ contents = NULL;
else
{
contents = flinfo->contents;
return false;
}
break;
+ case SEC_INFO_TYPE_SFRAME:
+ {
+ /* Merge .sframe sections into the ctf frame encoder
+ context of the output_bfd's section. The final .sframe
+ output section will be written out later. */
+ if (!_bfd_elf_merge_section_sframe (output_bfd, flinfo->info,
+ o, contents))
+ return false;
+ }
+ break;
default:
{
if (! (o->flags & SEC_EXCLUDE))
{
/* Reverse-copy input section to output. */
- if (o->reloc_count != 0
- && (o->size * bed->s->int_rels_per_ext_rel
- != o->reloc_count * address_size))
+ if ((o->size & (address_size - 1)) != 0
+ || (o->reloc_count != 0
+ && (o->size * bed->s->int_rels_per_ext_rel
+ != o->reloc_count * address_size)))
{
_bfd_error_handler
/* xgettext:c-format */
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_outext_info eoinfo;
bool merged;
- size_t relativecount = 0;
+ size_t relativecount;
+ size_t relr_entsize;
asection *reldyn = 0;
bfd_size_type amt;
asection *attr_section = NULL;
&& elf_symtab_shndx_list (sec->owner) != NULL)
max_sym_shndx_count = sym_count;
- if (esdo->this_hdr.sh_type == SHT_REL
- || esdo->this_hdr.sh_type == SHT_RELA)
+ esdi = elf_section_data (sec);
+
+ if (esdi->this_hdr.sh_type == SHT_REL
+ || esdi->this_hdr.sh_type == SHT_RELA)
/* Some backends use reloc_count in relocation sections
to count particular types of relocs. Of course,
reloc sections themselves can't have relocations. */
else if (bed->elf_backend_count_relocs)
reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
- esdi = elf_section_data (sec);
-
if ((sec->flags & SEC_RELOC) != 0)
{
size_t ext_size = 0;
later. Use bfd_malloc since it will be freed by
bfd_compress_section_contents. */
unsigned char *contents = esdo->this_hdr.contents;
- if ((o->flags & SEC_ELF_COMPRESS) == 0 || contents != NULL)
+ if (contents != NULL)
abort ();
contents
= (unsigned char *) bfd_malloc (esdo->this_hdr.sh_size);
/* If backend needs to output some local symbols not present in the hash
table, do it now. */
- if (bed->elf_backend_output_arch_local_syms
- && (info->strip != strip_all || emit_relocs))
+ if (bed->elf_backend_output_arch_local_syms)
{
if (! ((*bed->elf_backend_output_arch_local_syms)
(abfd, info, &flinfo, elf_link_output_symstrtab)))
off, true);
if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt))
+ || (bfd_write (flinfo.symshndxbuf, amt, abfd) != amt))
{
ret = false;
goto return_local_hash_table;
o->reloc_count = 0;
}
+ relativecount = 0;
if (dynamic && info->combreloc && dynobj != NULL)
relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
+ relr_entsize = 0;
+ if (htab->srelrdyn != NULL
+ && htab->srelrdyn->output_section != NULL
+ && htab->srelrdyn->size != 0)
+ {
+ asection *s = htab->srelrdyn->output_section;
+ relr_entsize = elf_section_data (s)->this_hdr.sh_entsize;
+ if (relr_entsize == 0)
+ {
+ relr_entsize = bed->s->arch_size / 8;
+ elf_section_data (s)->this_hdr.sh_entsize = relr_entsize;
+ }
+ }
+
/* If we are linking against a dynamic object, or generating a
shared library, finish up the dynamic linking information. */
if (dynamic)
default:
continue;
case DT_NULL:
- if (relativecount > 0 && dyncon + bed->s->sizeof_dyn < dynconend)
+ if (relativecount != 0)
{
switch (elf_section_data (reldyn)->this_hdr.sh_type)
{
case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
- default: continue;
}
- dyn.d_un.d_val = relativecount;
+ if (dyn.d_tag != DT_NULL
+ && dynconend - dyncon >= bed->s->sizeof_dyn)
+ {
+ dyn.d_un.d_val = relativecount;
+ relativecount = 0;
+ break;
+ }
relativecount = 0;
- break;
+ }
+ if (relr_entsize != 0)
+ {
+ if (dynconend - dyncon >= 3 * bed->s->sizeof_dyn)
+ {
+ asection *s = htab->srelrdyn;
+ dyn.d_tag = DT_RELR;
+ dyn.d_un.d_ptr
+ = s->output_section->vma + s->output_offset;
+ bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
+ dyncon += bed->s->sizeof_dyn;
+
+ dyn.d_tag = DT_RELRSZ;
+ dyn.d_un.d_val = s->size;
+ bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
+ dyncon += bed->s->sizeof_dyn;
+
+ dyn.d_tag = DT_RELRENT;
+ dyn.d_un.d_val = relr_entsize;
+ relr_entsize = 0;
+ break;
+ }
+ relr_entsize = 0;
}
continue;
if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
goto error_return;
+ if (! _bfd_elf_write_section_sframe (abfd, info))
+ goto error_return;
+
if (info->callbacks->emit_ctf)
info->callbacks->emit_ctf ();
/* Return the local debug definition section. */
asection *isec = bfd_section_from_elf_index (sec->owner,
sym->st_shndx);
- if ((isec->flags & SEC_DEBUGGING) != 0)
+ if (isec != NULL && (isec->flags & SEC_DEBUGGING) != 0)
return isec;
}
_bfd_elf_adjust_eh_frame_global_symbol, NULL);
}
+ o = bfd_get_section_by_name (output_bfd, ".sframe");
+ if (o != NULL)
+ {
+ asection *i;
+
+ for (i = o->map_head.s; i != NULL; i = i->map_head.s)
+ {
+ if (i->size == 0)
+ continue;
+
+ abfd = i->owner;
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ continue;
+
+ if (!init_reloc_cookie_for_section (&cookie, info, i))
+ return -1;
+
+ if (_bfd_elf_parse_sframe (abfd, info, i, &cookie))
+ {
+ if (_bfd_elf_discard_section_sframe (i,
+ bfd_elf_reloc_symbol_deleted_p,
+ &cookie))
+ {
+ if (i->size != i->rawsize)
+ changed = 1;
+ }
+ }
+ fini_reloc_cookie_for_section (&cookie, i);
+ }
+ /* Update the reference to the output .sframe section. Used to
+ determine later if PT_GNU_SFRAME segment is to be generated. */
+ if (!_bfd_elf_set_section_sframe (output_bfd, info))
+ return -1;
+ }
+
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
{
const struct elf_backend_data *bed;
if (info->eh_frame_hdr_type
&& !bfd_link_relocatable (info)
- && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
+ && _bfd_elf_discard_section_eh_frame_hdr (info))
changed = 1;
return changed;