check sframe version in _bfd_elf_parse_sframe
Alan Modra
amodra@gmail.com
Thu Mar 12 23:33:59 GMT 2026
Prompted by ld/bootstrap test failues on Ubuntu 25.10
ld-new: error in /lib/x86_64-linux-gnu/crt1.o (.sframe); unexpected SFrame format version 2
ld-new: final link failed
collect2: error: ld returned 1 exit status
Currently if you attempt to link an object file with sframe version 2
contents, the linker will complain in _bfd_elf_merge_section_sframe
and fail to produce an output. This affects anyone who has objects
assembled by binutils-2.45 with .sframe sections. A work-around is to
pass --discard-sframe to ld.
Ideally the linker would rewrite version 2 sframe input to version 3,
but in the absence of that support it would be nicer if ld just
ignored version 2 (or 1) sframe sections without needing to pass
--discard-sframe. That is the aim of this patch.
It does so by checking the sframe version in _bfd_elf_parse_sframe
where various failing checks result in an error being printed and the
section not being marked as SEC_INFO_TYPE_SFRAME, but causes no
overall linker failure. In addition, an sframe version failure now
also marks the sframe section with SEC_EXCLUDE. This is also done for
other sframe failures. See the changelog below for other fixes.
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Don't check
sframe version here.
(_bfd_elf_parse_sframe): Check sframe version here instead.
Do the "already parsed" check first. Reorder various other
checks. Do not bother parsing or print errors when
discard_sframe is set. Free section contents on failure
paths. Set SEC_EXCLUDE for fails. Check for NULL bfd_zalloc
return, and only allocate after successfully parsing sframe.
On errors report that the section will be ignored, not "no
.sframe will be created".
binutils/
* testsuite/lib/binutils-common.exp: Ignore sframe version
errors.
diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c
index 7b2eed81c9f..995987eea6d 100644
--- a/bfd/elf-sframe.c
+++ b/bfd/elf-sframe.c
@@ -220,7 +220,7 @@ _bfd_elf_sframe_present (struct bfd_link_info *info)
bool
_bfd_elf_parse_sframe (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
asection *sec, struct elf_reloc_cookie *cookie)
{
bfd_byte *sfbuf = NULL;
@@ -229,74 +229,85 @@ _bfd_elf_parse_sframe (bfd *abfd,
bfd_size_type sf_size;
int decerr = 0;
+ /* Check if this section was already parsed. */
+ if (sec->sec_info_type == SEC_INFO_TYPE_SFRAME)
+ return true;
+
if (info->discard_sframe)
- sec->flags |= SEC_EXCLUDE;
+ {
+ sec->flags |= SEC_EXCLUDE;
+ return false;
+ }
- /* Prior versions of assembler and ld were generating SFrame sections with
- section type SHT_PROGBITS. Issue an error for lack of support for such
- objects now. Even if section size is zero, a valid section type is
- expected. */
- if (elf_section_type (sec) != SHT_GNU_SFRAME)
+ if ((sec->flags & SEC_EXCLUDE) != 0
+ || bfd_is_abs_section (sec->output_section))
{
- _bfd_error_handler
- (_("error in %pB(%pA); unexpected SFrame section type"),
- abfd, sec);
+ /* This sections is being discarded from the link, ignore it. */
return false;
}
if (sec->size == 0
|| (sec->flags & SEC_HAS_CONTENTS) == 0)
{
- /* This file does not contain .sframe information. */
- return false;
+ /* This section does not contain .sframe information. */
+ goto fail4;
}
- /* Check if this section was already parsed. */
- if (sec->sec_info_type == SEC_INFO_TYPE_SFRAME)
- return true;
-
- if (bfd_is_abs_section (sec->output_section))
+ /* Prior versions of assembler and ld were generating SFrame sections with
+ section type SHT_PROGBITS. Issue an error for lack of support for such
+ objects now. Even if section size is zero, a valid section type is
+ expected. */
+ if (elf_section_type (sec) != SHT_GNU_SFRAME)
{
- /* At least one of the sections is being discarded from the
- link, so we should just ignore them. */
- return false;
+ _bfd_error_handler
+ (_("error in %pB(%pA); unexpected SFrame section type; section ignored"),
+ abfd, sec);
+ goto fail4;
}
/* Read the SFrame stack trace information from abfd. */
if (!_bfd_elf_mmap_section_contents (abfd, sec, &sfbuf))
- goto fail_no_free;
+ goto fail3;
/* Decode the buffer and keep decoded contents for later use.
Relocations are performed later, but are such that the section's
size is unaffected. */
- sfd_info = bfd_zalloc (abfd, sizeof (*sfd_info));
sf_size = sec->size;
+ sfd_ctx = sframe_decode ((const char *) sfbuf, sf_size, &decerr);
+ if (!sfd_ctx)
+ goto fail2;
- sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
+ uint8_t dctx_version = sframe_decoder_get_version (sfd_ctx);
+ if (dctx_version != SFRAME_VERSION)
+ {
+ _bfd_error_handler
+ (_("error in %pB(%pA); unexpected SFrame format version %" PRIu8),
+ abfd, sec, dctx_version);
+ goto fail2;
+ }
+
+ sfd_info = bfd_zalloc (abfd, sizeof (*sfd_info));
+ if (!sfd_info)
+ goto fail1;
+ sfd_info->sfd_ctx = sfd_ctx;
sfd_info->sfd_state = SFRAME_SEC_DECODED;
- sfd_ctx = sfd_info->sfd_ctx;
- if (!sfd_ctx)
- /* Free'ing up any memory held by decoder context is done by
- sframe_decode in case of error. */
- goto fail_no_free;
if (!sframe_decoder_init_func_bfdinfo (abfd, sec, sfd_info, cookie))
{
+ fail1:
sframe_decoder_free (&sfd_info->sfd_ctx);
- goto fail_no_free;
+ fail2:
+ _bfd_elf_munmap_section_contents (sec, sfbuf);
+ fail3:
+ _bfd_error_handler (_("error in %pB(%pA); SFrame section ignored"),
+ abfd, sec);
+ fail4:
+ sec->flags |= SEC_EXCLUDE;
+ return false;
}
sec->sec_info = sfd_info;
sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
-
- goto success;
-
-fail_no_free:
- _bfd_error_handler
- (_("error in %pB(%pA); no .sframe will be created"),
- abfd, sec);
- return false;
-success:
_bfd_elf_munmap_section_contents (sec, sfbuf);
return true;
}
@@ -384,8 +395,6 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
uint8_t sfd_ctx_abi_arch;
int8_t sfd_ctx_fixed_fp_offset;
int8_t sfd_ctx_fixed_ra_offset;
- uint8_t dctx_version;
- uint8_t ectx_version;
uint8_t dctx_flags;
uint8_t ectx_flags;
int encerr = 0;
@@ -472,17 +481,6 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
return false;
}
- /* Check that all .sframe sections being linked have the same version. */
- dctx_version = sframe_decoder_get_version (sfd_ctx);
- ectx_version = sframe_encoder_get_version (sfe_ctx);
- if (dctx_version != SFRAME_VERSION_3 || dctx_version != ectx_version)
- {
- _bfd_error_handler
- (_("error in %pB (%pA); unexpected SFrame format version %" PRIu8),
- sec->owner, sec, dctx_version);
- return false;
- }
-
/* Check that all SFrame sections being linked have the 'data encoding'
related flags set. The implementation does not support updating these
data encodings on the fly; confirm by checking the ectx_flags. */
diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index 24215502069..2dafd14e3ee 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -792,6 +792,9 @@ proc prune_warnings_extra { text } {
regsub -all {(^|\n)([^\n]*lto-wrapper: warning: using serial compilation of [0-9]+ LTRANS jobs[^\n]*\n?)+} $text {\1} text
regsub -all {(^|\n)([^\n]*lto-wrapper: note: [^\n]*\n?)+} $text {\1} text
+ # Ignore warnings about linking objects with an old sframe format
+ regsub -all {(^|\n)([^\n]* unexpected SFrame format version [^\n]*\n[^\n]* SFrame section ignored\n?)+} $text {\1} text
+
return $text
}
--
Alan Modra
More information about the Binutils
mailing list