[binutils-gdb/binutils-2_46-branch] check sframe version in _bfd_elf_parse_sframe
Alan Modra via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e7b4e8eb10a599773c7aef3f629bf67b2f7c7323 commit e7b4e8eb10a599773c7aef3f629bf67b2f7c7323 Author: Alan Modra <[email protected]> Date: Fri Mar 13 08:55:04 2026 +1030 check sframe version in _bfd_elf_parse_sframe 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. (cherry picked from commit 7c80233f4d47c2508d8984bdcfc644b9a6e7bf9a) Diff: --- bfd/elf-sframe.c | 100 ++++++++++++++--------------- binutils/testsuite/lib/binutils-common.exp | 3 + 2 files changed, 52 insertions(+), 51 deletions(-) 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 72cbf4a4e05..150dbfa594b 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 }