]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: elf: binutils: add new section type SHT_GNU_SFRAME
authorIndu Bhagat <indu.bhagat@oracle.com>
Sat, 12 Jul 2025 06:32:58 +0000 (23:32 -0700)
committerIndu Bhagat <indu.bhagat@oracle.com>
Sat, 12 Jul 2025 06:32:58 +0000 (23:32 -0700)
So far, SFrame sections were of type SHT_PROGBITS.

As per ELF specification, SHT_PROGBITS indicates that the section holds
information defined by the program, whose format and meaning are
determined solely by the program.

On the linker side, SHT_PROGBITS should be reserved for the simple "cat
contents after applying relocs" semantics.

Currently, the only way to know that a section contains SFrame stack
trace data is if consumer checks for section name.  Such a check for
section name is not quite conformant to ELF principles.

Some of this was discussed here
https://sourceware.org/pipermail/binutils/2025-March/140181.html

With this change, the SFrame sections generated by gas, ld will have
section type set to SHT_GNU_SFRAME.   The new section type is defined in
the SHT_LOOS/SHT_HIOS space.  The SFrame parsing routine
_bfd_elf_parse_sframe () now admits sections only when the the section
type is SHT_GNU_SFRAME.

No special handling / validation is done at the moment for the case of
manual creation of SFrame sections via obj_elf_section ().  Add function
level comments for now to add a note about this.

Although the default handling for (sh_type >= SHT_LOOS && sh_type <=
SHT_HIOS) is sufficient when SHT_GNU_SFRAME is in that range, it makes
sense to add it as a case of its own.

bfd/
* elf-sframe.c (_bfd_elf_parse_sframe): Check if section type is
SHT_GNU_SFRAME.
(_bfd_elf_set_section_sframe): Set SHT_GNU_SFRAME for output
SFrame section.
* elflink.c (obj_elf_section): Use section type for check
instead of section name.
* elfxx-x86.c: Set SHT_GNU_SFRAME for SFrame sections for
.plt* sections.
* elf.c (bfd_section_from_shdr): Add case for SHT_GNU_SFRAME.
binutils/
* readelf.c (get_os_specific_section_type_name): Add
SHT_GNU_SFRAME.
gas/
* NEWS: Announce emitted SFrame sections have SHT_GNU_SFRAME
set.
* config/obj-elf.c (obj_elf_attach_to_group): Add comments to
indicate no special handling for SFrame yet.
* dw2gencfi.c (cfi_finish): Set SHT_GNU_SFRAME for emitted
SFrame section.
ld/
* NEWS: Announce emitted SFrame sections have SHT_GNU_SFRAME
set.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: Add new test.
* gas/cfi-sframe/cfi-sframe-common-1b.d: New test.
* gas/cfi-sframe/cfi-sframe-common-1b.s: New test.
include/
* elf/common.h (SHT_GNU_SFRAME): Add new section type for SFrame
stack trace information.
libsframe/doc/
* sframe-spec.texi: Add expected ELF section type.

14 files changed:
bfd/elf-sframe.c
bfd/elf.c
bfd/elflink.c
bfd/elfxx-x86.c
binutils/readelf.c
gas/NEWS
gas/config/obj-elf.c
gas/dw2gencfi.c
gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
include/elf/common.h
ld/NEWS
libsframe/doc/sframe-spec.texi

index d74235b030a49d620964cd1ac93fd28ee07f22b2..b709e590a2dc9240f8910046d126734f5ac90925 100644 (file)
@@ -191,6 +191,18 @@ _bfd_elf_parse_sframe (bfd *abfd,
   bfd_size_type sf_size;
   int decerr = 0;
 
+  /* 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)
+    {
+      _bfd_error_handler
+       (_("error in %pB(%pA); unexpected SFrame section type"),
+        abfd, sec);
+      return false;
+    }
+
   if (sec->size == 0
       || (sec->flags & SEC_HAS_CONTENTS) == 0
       || sec->sec_info_type != SEC_INFO_TYPE_NONE)
@@ -298,8 +310,7 @@ _bfd_elf_discard_section_sframe
    BFD ABFD.  Returns true if no error.  */
 
 bool
-_bfd_elf_set_section_sframe (bfd *abfd,
-                               struct bfd_link_info *info)
+_bfd_elf_set_section_sframe (bfd *abfd, struct bfd_link_info *info)
 {
   asection *cfsec;
 
@@ -307,6 +318,7 @@ _bfd_elf_set_section_sframe (bfd *abfd,
   if (!cfsec)
     return false;
 
+  elf_section_type (cfsec) = SHT_GNU_SFRAME;
   elf_sframe (abfd) = cfsec;
 
   return true;
index 1eba14283f831370bc08af19f4a6e155cdcb7145..ba0e313524da31a8359f0f8718c6a5da6ec89dc6 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2476,6 +2476,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
     case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
     case SHT_GNU_LIBLIST:      /* .gnu.liblist section.  */
     case SHT_GNU_HASH:         /* .gnu.hash section.  */
+    case SHT_GNU_SFRAME:       /* .sframe section.  */
       ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
       goto success;
 
index 666399bc6809f6eeb7cd708bb34e020816a1a11e..c4f57cf2f3c6aad1e218b168a6abb948c2071be6 100644 (file)
@@ -11293,7 +11293,7 @@ _bfd_elf_default_action_discarded (asection *sec)
       && strncmp (sec->name, ".eh_frame.", 10) == 0)
     return 0;
 
-  if (strcmp (".sframe", sec->name) == 0)
+  if (elf_section_type (sec) == SHT_GNU_SFRAME)
     return 0;
 
   if (strcmp (".gcc_except_table", sec->name) == 0)
index 663f40ae7f071e9555329574629c2b0d0974a151..3dc00956eeff8ea7fc9bfbf9a4758ef25cee7c97 100644 (file)
@@ -4785,11 +4785,10 @@ _bfd_x86_elf_link_setup_gnu_properties
                            | SEC_HAS_CONTENTS | SEC_IN_MEMORY
                            | SEC_LINKER_CREATED);
 
-         sec = bfd_make_section_anyway_with_flags (dynobj,
-                                                   ".sframe",
-                                                   flags);
+         sec = bfd_make_section_anyway_with_flags (dynobj, ".sframe", flags);
          if (sec == NULL)
            info->callbacks->fatal (_("%P: failed to create PLT .sframe section\n"));
+         elf_section_type (sec) = SHT_GNU_SFRAME;
 
          // FIXME check this
          // if (!bfd_set_section_alignment (sec, class_align))
@@ -4805,6 +4804,7 @@ _bfd_x86_elf_link_setup_gnu_properties
                                                        flags);
              if (sec == NULL)
                info->callbacks->fatal (_("%P: failed to create second PLT .sframe section\n"));
+             elf_section_type (sec) = SHT_GNU_SFRAME;
 
              htab->plt_second_sframe = sec;
            }
@@ -4817,6 +4817,7 @@ _bfd_x86_elf_link_setup_gnu_properties
                                                        flags);
              if (sec == NULL)
                info->callbacks->fatal (_("%P: failed to create PLT GOT .sframe section\n"));
+             elf_section_type (sec) = SHT_GNU_SFRAME;
 
              htab->plt_got_sframe = sec;
            }
index 573024727f23513d66fb70ce7fed9a04a1ad6de6..87615d95ac12052eedf0cff0ee588cf2536e645b 100644 (file)
@@ -5964,6 +5964,7 @@ get_os_specific_section_type_name (Filedata * filedata, unsigned int sh_type)
     case SHT_GNU_HASH:                return "GNU_HASH";
     case SHT_GNU_LIBLIST:             return "GNU_LIBLIST";
     case SHT_GNU_OBJECT_ONLY:        return "GNU_OBJECT_ONLY";
+    case SHT_GNU_SFRAME:              return "GNU_SFRAME";
 
     case SHT_SUNW_move:               return "SUNW_MOVE";
     case SHT_SUNW_COMDAT:             return "SUNW_COMDAT";
@@ -8367,6 +8368,7 @@ process_section_headers (Filedata * filedata)
 
        case SHT_NOTE:
        case SHT_PROGBITS:
+       case SHT_GNU_SFRAME:
          /* Having a zero sized section is not illegal according to the
             ELF standard, but it might be an indication that something
             is wrong.  So issue a warning if we are running in lint mode.  */
index 56a2b88d1ea71b3b96723a4548eab023331c580e..24b3c8ace0c36e48aee8f8b4bbfe672b02116289 100644 (file)
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -8,6 +8,8 @@
   with the applicable encoding.  Setting the flag ensures compliance with the
   updated SFrame V2 specification.
 
+  ELF SFrame sections now have section type set to SHT_GNU_SFRAME.
+
 * Add .errif and .warnif directives, permitting user-controlled diagnostics
   with conditionals that are evaluated only at the end of assembly.
 
index 03b6c2470e741904a23c635001e98ffb58024133..315d08ea9963c44d6dcf86f00df8676574179d2f 100644 (file)
@@ -1163,6 +1163,15 @@ obj_elf_attach_to_group (int dummy ATTRIBUTE_UNUSED)
   elf_set_group_name (now_seg, gname);
 }
 
+/* Handle section related directives.
+
+   Note on support for SFrame sections: These are generally expected to be
+   generated by the assembler.  However, this function permits their direct
+   creation by the user.  At the moment though, we go no extra mile by adding
+   an explicit @sframe for SHT_GNU_SFRAME (using the numeric value of section
+   type should suffice); Nor do we implement any outright refusal for
+   non-supported targets via ELFOSABI-specific checks.  */
+
 void
 obj_elf_section (int push)
 {
index 6f8d5912a36061dd1d44ac6098158bc9efc47417..5c63054292f4ec569dce6a7004ac4fdae610ba7f 100644 (file)
@@ -2611,6 +2611,7 @@ cfi_finish (void)
                                    (SEC_ALLOC | SEC_LOAD | SEC_DATA
                                     | DWARF2_EH_FRAME_READ_ONLY),
                                    alignment);
+         elf_section_type (sframe_seg) = SHT_GNU_SFRAME;
          output_sframe (sframe_seg);
        }
       else
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.d
new file mode 100644 (file)
index 0000000..c6ddfba
--- /dev/null
@@ -0,0 +1,6 @@
+#as: --gsframe
+#readelf: -S
+#name: SFrame section header in readelf output
+#...
+[      ]*\[.*\][       ]+\.sframe[     ]+GNU_SFRAME.*
+#...
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.s
new file mode 100644 (file)
index 0000000..ac9c6ca
--- /dev/null
@@ -0,0 +1,3 @@
+       .cfi_sections .sframe
+       .cfi_startproc
+       .cfi_endproc
index 9c5a16f255b469922dd8f9cc66d4516bc257efeb..8a424198a88e9e8b87bbe1d5e3a8f0679f29a112 100644 (file)
@@ -72,6 +72,7 @@ if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]
     set old_ASFLAGS "$ASFLAGS"
 
     run_dump_test "cfi-sframe-common-1"
+    run_dump_test "cfi-sframe-common-1b"
     run_dump_test "cfi-sframe-common-2"
     run_dump_test "cfi-sframe-common-3"
     run_dump_test "cfi-sframe-common-4"
index f395278b243841e930673d1a3a91199727b0e4dc..0d9a7b7a8a98e177ac0e6fd02ae119c3a1a80942 100644 (file)
 
 #define SHT_ANDROID_RELR             0x6fffff00
 
+#define SHT_GNU_SFRAME              0x6ffffff4 /* SFrame stack trace information.  */
 #define SHT_GNU_ATTRIBUTES           0x6ffffff5        /* Object attributes */
 #define SHT_GNU_HASH                0x6ffffff6 /* GNU style symbol hash table */
 #define SHT_GNU_LIBLIST                     0x6ffffff7 /* List of prelink dependencies */
diff --git a/ld/NEWS b/ld/NEWS
index 2ad06e9c124ee4d32d921f5c1dbc24529693b79d..c37352b89f6a08d085412424e7f345f69840ef72 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -9,6 +9,8 @@
   sfde_func_start_address field in the SFrame section.  Relocatable SFrame
   links are now fixed.
 
+  ELF SFrame sections now have section type set to SHT_GNU_SFRAME.
+
 * On RISC-V, add new PLT formats, and GNU property merge rules for zicfiss and
   zicfilp extensions.
 
index ecc333df3ae8fbb72394972d50e5346cc46e7f3f..7307789df2645b0c51cf10b03b4089b5ba2fade3 100644 (file)
@@ -77,9 +77,10 @@ Appendices
 @section Overview
 @cindex Overview
 
-The SFrame stack trace information is provided in a loaded section, known as the
-@code{.sframe} section.  When available, the @code{.sframe} section appears in
-a new segment of its own, PT_GNU_SFRAME.
+The SFrame stack trace information is provided in a loaded section, known as
+the @code{.sframe} section.  When available, the @code{.sframe} section appears
+in segment of type PT_GNU_SFRAME.  An ELF SFrame section will have the type
+SHT_GNU_SFRAME.
 
 The SFrame format is currently supported only for select ABIs, namely, AMD64,
 AAPCS64, and s390x.