if (elfsec == 0)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- if (bed->link_order_error_handler)
- bed->link_order_error_handler
- /* xgettext:c-format */
- (_("%pB: warning: sh_link not set for section `%pA'"),
- abfd, s);
+ bed->link_order_error_handler
+ /* xgettext:c-format */
+ (_("%pB: warning: sh_link not set for section `%pA'"),
+ abfd, s);
}
else
{
}
/* Allow the target a chance to decide how these fields should be set. */
- if (bed->elf_backend_copy_special_section_fields != NULL
- && bed->elf_backend_copy_special_section_fields
- (ibfd, obfd, iheader, oheader))
+ if (bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+ iheader, oheader))
return TRUE;
/* We have an iheader which might match oheader, and which has non-zero
{
/* Final attempt. Call the backend copy function
with a NULL input section. */
- if (bed->elf_backend_copy_special_section_fields != NULL)
- (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
+ (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+ NULL, oheader);
}
}
return FALSE;
}
-/* Get version string. */
+/* Get version name. If BASE_P is TRUE, return "Base" for VER_FLG_BASE
+ and return symbol version for symbol version itself. */
const char *
_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
+ bfd_boolean base_p,
bfd_boolean *hidden)
{
const char *version_string = NULL;
&& (vernum > elf_tdata (abfd)->cverdefs
|| (elf_tdata (abfd)->verdef[0].vd_flags
== VER_FLG_BASE)))
- version_string = "Base";
+ version_string = base_p ? "Base" : "";
else if (vernum <= elf_tdata (abfd)->cverdefs)
- version_string =
- elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ {
+ const char *nodename
+ = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ version_string = "";
+ if (base_p
+ || nodename == NULL
+ || symbol->name == NULL
+ || strcmp (symbol->name, nodename) != 0)
+ version_string = nodename;
+ }
else
{
Elf_Internal_Verneed *t;
/* If we have version information, print it. */
version_string = _bfd_elf_get_symbol_version_string (abfd,
symbol,
+ TRUE,
&hidden);
if (version_string)
{
if (sections_being_created == NULL)
{
size_t amt = elf_numsections (abfd) * sizeof (bfd_boolean);
- sections_being_created = (bfd_boolean *) bfd_zalloc (abfd, amt);
+
+ /* PR 26005: Do not use bfd_zalloc here as the memory might
+ be released before the bfd has been fully scanned. */
+ sections_being_created = (bfd_boolean *) bfd_malloc (amt);
if (sections_being_created == NULL)
return FALSE;
+ memset (sections_being_created, FALSE, amt);
sections_being_created_abfd = abfd;
}
if (sections_being_created [shindex])
sections. */
if (*p_hdr != NULL)
{
- if (bed->init_secondary_reloc_section == NULL
- || ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
+ if (!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"),
+ (_("%pB: warning: secondary relocation section '%s' "
+ "for section %pA found - ignoring"),
abfd, name, target_sect);
}
goto success;
sections_being_created [shindex] = FALSE;
if (-- nesting == 0)
{
+ free (sections_being_created);
sections_being_created = NULL;
- sections_being_created_abfd = abfd;
+ sections_being_created_abfd = NULL;
}
return ret;
}
where s is NULL. */
const struct elf_backend_data *bed
= get_elf_backend_data (abfd);
- if (bed->link_order_error_handler)
- bed->link_order_error_handler
- /* xgettext:c-format */
- (_("%pB: warning: sh_link not set for section `%pA'"),
- abfd, sec);
+ bed->link_order_error_handler
+ /* xgettext:c-format */
+ (_("%pB: warning: sh_link not set for section `%pA'"),
+ abfd, sec);
}
}
elf_section_data (s)->this_hdr.sh_link = d->this_idx;
/* This is a .stab section. */
- if (elf_section_data (s)->this_hdr.sh_entsize == 0)
- elf_section_data (s)->this_hdr.sh_entsize
- = 4 + 2 * bfd_get_arch_size (abfd) / 8;
+ elf_section_data (s)->this_hdr.sh_entsize = 12;
}
}
break;
{
i = m->count;
while (--i != (unsigned) -1)
- if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
- == (SEC_LOAD | SEC_HAS_CONTENTS))
- break;
+ {
+ if (m->sections[i]->size > 0
+ && (m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
+ == (SEC_LOAD | SEC_HAS_CONTENTS))
+ break;
+ }
if (i != (unsigned) -1)
break;
}
p->p_memsz += adjust;
- if (this_hdr->sh_type != SHT_NOBITS)
+ if (p->p_type == PT_LOAD)
{
- if (p->p_type == PT_LOAD)
+ if (this_hdr->sh_type != SHT_NOBITS)
{
+ off_adjust = 0;
if (p->p_filesz + adjust < p->p_memsz)
{
/* We have a PROGBITS section following NOBITS ones.
if (!write_zeros (abfd, off, adjust))
return FALSE;
}
+ }
+ /* We only adjust sh_offset in SHT_NOBITS sections
+ as would seem proper for their address when the
+ section is first in the segment. sh_offset
+ doesn't really have any significance for
+ SHT_NOBITS anyway, apart from a notional position
+ relative to other sections. Historically we
+ didn't bother with adjusting sh_offset and some
+ programs depend on it not being adjusted. See
+ pr12921 and pr25662. */
+ if (this_hdr->sh_type != SHT_NOBITS || i == 0)
+ {
off += adjust;
+ if (this_hdr->sh_type == SHT_NOBITS)
+ off_adjust += adjust;
}
- p->p_filesz += adjust;
}
+ if (this_hdr->sh_type != SHT_NOBITS)
+ p->p_filesz += adjust;
}
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
elf_section_flags (s->output_section) &= ~SHF_GROUP;
elf_group_name (s->output_section) = NULL;
}
- /* Conversely, if the member section is not being output
- but the SHT_GROUP section is, then adjust its size. */
- else if (s->output_section == discarded
- && isec->output_section != discarded)
+ else
{
struct bfd_elf_section_data *elf_sec = elf_section_data (s);
- removed += 4;
- if (elf_sec->rel.hdr != NULL
- && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
- removed += 4;
- if (elf_sec->rela.hdr != NULL
- && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
- removed += 4;
+ if (s->output_section == discarded
+ && isec->output_section != discarded)
+ {
+ /* Conversely, if the member section is not being
+ output but the SHT_GROUP section is, then adjust
+ its size. */
+ removed += 4;
+ if (elf_sec->rel.hdr != NULL
+ && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
+ removed += 4;
+ if (elf_sec->rela.hdr != NULL
+ && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
+ removed += 4;
+ }
+ else
+ {
+ /* Also adjust for zero-sized relocation member
+ section. */
+ if (elf_sec->rel.hdr != NULL
+ && elf_sec->rel.hdr->sh_size == 0)
+ removed += 4;
+ if (elf_sec->rela.hdr != NULL
+ && elf_sec->rela.hdr->sh_size == 0)
+ removed += 4;
+ }
}
s = elf_next_in_group (s);
if (s == first)
}
long
-_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
- sec_ptr asect)
+_bfd_elf_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
{
+ if (asect->reloc_count != 0)
+ {
+ /* Sanity check reloc section size. */
+ struct bfd_elf_section_data *d = elf_section_data (asect);
+ Elf_Internal_Shdr *rel_hdr = &d->this_hdr;
+ bfd_size_type ext_rel_size = rel_hdr->sh_size;
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+
+ if (filesize != 0 && ext_rel_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
+
#if SIZEOF_LONG == SIZEOF_INT
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
{
long
_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
{
- bfd_size_type count;
+ bfd_size_type count, ext_rel_size;
asection *s;
if (elf_dynsymtab (abfd) == 0)
}
count = 1;
+ ext_rel_size = 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))
{
+ ext_rel_size += s->size;
+ if (ext_rel_size < s->size)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
if (count > LONG_MAX / sizeof (arelent *))
{
return -1;
}
}
+ if (count > 1)
+ {
+ /* Sanity check reloc section sizes. */
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && ext_rel_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
return count * sizeof (arelent *);
}
return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
}
+static bfd_boolean
+elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-arc-v2", note);
+}
+
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
else
return TRUE;
+ case NT_ARC_V2:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_arc_v2 (abfd, note);
+ else
+ return TRUE;
+
case NT_ARM_VFP:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
}
+char *
+elfcore_write_arc_v2 (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *arc_v2,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARC_V2, arc_v2, size);
+}
+
char *
elfcore_write_register_note (bfd *abfd,
char *buf,
return elfcore_write_aarch_sve (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-aarch-pauth") == 0)
return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-arc-v2") == 0)
+ return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size);
return NULL;
}