From: Indu Bhagat Date: Sat, 12 Jul 2025 06:32:58 +0000 (-0700) Subject: gas: elf: binutils: add new section type SHT_GNU_SFRAME X-Git-Tag: binutils-2_45~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6ab3f09a682a;p=thirdparty%2Fbinutils-gdb.git gas: elf: binutils: add new section type SHT_GNU_SFRAME 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. --- diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c index d74235b030a..b709e590a2d 100644 --- a/bfd/elf-sframe.c +++ b/bfd/elf-sframe.c @@ -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; diff --git a/bfd/elf.c b/bfd/elf.c index 1eba14283f8..ba0e313524d 100644 --- 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; diff --git a/bfd/elflink.c b/bfd/elflink.c index 666399bc680..c4f57cf2f3c 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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) diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 663f40ae7f0..3dc00956eef 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -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; } diff --git a/binutils/readelf.c b/binutils/readelf.c index 573024727f2..87615d95ac1 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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. */ diff --git a/gas/NEWS b/gas/NEWS index 56a2b88d1ea..24b3c8ace0c 100644 --- 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. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 03b6c2470e7..315d08ea996 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -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) { diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 6f8d5912a36..5c63054292f 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -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 index 00000000000..c6ddfba3256 --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.d @@ -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 index 00000000000..ac9c6ca2cf3 --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-1b.s @@ -0,0 +1,3 @@ + .cfi_sections .sframe + .cfi_startproc + .cfi_endproc diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp index 9c5a16f255b..8a424198a88 100644 --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp @@ -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" diff --git a/include/elf/common.h b/include/elf/common.h index f395278b243..0d9a7b7a8a9 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -568,6 +568,7 @@ #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 2ad06e9c124..c37352b89f6 100644 --- 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. diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi index ecc333df3ae..7307789df26 100644 --- a/libsframe/doc/sframe-spec.texi +++ b/libsframe/doc/sframe-spec.texi @@ -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.