From: Indu Bhagat Date: Fri, 6 Feb 2026 20:21:34 +0000 (-0800) Subject: objdump: sframe: fix multiple emission of SFrame and DWARF Frame X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7aed4728e4d266f8e3c82f4689d90e53e9231f91;p=thirdparty%2Fbinutils-gdb.git objdump: sframe: fix multiple emission of SFrame and DWARF Frame Currently, when a user specifies both -WF (to dump DWARF Frame) and --sframe, the dump_dwarf () call is triggered twice, First, in dump_bfd (): if (dump_dwarf_section_info) dump_dwarf (abfd, is_mainfile); And then again in dump_bfd () via: if (dump_sframe_section_info) dump_sframe_section (abfd, dump_sframe_section_name, is_mainfile); Where dump_sframe_section () itself invokes dump_dwarf () to emit SFrame section. The original intent of making dump_sframe_section () to invoke dump_dwarf () was to reuse the existing (DWARF) machinery for relocation and emission of SFrame section (along with DWARF sections). But this may cause duplicate emission as noted above (PR 33806). So, carve out the necessary work into dump_sframe_section () to make it not invoke dump_dwarf (): explicitly load the SFrame section and then invoke the associated display function directly. This ensures that the SFrame textual dump is emitted exactly once as intended. Additionally, this patch removes: - the temporary "sframe-internal-only" debug option because it not needed anymore, now that we dont use dump_dwarf () for SFrame dumping anymore. - stubs from dump_dwarf_section () specific to SFrame, as it is not called for it anymore. While at it, xstrdup consistently and free the dump_sframe_section_name var. Update the existing sframe-func.s to ensure .eh_frame section is emitted as well. Add new test objdump-sframe-2.d to verify that textual dump using objdump contains single textual dumps of .eh_frame and .sframe (if both --sframe and -WF are specified). PR libsframe/33806 binutils/ PR libsframe/33806 * dwarf.c (debug_option_table): Remove sframe-internal-only. * objdump.c (dump_sframe_section): Call display function directly instead of dump_dwarf. (dump_bfd): Update call to dump_sframe_section. (main): Remove 'sframe-internal-only' hack. binutils/testsuite/ * binutils-all/x86-64/sframe-func.s: Emit .eh_frame section as well. * binutils-all/x86-64/objdump-sframe-2.d: New test. --- diff --git a/binutils/dwarf.c b/binutils/dwarf.c index a671d4da616..3c2ba3099fb 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -14005,7 +14005,6 @@ static const debug_dump_long_opts debug_option_table[] = /* For compatibility with earlier versions of readelf. */ { 'r', "ranges", &do_debug_aranges, 1 }, { 's', "str", &do_debug_str, 1 }, - { '\0', "sframe-internal-only", &do_sframe, 1 }, { 'T', "trace_aranges", &do_trace_aranges, 1 }, { 't', "pubtypes", &do_debug_pubtypes, 1 }, { 'U', "trace_info", &do_trace_info, 1 }, diff --git a/binutils/objdump.c b/binutils/objdump.c index 7fc6f7684b0..8b6021a20fe 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -4495,10 +4495,6 @@ dump_dwarf_section (bfd *abfd, asection *section, else match = name; - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour - && elf_section_type (section) == SHT_GNU_SFRAME) - match = ".sframe"; - for (i = 0; i < max; i++) if ((strcmp (debug_displays [i].section.uncompressed_name, match) == 0 || strcmp (debug_displays [i].section.compressed_name, match) == 0 @@ -5043,33 +5039,36 @@ dump_ctf (bfd *abfd ATTRIBUTE_UNUSED, const char *sect_name ATTRIBUTE_UNUSED, #endif static void -dump_sframe_section (bfd *abfd, const char *sect_name, bool is_mainfile) +dump_sframe_section (bfd *abfd, const char *sect_name) { /* Error checking for user provided SFrame section name, if any. */ - if (sect_name) + asection *sec = bfd_get_section_by_name (abfd, sect_name); + if (sec == NULL) { - asection *sec = bfd_get_section_by_name (abfd, sect_name); - if (sec == NULL) - { - printf (_("No %s section present\n\n"), sanitize_string (sect_name)); - return; - } - /* Starting with Binutils 2.45, SFrame sections have section type - SHT_GNU_SFRAME. For SFrame sections from Binutils 2.44 or earlier, - check explcitly for SFrame sections of type SHT_PROGBITS and name - ".sframe" to allow them. */ - else if (bfd_get_flavour (abfd) != bfd_target_elf_flavour - || (elf_section_type (sec) != SHT_GNU_SFRAME - && !(elf_section_type (sec) == SHT_PROGBITS - && strcmp (sect_name, ".sframe") == 0))) - { - printf (_("Section %s does not contain SFrame data\n\n"), - sanitize_string (sect_name)); - return; - } + printf (_("No %s section present\n\n"), sanitize_string (sect_name)); + return; + } + /* Starting with Binutils 2.45, SFrame sections have section type + SHT_GNU_SFRAME. For SFrame sections from Binutils 2.44 or earlier, + check explcitly for SFrame sections of type SHT_PROGBITS and name + ".sframe" to allow them. */ + else if (bfd_get_flavour (abfd) != bfd_target_elf_flavour + || (elf_section_type (sec) != SHT_GNU_SFRAME + && !(elf_section_type (sec) == SHT_PROGBITS + && strcmp (sect_name, ".sframe") == 0))) + { + printf (_("Section %s does not contain SFrame data\n\n"), + sanitize_string (sect_name)); + return; } - dump_dwarf (abfd, is_mainfile); + + if (!load_specific_debug_section (sframe, sec, (void *) abfd)) + return; + + struct dwarf_section *section = &debug_displays[sframe].section; + section->name = sect_name; + debug_displays[sframe].display (section, abfd); } @@ -5893,7 +5892,7 @@ dump_bfd (bfd *abfd, bool is_mainfile) dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name, dump_ctf_parent_section_name); if (dump_sframe_section_info) - dump_sframe_section (abfd, dump_sframe_section_name, is_mainfile); + dump_sframe_section (abfd, dump_sframe_section_name); if (dump_stab_section_info) dump_stabs (abfd); if (dump_reloc_info && ! disassemble) @@ -6362,9 +6361,7 @@ main (int argc, char **argv) seenflag = true; if (optarg) { - if (strcmp (optarg, "sframe-internal-only") == 0) - warn (_("Unrecognized debug option 'sframe-internal-only'\n")); - else if (dwarf_select_sections_by_names (optarg)) + if (dwarf_select_sections_by_names (optarg)) dump_dwarf_section_info = true; } else @@ -6409,12 +6406,7 @@ main (int argc, char **argv) if (optarg) dump_sframe_section_name = xstrdup (optarg); else - dump_sframe_section_name = ".sframe"; - - /* Error checking for dump_sframe_section_name is done in - dump_sframe_section (). Initialize for now with the default - internal name: "sframe-internal-only". */ - dwarf_select_sections_by_names ("sframe-internal-only"); + dump_sframe_section_name = xstrdup (".sframe"); seenflag = true; break; @@ -6507,6 +6499,7 @@ main (int argc, char **argv) free (dump_ctf_parent_name); free ((void *) source_comment); free (dump_ctf_parent_section_name); + free (dump_sframe_section_name); return exit_status; } diff --git a/binutils/testsuite/binutils-all/x86-64/objdump-sframe-2.d b/binutils/testsuite/binutils-all/x86-64/objdump-sframe-2.d new file mode 100644 index 00000000000..3d3b27e0592 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/objdump-sframe-2.d @@ -0,0 +1,33 @@ +#name: objdump SFrame with EH Frame +#source: sframe-func.s +#as: --gsframe +#objdump: --sframe -WF +#target: x86_64-*-* +#notarget: ![gas_sframe_check] + +.*: +file format .* + +Contents of the .eh_frame section: + +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ CIE "zR" cf=1 df=-8 ra=16 +#... +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ FDE cie=[0-9a-f]+ pc=[0-9a-f]+..0+0010 +#... + +Contents of the SFrame section .sframe: + Header : + + Version: SFRAME_VERSION_3 + Flags: SFRAME_F_FDE_FUNC_START_PCREL +#... + Num FDEs: 1 + Num FREs: 4 + + Function Index : + + func idx \[0\]: pc = 0x0, size = 16 bytes + STARTPC +CFA +FP +RA + + 0+0000 +sp\+8 +u +f + + 0+0004 +sp\+16 +c-16 +f + + 0+0008 +fp\+16 +c-16 +f + + 0+000c +sp\+8 +c-16 +f + diff --git a/binutils/testsuite/binutils-all/x86-64/sframe-func.s b/binutils/testsuite/binutils-all/x86-64/sframe-func.s index cbd83c38d67..d806ec1b499 100644 --- a/binutils/testsuite/binutils-all/x86-64/sframe-func.s +++ b/binutils/testsuite/binutils-all/x86-64/sframe-func.s @@ -1,4 +1,3 @@ - .cfi_sections .sframe .cfi_startproc .long 8 .cfi_def_cfa_offset 16