Indu Bhagat [Sat, 6 Dec 2025 04:57:30 +0000 (20:57 -0800)]
[SFrame-V3] ld: testsuite: x86: sframe: check link of signal frame and outermost frames
In this test, two "special" case FDEs are linked:
- Signal frame where the SFrame stack trace data is not
respresentable.
- _start like outermost frame function.
This is useful test for sframe_encoder's merge input sections
functionality and its associated write code-paths (sframe_encoder_write)
too.
ld/testsuite/
* ld-x86-64/sframe-link-1.d: New test.
* ld-x86-64/sframe-signal.s: New input file.
* ld-x86-64/sframe-start.s: Likewise.
* ld-x86-64/x86-64.exp: Add new test.
Indu Bhagat [Wed, 3 Dec 2025 23:45:20 +0000 (15:45 -0800)]
[SFrame-V3] ld: discard sframe sections when --no-sframe-info
Mark SFrame sections with SEC_EXCLUDE if --no-sframe-info is in effect.
TBD:
- This does generate an empty .sframe section though! A problem ? No
segment marker PT_GNU_SFRAME is created, which is good
bfd/
* elf-sframe.c (_bfd_elf_parse_sframe): Mark with SEC_EXCLUDE if
--no-sframe-info is in effect.
ld/testsuite/
* ld-x86-64/x86-64.exp: New test.
* ld-x86-64/sframe-command-line-1.d: New test.
Indu Bhagat [Wed, 3 Dec 2025 20:50:33 +0000 (12:50 -0800)]
[SFrame-V3] ld: add --no-sframe-info command line option
Add a new command line option `--no-sframe-info` to the linker. This option
allows users to prevent the linker from generating .sframe sections,
including the linker-generated (internal) SFrame sections for PLT entries.
Previously, the existing `--no-ld-generated-unwind-info` option
controlled whether (not just .eh_frame for PLT entries, but also) SFrame
for PLT entries. This change decouples SFrame from other unwind formats
(like .eh_frame), allowing for more control over the output binary's
SFrame data.
The option is added for architectures that currently support SFrame:
AArch64, s390x, and x86_64.
In a subsequent commit, we will tie this option with discard of all
input .sframe sections.
TBD:
- For aarch64, is adding to both aarch64elf.sh and aarch64linux.sh
necessary? The desired outcome is to allow the new command line for
aarch64 elf, amd64 elf, s390x elf only. Confirm.
bfd/
* elf64-s390.c (elf_s390_create_dynamic_sections): Use
no_ld_sframe_info to guard .sframe section creation.
* elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Likewise.
include/
* bfdlink.h (struct bfd_link_info): Add no_ld_sframe_info bitfield.
ld/
* ldlex.h (enum option_values): Add OPTION_NO_LD_SFRAME_INFO.
* lexsup.c (elf_sframe_list_options): New function.
(ld_list_options): Add sframe_info argument. Update callers.
* emulparams/sframe_info.sh: New file.
* emulparams/aarch64elf.sh: Source sframe_info.sh.
* emulparams/aarch64linux.sh: Likewise.
* emulparams/elf64_s390.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* Makefile.am: Update to handle sframe_info.sh and new list options.
* configure.ac: Handle SFRAME_INFO target variable.
* Makefile.in: Regenerate.
* configure: Regenerate.
Indu Bhagat [Mon, 24 Nov 2025 20:16:05 +0000 (12:16 -0800)]
[SFrame-V3] gas: sframe: doc: testsuite: add new command line option --gsframe-3
This option will allow users to select emission of SFrame stack trace
information as per the SFrame version 3 specification. Currenly, SFrame
version 3 is also the default.
In future, as SFrame evolves, similar command line args may be added for
future versions.
gas/
* as.c (enum gen_sframe_version): New definition.
(parse_args): Add option processing for --gsframe-3.
* as.h (enum gen_sframe_version): New declaration.
* doc/as.texi: Document the new option.
* gen-sframe.c (sframe_set_version): Use enum gen_sframe_version
as version.
(output_sframe): Likewise.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: New test.
* gas/cfi-sframe/cfi-sframe-common-1d.d: Test new command line
option --gsframe-3.
* gas/cfi-sframe/cfi-sframe-common-1d.s: Likewise.
Indu Bhagat [Sat, 22 Nov 2025 01:00:42 +0000 (17:00 -0800)]
[SFrame-V3] include: gas: libsframe: split FDE into desc and attr
This patch introduces a structural change to the SFrame V3 format. It
splits the Function Descriptor Entry (FDE) into two distinct parts to
optimize the binary search table and data organization:
- FDE Descriptor (sframe_func_desc_entry_v3): This structure is stripped
down to contain only the essential indexing information: the function
start address, size, and the offset to the Frame Row Entries (FREs).
This reduces the size of the entry in the FDE index table.
- FDE Attributes (sframe_func_desc_attr_v3): The metadata regarding the
function (number of FREs, FDE type, other data in func_info2, and
repetition block size) is moved to a new structure.
On-Disk Layout: In V3, the "Attributes" are now stored immediately
preceding the FREs for that function. The sfde_func_start_fre_off now
points to the attr structure, and the actual FREs follow immediately
after. IOW, the "Attributes" are now moved to the FRE sub-section,
located immediately preceding the FREs for the respective function.
The read/write paths in sframe.c are updated to account for this
indirection.
sframe_fde_tbl_init now requires access to the FRE buffer to populate
the internal FDE table, as the attributes are no longer resident in the
FDE section.
flip_sframe is refactored into version-specific handlers (_v2 and _v3)
because the endian-swapping logic now differs significantly. In V3, the
iterator must jump from the FDE table to the FRE section to swap the
attributes.
Lastly, the two entities generating SFrame sections (GAS and GNU ld)
both now must _not_ set the sfde_func_start_fre_off to zero, when the
number of FREs is zero. This is because now there will be some valid
attr data at that location.
Backward Compatibility: Due to the need to support readelf/objdump for
SFrame V2 sections, the patch explicitly maintains V2 support via
separate code paths (e.g., flip_sframe_fdes_with_fres_v2)
include/
* sframe.h (sframe_func_desc_entry_v3): Remove sfde_func_num_fres,
sfde_func_info, sfde_func_info2, and sfde_func_rep_size.
(sframe_func_desc_attr_v3): New structure to hold moved fields.
libsframe/
* sframe.c (sframe_fde_tbl_init): Add argument for FRE buffer.
Read attributes from the FRE section for V3.
(flip_fde_desc): Rename from flip_fde. Check size against
sframe_func_desc_entry_v3.
(flip_fde_attr_v3): New function.
(sframe_decode_fde_desc_v2): New function extracted from
sframe_decode_fde.
(sframe_decode_fde_desc_v3): New function.
(sframe_decode_fde_attr_v3): New function.
(flip_sframe_fdes_with_fres_v2): New function for V2 flipping.
(flip_sframe_fdes_with_fres_v3): New function for V3 flipping.
(flip_sframe): Dispatch to version-specific flip functions.
(sframe_decode): Pass FRE buffer to sframe_fde_tbl_init.
(sframe_find_fre): Skip attribute size to find FREs in V3.
(sframe_decoder_get_fre): Likewise.
(sframe_decoder_get_fres_buf): Likewise.
(sframe_encoder_add_fre): Add attribute size to byte count.
(sframe_encoder_add_fres_buf): Read attributes from buffer.
(sframe_encoder_write_fde): Write only FDE index fields.
(sframe_encoder_write_func_attr): New function.
(sframe_encoder_write_sframe): Write FDE attributes before FREs.
gas/
* gen-sframe.c (output_sframe_funcdesc): Do not reset
sfde_func_start_fre_off to zero when zero num FREs.
(output_sframe_func_desc_attr): New refactored out function.
(output_sframe_internal): Invoke output_sframe_func_desc_attr.
libsframe/testsuite/
* libsframe.decode/DATA2: Regenerate data file.
Indu Bhagat [Thu, 20 Nov 2025 17:32:32 +0000 (09:32 -0800)]
[SFrame-V3] bfd: ld: sframe: avoid unnecessary decoding of SFrame FREs at link time
At link time, in _bfd_elf_merge_section_sframe (), it suffices to bring
over the function metadata (FDE attr and all FREs) as a blob into the
SFrame encoder object. There is no need to "decode" each SFrame FRE,
only to add them in a serial fashion.
This is an optimization, and not directly related to any SFrame V3
related changes to the specification. This should also bring us a step
closer to supporting SFrame for targets which use linker relaxations.
Removing the need to decode the input FREs can allow the linker to
simply use the available set of FREs from (relocated) contents. Other
changes in the work done at SFrame parse time may also be necessary, but
this brings us just a step closer.
Add two new APIs to accomplish this:
- sframe_decoder_get_fres_buf, and
- sframe_encoder_add_fres_buf
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Get all FRE data
and add it all in bulk.
libsframe/
* libsframe.ver: Add new APIs.
* sframe.c (sframe_buf_fre_entry_size): New internal API to get
size of one SFrame FRE at the indicated buffer location, without
fully "decoding" the SFrame FRE.
(sframe_decoder_get_fres_buf): New definition.
(sframe_encoder_add_fres_buf): New definition.
include/
* sframe-api.h (sframe_decoder_get_fres_buf): New declaration.
(sframe_encoder_add_fres_buf): New declaration.
Indu Bhagat [Sat, 6 Dec 2025 20:50:44 +0000 (12:50 -0800)]
[SFrame-V3] gas: sframe: add handling for .cfi_register for FP and RA
Use SFrame FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
When FP, RA were moved to a general-purpose register, the SFrame
generation previously warned and skipped the FDE (except on S390X). This
patch updates the translator to detect`.cfi_register` for RA (and FP) on
AMD64, tracks the destination register in the SFrame row entry, and
emits the register in the relevant FRE offsets in SFrame FDE type
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
gas/
* gen-sframe.c (output_sframe_row_entry_offsets): Emit register
encoding for RA if tracked.
(sframe_row_entry_initialize): Propagate ra_reg and ra_deref_p.
(sframe_xlate_do_register): Handle .cfi_register for RA/FP on
AMD64 by setting flex_topmost_p and recording the register.
* gen-sframe.h (struct sframe_row_entry): Add ra_reg and
ra_deref_p.
testsuite/gas/
* cfi-sframe/cfi-sframe.exp: Run new test.
* cfi-sframe/cfi-sframe-x86_64-6.d: New test.
* cfi-sframe/cfi-sframe-x86_64-6.s: New test.
Indu Bhagat [Wed, 19 Nov 2025 17:28:02 +0000 (09:28 -0800)]
[SFrame-V3] gas: x86: testsuite: add new testcases for SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
gas/testsuite/
* gas/cfi-sframe/cfi-sframe-x86_64-4.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-4.s: DRAP pattern.
* gas/cfi-sframe/cfi-sframe-x86_64-5.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-5.s: Non SP/FP based CFA.
* gas/cfi-sframe/cfi-sframe.exp: Add new tests.
Indu Bhagat [Sun, 30 Nov 2025 05:14:32 +0000 (21:14 -0800)]
[SFrame-V3] sframe: gas: translate specific CFI directives for SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
This patch updates the SFrame generation in GAS to translate specific CFI
directives into the new SFrame V3 FDE type: SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
The primary goal is to support code patterns where:
- the Canonical Frame Address (CFA) is not defined by a simple offset
from the Stack Pointer (SP) or Frame Pointer (FP), or where the CFA
rule involves a dereference. Such patterns are generated by compilers
for stack realignment (e.g., DRAP on x86_64, or when mixing legacy
codes that keep 4-byte stack alignment with modern codes that keep
16-byte stack alignment for SSE compatibility).
- the Frame Pointer is not defined by a simple offset from the CFA,
but may even involve another register and/or dereferencing.
- the Return Address is not defined by a simple offset from the CFA,
but may even involve another register and/or dereferencing.
Support for non-SP/FP based CFA: Update sframe_xlate_do_def_cfa () and
sframe_xlate_do_def_cfa_register () to detect when a non-SP/FP register
is used for the CFA.
Support for CFA expressions: A vital part of supporting the
above-mentioned cases on AMD64 is support for CFA expressions. Add
sframe_xlate_do_escape_cfa_expr () to parse simple
DW_CFA_def_cfa_expression sequence in .cfi_escape.
Support for FP expressions: Update sframe_xlate_do_escape_expr () to
handle DW_CFA_expression involving `DW_OP_breg6` (rbp) on AMD64,
allowing for tracking of the Frame Pointer when it is saved with a
dereference rule in the DRAP pattern.
The "support" for both CFA expressions and FP expressions is quite
minimal, and is tailored to the most commonly seen occurences generated
by GCC.
Add a helper sframe_fre_reg_encodable_p () to verify if a DWARF register
number can be encoded in the limited bits (5 bits) available in the
SFrame format.
This functionality is currently implemented only for the
SFRAME_ABI_AMD64_ENDIAN_LITTLE ABI. Support for other ABIs may be added
without format version bump, as the necessary specification changes will
already be in place.
gas/
* gen-sframe.c (sframe_fre_reg_encodable_p): New function.
(sframe_xlate_do_def_cfa): Handle non-SP/FP CFA registers by setting
flex_topmost_p for AMD64.
(sframe_xlate_do_def_cfa_register): Likewise.
(sframe_xlate_do_escape_cfa_expr): New function to handle
DW_CFA_def_cfa_expression of specific shapes.
(sframe_xlate_do_escape_expr): Update to handle dereferenced FP rules.
(sframe_xlate_do_cfi_escape): Invoke sframe_xlate_do_escape_cfa_expr ().
Indu Bhagat [Mon, 17 Nov 2025 18:39:14 +0000 (10:39 -0800)]
[SFrame-V3] libsframe: textual dump of fde type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
Refactor the SFrame textual dumper in sframe-dump.c to properly handle
the new FDE type.
In SFrame V2, the textual dumper could afford to be oblivious to the
exact DWARF register number for stack-pointer and frame-pointer
registers in each ABI. This is because a single bit was used to
differentiate between the two (irrespective of the ABI), and the dumper
could easily just use a:
const char *base_reg_str[] = {"fp", "sp"};
to get the register name.
With the introduction of new SFrame FDE type
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME, which carry DWARF register numbers
if applicable. E.g., for some patterns on AMD64, one may see CFA is the
value at 'r10+0'; or FP is the value at 'rbp+8'. For textual dump, we
now need a mapping from:
- the ABI-specific frame-pointer to string "fp"
- the ABI-specific stack-pointer to string "sp"
This is done via the SFRAME_ABI_REG_MAP helper macros and the new
sframe_get_reg_name () API.
For registers other than stack-pointer and frame-pointer, the SFrame
textual dump does not print the register name (say, "rax", but just the
number (i.e., "r0").
Check the func_info2 byte and dispatch the stack frame row entry (FRE)
dumping to the correct function: either dump_sframe_func_fre_simple or
dump_sframe_func_fre_flex_topmost.
libsframe/
* sframe-dump.c (SFRAME_SP): Define mapping from stack-pointer
register number to "sp".
(SFRAME_FP): Define mapping from frame-pointer register number
to "fp".
(SFRAME_ABI_REG_MAP): Helper macro to define per-ABI-arch
mappings.
(sframe_get_reg_name): Helper API to get register name.
(dump_sframe_func_with_fres): Refactor a bit...
(dump_sframe_func_fre_simple): ..into this.
(sframe_format_fre_disp): New definition.
(dump_sframe_func_fre_flex_topmost): Likewise.
(dump_sframe): Allow both SFrame version 2 and version 3.
Indu Bhagat [Mon, 17 Nov 2025 18:36:27 +0000 (10:36 -0800)]
[SFrame-V3] libsframe: testsuite: add new argument to offset access APIs
For FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME, the offsets are not
only laid out differently, they also have different encoding.
Adjust the APIs in libsframe to get stack frame offsets by adding a new
argument type.
ATM, the stack tracer testsuite is not using this newly externalized API
sframe_get_fre_offset. So not exposing this via the libsframe.ver file
is OK for now.
At the moment, like the generation routines in GAS, the textual dump
routines in sframe-dump.c are also unaware of
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME FDE type. In the next commits, these
capabilities will be added.
include/
* sframe-api.h (MAX_NUM_STACK_OFFSETS): Increase the number of
stack offsets to 6 to accommodate the FDE type
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.
(sframe_get_fre_offset): Make extern.
(sframe_fre_get_cfa_offset): Add new arg.
(sframe_fre_get_fp_offset): Likewise.
(sframe_fre_get_ra_offset): Likewise.
libsframe/
* libsframe/sframe-dump.c (dump_sframe_func_with_fres): Pass 0
for FDE type.
* sframe.c (sframe_fre_get_cfa_offset): Handle FDE type.
(sframe_fre_get_fp_offset): Likewise.
(sframe_fre_get_ra_offset): Likewise.
libsframe/testsuite/
* libsframe.find/findfre-1.c: Pass 0 for FDE type.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
Indu Bhagat [Wed, 19 Nov 2025 17:26:47 +0000 (09:26 -0800)]
[SFrame-V3] gas: sframe: output new FDE type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
This patch updates the routines for emission of the new FDE type
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME in the SFrame output section. The
support for generating the flex-topmost-frame FDEs themselves is added
in a subsequent commit.
For flex topmost FDE type, output_sframe_row_entry_offsets () emits two
offsets for RA tracking, irrespective of the ABI/arch, i.e.,
irrespecitve of whether RA-tracking is enabled. This is because, for
flexible topmost frames, RA is allowed "non-standard" recovery rules,
e.g., RA = REG or RA = *(REG+offset). In a follow-up patch, when
handling for .cfi_register RA, REG is added, emission code will be
patched up accodingly.
gas/
* gen-sframe.c (get_fre_num_offsets): Get number of offsets for
SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME fde type as well (new
argument).
(output_sframe_row_entry_offsets): Output the SFrame FREs for
two different cases (fde type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
or the default).
(output_sframe_row_entry): Update caller.
(output_sframe_funcdesc): Emit func type in func_info2 field.
(sframe_xlate_ctx_init): Initialize flex_topmost_p in
translation context object.
(sframe_xlate_ctx_finalize): Likewise.
(sframe_row_entry_initialize): Copy over new data members too.
* gen-sframe.h (struct sframe_row_entry): Add tracking for CFA
dereferencing, frame pointer dereferencing.
(struct sframe_func_entry): Add tracking for flexible topmost
frame.
(struct sframe_xlate_ctx): Likewise.
Indu Bhagat [Tue, 25 Nov 2025 00:27:30 +0000 (16:27 -0800)]
[SFrame-V3] include: sframe: reserve 4 bits for new FDE types
In SFrame V2, the FDE representation caters to the most common cases of
stack trace metadata:
- CFA is SP/FP based,
- FP/RA offsets, if present are CFA based (except some cases in s390x
where reg can be encoded).
Introduce an additional FDE type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME,
which can encode a more flexible set of CFA, FP and RA recovery rules.
Some of the patterns supported include:
- CFA may be non-SP/FP based.
- CFA, FP may encode dereferencing of register after offset adjustment
- RA may be in a non-default register.
The important bit here is that since SFrame does not track all
callee-saved registers, the above-mentioned recovery rules must only be
done for top-most frames (by the stack tracer).
Adding a new FDE type does have implications for a stack tracer in that
it needs to:
- Check the FDE type before interpreting the Stack offsets data.
- If the FDE type is SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME, and the
recovery rules employ the use of any non-SP/FP based register, the
stack tracer must proceed only if it is the topmost frame on stack.
For each of CFA and RA two offsets are always used. The two offsets
represent the information as follows:
- (minimum 8-bit) offset1 to encode register like:
(regnum << 3) | unused << 2 | deref << 1 | reg_p (=1)
- offset2 to encode offset: offset
The offsets are in the usual order: CFA, RA, FP if present.
For example, for FP/RA tracking,
a) If the reg is REG1 for FP/RA tracking,
- Encoding:
+ offset1 to encode register: (REG1 << 3) | unused << 2 | deref << 1 | reg_p (=1)
+ offset2 to encode offset: offset
- Action:
+ if deref, FP/RA = \*(REG1 + offset) (e.g., seen for FP recovery
with certain DRAP patterns on x86_64)
+ if no deref, FP/RA = REG1 + offset
b) If the reg is CFA for FP/RA tracking,
- Encoding:
+ [=Effectively Padding] offset1 to encode register:
(( 0 << 3 ) | unused << 2 | 0 << 1 | reg_p (=0))
+ offset2 to encode offset: offset
- Action:
+ if deref, FP/RA = *(CFA + offset)
+ if no deref, FP/RA = CFA + offset (pattern shouldnt be seen for
RA)
Next for CFA tracking,
- Action:
+ if deref, CFA = *(reg + offset) (e.g., seen for CFA recovery in
some stack realignment patterns on AMD64)
+ if no deref, CFA = reg + offset (e.g., for .cfi_def_cfa 2, 8, or
.cfi_def_cfa 10, 0)
Expected usage of this FDE type is quite low (DRAP on x86_64).
TBD:
- Terminology concern. Up until now, we called the following as FDE
types:
- SFRAME_FDE_TYPE_PCINC
- SFRAME_FDE_TYPE_PCMASK
In hindsight, these should have been referred to as "PC type" for
FDE. Fixup comments and macro etc.
- Cleanup the FDE type terminology from code base.
include/
* sframe.h (SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME): New SFrame FDE
type.
(SFRAME_V3_FUNC_FDE_TYPE_MASK): New constant definition.
(SFRAME_V3_FUNC_INFO2_GET_FDE_TYPE): New macro definition.
(SFRAME_V3_FUNC_INFO2_SET_FDE_TYPE): Likewise.
(SFRAME_V3_FLEX_FDE_REG_ENCODE): Macro to encode register in the
SFrame offset data.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_NUM): New definition.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_DEREF_P): Likewise.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_P): Likewise.
Indu Bhagat [Mon, 10 Nov 2025 22:44:48 +0000 (14:44 -0800)]
[SFrame-V3] include: gas: libsframe: add 8-bits of func_info2 for extensibility in FDE
FDE's func_info field is a key member which is used to convey important
information around the encoding and interpretation of the SFrame FDE and
the function's SFrame FRE information.
Currently there is 1 bit left for AArch64, and 2 bits for AMD64,s390x
(and other future ABIs to be supported). Provision some additional
space now (specifically an additional 8-bits) for future needs for V3
and beyond.
Compared to V2, this now increases the size of SFrame FDE by 1 byte in
V3. In this patch, the additional byte is not used functionally in the
patch. Hence, rather mechanical changes in libsframe, bfd and
libsframe/testsuite accompany.
With the addition of a new byte for additional func info (func_info2),
add a new arg to allow usecases like textual dumper to get all data
members in one API: sframe_decoder_get_funcdesc_v3.
To keep the APIs symmetric looking, add new arg to
sframe_encoder_add_funcdesc_v3 too.
Since bfd uses these APIs too, carry out the mechanical change in the
respective APIs too. And of course, the testsuite which exercises these
APIs.
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Get and set
func_info2.
* elf64-s390.c (_bfd_s390_elf_create_sframe_plt): Pass 0 for
func_info2 for SFrame FDE for PLT.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Likewise.
gas/
* gen-sframe.c (output_sframe_funcdesc): Emit the uint8_t for
func_info2.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres):
* sframe.c (sframe_fde_tbl_init): Handle the new additional
member.
(sframe_encoder_write_fde): Likewise.
* sframe.c (sframe_decoder_get_funcdesc_v3): Update func_info2.
libsframe/testsuite/
* libsframe.decode/DATA2: Update data file with SFrame section
data.
* libsframe.encode/encode-1.c: Pass 0 for func_info2 arg.
* libsframe.find/findfre-1.c: Likewise.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
include/
* sframe.h: Add new uint8_t sfde_func_info2 to
sframe_func_desc_entry_v3.
* sframe-api.h (sframe_decoder_get_funcdesc_v3): New arg.
(sframe_encoder_add_funcdesc_v3): Likewise.
Indu Bhagat [Sun, 7 Dec 2025 04:35:45 +0000 (20:35 -0800)]
[SFrame-V3] gas: sframe: allow SFrame FDEs with 0 FREs for signal frames
Update the SFrame generation logic in GAS to emit Function Descriptor Entries
(FDEs) for signal frames even when no Frame Row Entries (FREs) could be
generated.
Previously, create_sframe_all () would discard any FDE that failed
translation or resulted in zero FREs. However, for signal frames (marked
with .cfi_signal_frame), preserving the FDE may be valuable even without
stack offsets. The presence of the SFrame FDE with the 'Signal'
attribute may allow stack tracers to identify the frame as a signal
trampoline and potentially apply fallback handling, rather than treating
the PC range as having no stack trace info at all.
The patch modifies create_sframe_all () to detect translation errors for
signal frames, effectively allowing the generation of an empty FDE (0 FREs)
marked with the 'S' attribute.
TBD:
- But the warnings are already issued, we may emit SFrame FDE with no
FREs. Somewhat misleading.
gas/
* gen-sframe.c (sframe_fde_free): Add NULL check for safety.
(create_sframe_all): Allow FDEs for signal frames even if translation
encountered errors or produced no FREs.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d: New test ensuring
signal frame FDE is emitted with 0 FREs.
* gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s: New test.
Indu Bhagat [Fri, 24 Oct 2025 16:39:15 +0000 (09:39 -0700)]
[SFrame-V3] sframe: gas: bfd: add support for signal frames
Reserve a bit in function info byte in the SFrame FDE to designate
signal frames.
Also update the SFrame opt code in GAS and dumping routines in libsframe
to handle signal frame bit.
include/
* sframe.h (SFRAME_V3_FUNC_SIGNAL_P): Extract signal frame bit.
(SFRAME_V3_FUNC_INFO_UPDATE_SIGNAL_P): Set signal frame bit.
gas/
* gen-sframe.c (get_dw_fde_signal_p): New function to retrieve signal
frame state from DWARF FDE.
(sframe_v3_set_func_info): Renamed from sframe_v1_set_func_info.
Accept signal_p argument and encode it.
(sframe_set_version): Update ops to use sframe_v3_set_func_info.
(sframe_set_func_info): Pass signal_p to the ops hook.
(output_sframe_funcdesc): Retrieve signal frame marker and pass to
sframe_set_func_info.
* gen-sframe.h (struct sframe_version_ops): Update set_func_info
signature.
* sframe-opt.c (sframe_convert_frag): Preserve signal_p bit during
fragment conversion.
libsframe/testsuite/
* gas/cfi-sframe/cfi-sframe-common-13.d: New test.
* gas/cfi-sframe/cfi-sframe-common-13.s: New test.
* gas/cfi-sframe/cfi-sframe.exp: Run new test.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres): Decode signal frame bit
and print "S" attribute in the dump output.
Indu Bhagat [Tue, 28 Oct 2025 08:39:55 +0000 (01:39 -0700)]
[SFrame-V3] include: libsframe: bfd: gas: testsuite: support for signed 64-bit offset in SFrame FDE
This change enables support text > 2 GiB in SFrame format.
Each SFrame FDE needs to hold information about the start PC of the
function it pertains to. Currently, the field 'sfde_func_start_address'
in SFrame FDE is encoded as a 32-bit offset to the start PC of the
function from the field itself.
In SFrame V2, this offset was a signed 32-bit offset. The signedness
gives the flexibility of having .sframe ELF section before or after the
.text* sections. But the size of 32-bit puts the limitation that
.sframe togther with the .text* sections must fit the 2 GiB range.
Currently, if the linker sees the offset not representable as 32-bit
signed offset, it issues an error (not seen in the wild, simulated by
forcing a function to align via an '.align 2147483648' directive):
test.o:(.sframe+0x1c): relocation truncated to fit: R_X86_64_PC32 against `.text'
make: *** [Makefile:7: all] Error 1
ATM, EH Frame also suffers with the same issue.
Moving forward, some cloud applications have been shown to be nearing
1.5 GiB threshold. Extending the offset to int64_t now seems to be good
choice to make now for future-proof'ing the sections.
The use of int64_t offset is done for all SFrame V3 sections. This
bump from int32_t to int64_t should not lead to an increase in the size
of SFrame sections, because of the following additional changes to the
SFrame FDE specification:
- Reduce the type of sfde_func_num_fres (from uint32_t to uint16_t)
- Remove the 2 bytes of padding (sfde_func_padding2). These served the
two-fold purpose of keeping FDE data aligned _and_ unused space for
future needs.
Now that the offset is int64_t, start using the
sframe_decoder_get_funcdesc_v3 () instead of
sframe_decoder_get_funcdesc_v2 () in GNU ld.
This patch changes the offset type in the SFrame FDE definition to an
int64_t. No further changes in gas are necessary because the code
already accounts for writing out as per the size of the member of the
struct:
bfd/
* elf-sframe.c (sframe_read_value): Signed offset for start PC
is 8-bytes now.
(_bfd_elf_merge_section_sframe): Likewise.
* elf64-s390.c (_bfd_s390_elf_create_sframe_plt): Use V3 API.
(elf_s390_finish_dynamic_sections): Signed offset for start PC
is 8-bytes now.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Use V3 API.
(_bfd_x86_elf_finish_dynamic_sections): Signed offset for start
PC is 8-bytes now.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres): Use int64_t.
* sframe.c (sframe_decoder_get_secrel_func_start_addr): Likewise.
(sframe_fre_check_range_p): Likewise.
(sframe_find_fre): Likewise.
(sframe_encoder_add_funcdesc): Likewise.
(sframe_encoder_write_fde): Write out int64_t now.
libsframe/testsuite/
* libsframe.decode/DATA2: Regenerate the data file.
* libsframe.encode/encode-1.c: Use int64_t for start pc offset.
* libsframe.find/findfre-1.c: Likewise.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
include/
* sframe-api.h (sframe_find_fre): Update arg type to int64_t.
(sframe_encoder_add_funcdesc): Likewise.
* sframe.h: Change data type to int64_t.
Indu Bhagat [Fri, 28 Nov 2025 20:31:17 +0000 (12:31 -0800)]
[SFrame-V3] sframe: gas: libsframe: remove padding field from FDE
Remove the unused sfde_func_padding2 member from the
sframe_func_desc_entry_v3 structure.
A later patch in this series reorganizes the members of the FDE
structure in a way explicit padding is no longer necessary to keep
natural alignment. So remove the explicit padding now.
Indu Bhagat [Fri, 28 Nov 2025 19:50:14 +0000 (11:50 -0800)]
[SFrame-V3] sframe: gas: libsframe: use uint16_t for num_fres of FDE
Reduce the size of the num_fres field in the Function Descriptor Entry
(FDE) from 32 bits to 16 bits.
The number of Frame Row Entries (FREs) for a single function is extremely
unlikely to exceed 65,535 in real-world scenarios. Reducing this field
saves 2 bytes per FDE, contributing to a smaller overall SFrame section size.
(BTW, these savings will be eaten up by a later commit which adds
support for text > 2 GiB by increasing an offset from int32_t to
int64_t).
Safety checks are added to the assembler to warn and skip SFrame FDE
generation if a function's FRE count exceeds UINT16_MAX.
include/
* sframe.h (sframe_func_desc_entry_v3): Change sfde_func_num_fres
type to uint16_t.
gas/
* gen-sframe.c (output_sframe_funcdesc): Write 2 bytes for num_fres
and assert it fits in uint16_t.
(sframe_do_fde): Add check to skip FDE emission if num_fres exceeds
UINT16_MAX.
libsframe/
* sframe.c (sframe_fde_tbl_init): Cast num_fres to uint16_t.
(sframe_decode_fde): Likewise.
(sframe_encoder_write_fde): Likewise.
* testsuite/libsframe.decode/DATA2: Update binary test data.
Indu Bhagat [Wed, 13 Aug 2025 00:13:15 +0000 (17:13 -0700)]
[SFrame-V3] libsframe: add V3 APIs for adding and getting SFrame FDE
(Similar to V2) Add two new APIs for adding and getting SFrame FDE:
- sframe_encoder_add_funcdesc_v3
- sframe_decoder_get_funcdesc_v3
Note the argument for the function start address is int64_t instead of
int32_t (the latter is used in sframe_encoder_add_funcdesc_v2 and
sframe_encoder_get_funcdesc_v2). The new V3 APIs will be used in a
subsequent commit to extend SFrame V3 to support text > 2 GiB by
allowing int64_t offsets by default.
Similar to the analogous V2 APIs, they return 0 on success and
SFRAME_ERR on failure.
include/
* sframe-api.h (sframe_decoder_get_funcdesc_v3): New
declaration.
(sframe_encoder_add_funcdesc_v3): Likewise.
libsframe/
* libsframe.ver: Add the new APIs.
* sframe.c (sframe_decoder_get_funcdesc_v3): New definition.
(sframe_encoder_add_funcdesc_v3): Likewise.
Indu Bhagat [Fri, 24 Oct 2025 16:39:08 +0000 (09:39 -0700)]
[SFrame-V3] libsframe: bump so version to libsframe.so.3.0.0
Consolidate the 2.0 and 2.1 nodes into a new 3.0 node.
In subsequent patches for releasing SFrame V3, libsframe APIs will be
affected. A non-exhaustive list of noteworthy changes are mentioned
next.
Some existing APIs (breaking binary compatibility) by adding an
additional arg to these:
- sframe_fre_get_ra_offset
- sframe_fre_get_fp_offset
- sframe_fre_get_cfa_offset
Change of argument type:
- sframe_find_fre
The behaviour of some APIs will change:
- sframe_encoder_write now writes out V3.
And lastly removal of two APIs:
- sframe_decoder_get_funcdesc
- sframe_encoder_add_funcdesc
Above make this release of the library binary incompatible with previous
release, hence a version bump and new version node 3.0.
TBD:
- Test versioning of the minimum impacted set instead.
libsframe/
* libsframe.ver: Create a new 3.0 node. Remove the 2.0 node.
* libtool-version: Bump the so version.
Indu Bhagat [Fri, 24 Oct 2025 16:39:01 +0000 (09:39 -0700)]
[SFrame-V3] sframe: gas: bfd: ld: format bump to version 3
Bump version to SFRAME_VERSION_3. Introduce a new definition of SFrame
FDE for version 3, which is a duplicate of SFrame FDE in V2, for now.
In other words, no changes to the format specification yet.
GNU as emits SFrame V3 by default. SFrame encoder (ld) emits SFrame V3
sections. In a later commit, we will add a new command line option to
gas: --gsframe-3 which will bind the implementation in gas to emit
SFrame V3.
Also, adjust the testcases for the new version string
"SFRAME_VERSION_3".
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Linker emits
the latest version by default.
* elf64-s390.c (_bfd_s390_elf_create_sframe_plt): Linker emitted
PLT sections are also SFRAME_VERSION_3.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Likewise.
gas/
* gen-sframe.c (sframe_set_version): GAS emits SFrame V3 by
default.
(output_sframe): Likewise.
include/ChangeLog:
* sframe.h (SFRAME_VERSION_3): New definition.
(SFRAME_VERSION): Current version is now SFRAME_VERSION_3.
(SFRAME_V3_FUNC_INFO): New definition.
(SFRAME_V3_FUNC_FRE_TYPE): Likewise.
(SFRAME_V3_FUNC_FDE_TYPE): Likewise.
(SFRAME_V3_FUNC_PAUTH_KEY): Likewise.
(SFRAME_V3_FUNC_INFO_UPDATE_PAUTH_KEY): Likewise.
binutils/testsuite/
* all affected tests: Replace SFRAME_VERSION_2 with
SFRAME_VERSION_3.
gas/testsuite/
* all affected tests: Likewise.
ld/testsuite/
* all affected tests: Likewise.
libsframe/testsuite/
* all affected tests: Likewise.
Indu Bhagat [Fri, 14 Nov 2025 23:49:38 +0000 (15:49 -0800)]
[SFrame-V3] sframe: use const for sframe_decoder_ctx object arg
As the library version will be bumped soon, include this change now.
Note the arg names in sframe-dump.c APIs have 'sfd_ctx' instead of the
usual 'dctx'. We can address this cosmetic change at a later time.
Other cosmetic changes, e.g. to make fixing function-level comments more
consistent, are left out of the patch for now.
Additionally, constify the return type of static function
sframe_decoder_get_header, now that the call sites consistently use a
const object.
Indu Bhagat [Mon, 3 Nov 2025 08:17:41 +0000 (00:17 -0800)]
[SFrame-V3] libsframe: remove old sframe_decoder_get_funcdesc API
sframe_decoder_get_funcdesc () was added for SFRAME_VERSION_1. This has
since been obsoleted by introduction of SFRAME_VERSION_2 and its
corresponding sframe_decoder_get_funcdesc_v2 API.
Remove from the version script file as well. We will bump the version
of the library to 3.0.0 in a subsequent patch (closer to release) and
consolidate the entries into a new LIBSFRAME_3.0 node.
Indu Bhagat [Fri, 5 Dec 2025 09:29:47 +0000 (01:29 -0800)]
[SFrame-V3] libsframe: testsuite: add a new test for SFrame V2
The existing frecnt-2.c testcase reads the SFrame section from the
provided DATA2 buffer. It exercises the sframe_decode (),
sframe_decoder_get_num_fidx (), and sframe_decoder_get_funcdesc_v2 ()
APIs. Currently DATA2 file is the SFrame section created from the test
input (mentioned in the comments in the file) in SFrame version 2.
Moving forward, creating SFrame V2 section via GNU assembler and GNU ld
will not be supported. But textual dump of SFrame V2 sections via
readelf/objdump will need to be supported. Add a test similar to
frecnt-2.c using SFrame version 2 binary data to the libsframe
testsuite. Such a test will help ensure that sframe_decode () and
related APIs remain tested for multiple supported arches till the
support for V2 sections is to be maintained.
Duplicate frecnt-2.c to create a frecnt-v2.c, the latter will test with
a SFrame V2 input section.
libsframe/
* Makefile.in: Regenerated.
libsframe/testsuite/
* libsframe.decode/decode.exp: Likewise/
* libsframe.decode/local.mk: Likewise
* libsframe.decode/DATA-V2: New SFrame V2 test data file.
* libsframe.decode/frecnt-v2.c: New test.
Indu Bhagat [Fri, 5 Dec 2025 20:24:30 +0000 (12:24 -0800)]
[SFrame-V3] readelf: testsuite: sframe: add new SFrame V2 test
In subsequent commits, we will add support for SFrame V3. GNU as and ld
will only generate SFrame V3; SFrame V2 will not be supported for
generation.
For readelf/objdump, however, continue to support textual dump of SFrame
V2 sections. Add a binary file (with no debug data) with SFrame V2
section to keep the dumping tested.
TBD:
- The cmp file should ideally be a set of regexp checks.
binutils/testsuite/
* binutils-all/x86-64/sframe.exp: New test.
* binutils-all/x86-64/test-v2.sframe.bz2: New test.
* binutils-all/x86-64/test-v2-ET_EXEC.sframe.bz2: New test.
* binutils-all/x86-64/test-v2-ET_EXEC.sframe.dump: New test.
* binutils-all/x86-64/test-v2-ET_REL.sframe.bz2: New test.
* binutils-all/x86-64/test-v2-ET_REL.sframe.dump: New test.
Indu Bhagat [Thu, 20 Nov 2025 20:09:00 +0000 (12:09 -0800)]
libsframe: refactor out sframe_fre_grow_tbl
Usage of a global int number_of_entries is likely unnecessary. The same
global is used for growing the FDE tbl too, when adding FDEs. At the
moment, however, carve out a new function to grow the FRE table, and
use a macro instead of 'number_of_entries'.
This refactoring helps provide basis for a later patch where we add
SFrame FREs in bulk instead of one at a time to the SFrame encoder
object.
libsframe/
* sframe.c (SFRAME_FRE_ALLOC_LEN): New definition.
(sframe_grow_fre_tbl): New definition.
(sframe_encoder_add_fre): Use the new function.
---
[Changes in V2]
- Minor code comment adjustment.
[End of changes in v2]
Indu Bhagat [Sat, 8 Nov 2025 22:02:05 +0000 (14:02 -0800)]
libsframe: refactor sframe_decoder_add_funcdesc for internal use
sframe_encoder_add_funcdesc () was added for SFRAME_VERSION_1. This has
since been obsoleted by introduction of SFRAME_VERSION_2 and its
corresponding sframe_decoder_add_funcdesc_v2 API.
Refactor the functionality into an internal-only API:
sframe_encoder_add_funcdesc_internal (). Ensure it returns the error
code for the caller to take necessary action or pass to user.
Keep only two args for sframe_encoder_add_funcdesc: function size and
function start addr. This simple barebone API will be used in a
subsequent commit to adjust the link-time behaviour of SFrame sections.
libsframe/
* sframe.c (sframe_encoder_add_funcdesc): Refactor out into
sframe_encoder_add_funcdesc_internal. Change args.
(sframe_encoder_add_funcdesc_v2): Use the new internal API.
---
[Changes in V2]
- Use only two args for the sframe_encoder_add_funcdesc_internal
[End of changes in V2]
Indu Bhagat [Thu, 13 Nov 2025 21:16:52 +0000 (13:16 -0800)]
gas: sframe: refactor out the offsets emission code
Minor refactoring. Carve out the SFrame FRE offsets emission code into
a new output_sframe_row_entry_offsets (). This change helps prepare for
later supporting a new FDE type in SFrame V3.
gas/
* gen-sframe.c (output_sframe_row_entry_offsets): New
definition.
(output_sframe_row_entry): Use the new definition.
Indu Bhagat [Fri, 31 Oct 2025 22:35:52 +0000 (15:35 -0700)]
gas: sframe: add new sframe_xlate_ctx_get_cur_cfa_reg
Purely cosmetic change.
gas/
* gen-sframe.c (sframe_xlate_ctx_get_cur_cfa_reg): New
definition.
(sframe_xlate_do_def_cfa_offset): Use it.
(sframe_xlate_do_escape_expr): Likewise.
(sframe_xlate_do_escape_gnu_args_size): Likewise.
---
Note:
- This change was initially thought to be useful refactoring for a
SFrame V3 patch, but currently this is not used by any following
patch in the near future...
Indu Bhagat [Thu, 16 Oct 2025 18:41:19 +0000 (11:41 -0700)]
include: sframe: add SFRAME_V2_ prefixed macro names for FDE
Such a change for readability only. SFrame V1 is now obsolete, and with
newer versions like V3 or later, its likely better to have macro names
reflect the applicable version.
Add new macro names for FDE information related macros.
Indu Bhagat [Wed, 22 Oct 2025 23:29:48 +0000 (16:29 -0700)]
libsframe: implement an internal-only SFrame FDE representation
Up until now, libsframe has used the same SFrame FDE representation as
the on-disk representation (sframe_func_desc_entry). The choice made by
the author of the libary, back when it was first contributed, perhaps
sufficed the needs then. But looking forward, we need to be able to
allow reading and dumping out of not just sections with version
SFRAME_VERSION_2 but also future supported versions.
Note that libsframe did not expose the SFrame FDE representation in any
public APIs; doing so is not recommended.
For the path forward, create an internal-only SFrame FDE representation
(sframe_func_desc_entry_int). libsframe now keeps all in-memory FDEs of
type sframe_func_desc_entry_int. Doing so means instead of memcpy, we
need to resort to member-by-member mapping. This can be seen in
sframe_fde_tbl_init (read time) and the new function
sframe_encoder_write_fde (write time).
Other than that, replace out the previous direct interaction with
on-disk format when:
- flipping SFrame contents before decoding them in sframe_decode.
- flipping SFrame contents before writing them out in sframe_encode.
Indu Bhagat [Wed, 22 Oct 2025 23:29:38 +0000 (16:29 -0700)]
include: gas: bfd: sframe: clean the abstraction
... between specification and implmentation.
Move to definition in the implementation (gas/ld/libsframe) and not the
specification (include/sframe.h). At this time the implementation in
gas and ld generate the sections in the latest SFrame version only.
Indu Bhagat [Fri, 14 Nov 2025 18:15:15 +0000 (10:15 -0800)]
gas: sframe: ignore .cfi_offset for RA selectively
For ABIs not tracking RA (e.g., AMD64), the return address is expected
to be in a specific location (usually a fixed offset from CFA on stack).
Explicit manourvering to a different offset may be non-representable in
SFrame, and should not be simply ignored.
Although such patterns are not usually seen in the wild, it is more
correct to catch them if at all they manifest.
gas/
* gen-sframe.c (sframe_xlate_do_offset): Do not ignore
.cfi_offset for RA all the time.
Indu Bhagat [Fri, 14 Nov 2025 07:01:36 +0000 (23:01 -0800)]
gas: sframe: testsuite: add testcase for .cfi_register RA
PS: Adding a testcase is not strictly necessary now. Once the SFrame V3
patches are in, this testcase will need to be reverted. SFrame V3
allows a new FDE type where .cfi_register RA may be represented.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-5.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-5.s: New test.
---
[Changes in V2]
- Add a clear note in commit log that this patch is eventually
reverted after SFrame V3 make it in.
- I am inclining towards not putting this in.
[End of changes in V2]
gas: Don't skip SFrame FDE if .cfi_register specifies RA w/o tracking
Do not skip SFrame FDE if .cfi_register specifies RA register without
RA tracking being actually used. Without RA tracking the register
contents can always be restored from the stack using the fixed
RA offset from CFA.
Even for ABI/arch without RA tracking, there may be instances where user
may specify '.cfi_register RA, reg'. This needs to be caught, skipping
this from SFrame generation may not be correct. This may be done in
certain hand-written asm sequences where the user needs to manipulate
the return to a certain function.
A later commit will add a testcase for documentation purposes.
Tom de Vries [Mon, 8 Dec 2025 15:38:28 +0000 (16:38 +0100)]
[gdb/testsuite] Fix FAIL in gdb.multi/remote-with-running-inferior.exp
Occasionally, with test-case gdb.multi/remote-with-running-inferior.exp I run
into:
...
(gdb) continue^M
Continuing.^M
^M
Thread 1.1 "remote-with-run" hit Breakpoint 1.1, main () at \
remote-with-running-inferior.c:31^M
31 for (int i = 0; i < 30; ++i)^M
(gdb) PASS: $exp: target_non_stop=auto: non_stop=off: \
continue to breakpoint: continue to breakpoint in breakpt
bt 1^M
(gdb) FAIL: $exp: target_non_stop=auto: non_stop=off: \
check inferior 1 is in breakpt
...
The problem is a race between:
- inferior 1 reaching main, and
- gdb setting a breakpoint on main.
If the breakpoint on main is set before inferior 1 reaches main, the
breakpoint triggers for inferior 1, which the test-case doesn't expect.
Fix this by setting the breakpoint on main only for inferior 2.
Andrew Burgess [Thu, 23 Oct 2025 15:34:20 +0000 (16:34 +0100)]
gdbsupport: remove undefined behaviour from (forward_)scope_exit
Our implementation of scope_exit and forward_scope_exit make use of
the Curiously Recurring Template Pattern (CRTP) to provide the
"release" functionality, this is done in the scope_exit_base class in
scope-exit.h.
The interesting (for this commit) parts of scope_exit_base look like
this:
~scope_exit_base ()
{
if (!m_released)
{
auto *self = static_cast<CRTP *> (this);
self->on_exit ();
}
}
... snip ...
};
By the time ~scope_exit_base is called the destructor for the derived
class (called CRTP here) has already been run, which means any data
members in the derived class will have also have had their destructors
run. As a result of this I believe that casting 'this' to the derived
type, and then calling the on_exit method is undefined behaviour, as
'this' can no longer be considered a valid instance of CRTP (the CRTP
part has been destructed).
In reality, the memory for the derived type is not reclaimed until
after ~scope_exit_base has finished, so as long as the data members of
the derived type are Plain Old Data (POD), then the current code
should be just fine; any data members of the derived class will remain
in place, and untouched, until ~scope_exit_base has completed.
But still, I don't think we should rely on undefined behaviour.
I actually ran into this when, in another series, I tried to reuse
scope_exit_base with a class where a data member was not POD, and in
this case GDB would crash because my new on_exit function was making
use of the non-POD data member after it had been destructed, and
resources released.
I propose that we move away from the CRTP, and instead flip the class
hierarchy. Instead of derived classes like scope_exit inheriting from
scope_exit_base, scope_exit_base should inherit from scope_exit.
What this means, is that when ~scope_exit_base is called, ~scope_exit
will not yet have been run, and the data members of scope_exit will
still be valid.
To allow the existing names to be used, the plan is that the existing
scope_exit and forward_scope_exit classes are renamed to
scope_exit_policy and forward_scope_exit_policy. These policy classes
will then be injected via a template argument as the base class for
scope_exit_base. Finally, we can:
template<typename EF>
using scope_exit = scope_exit_base<scope_exit_policy<EF>>;
which defines the scope_exit type. This type is a drop in replacement
with all of GDB's existing code, but avoids the undefined behaviour.
We can do something similar with forward_scope_exit.
There should be no user visible changes after this commit.
Starting in C23, strchr and strrchr will return const char *, if fed a
const char *. This means that several files in the BFD directory will
fail to build as they are assigning the return of those functions to a
char *.
Fix this by const-ifying several variables. The only place where that
wasn't just that was in targets.c, where a variable was being used in
subsequent strrchr invocations to change the underlying string, so a new
variable had to be introduced.
No user-visible change should happen after this commit.
Guinevere Larsen [Thu, 30 Oct 2025 20:43:55 +0000 (17:43 -0300)]
gdb/record_full: add ptid entry for history.
For record full to work on multi-threaded inferiors, we must know to
which thread any given recorded instruction belongs to. This commit adds
this as a new entry for each instruction when an inferior is
multi-threaded. This way, when replaying the instruction, the subsystem
is able to change inferior thread as needed, and avoid SIGILLs when
changing stuff
Ideally, we would only add the PTID entry when we actually need to
switch threads, but that is left as a future improvement.
WIP: replaying doesn't automatically change threads yet, but there was
an attempt
PR 33676 ld segfaults when using binary input inside NOLOAD
The code at ldlang.c:2840-2841 checks if the output BFD is ELF format,
then unconditionally uses elf_section_type() on the input section
without verifying the input section is also ELF format.
This was introduced in commit d87be451e (PR ld/32787) which added
special handling for NOLOAD note sections.
PR 33676
PR 32787
* ldlang.c (lang_add_section): Check section owner's BFD
flavour before using elf_section_type.
Alan Modra [Mon, 8 Dec 2025 05:30:16 +0000 (16:00 +1030)]
PR 33698 and PR 33700
It is possible for dump_relocations to return on an error from
slurp_rela_relocs or slurp_rel_relocs without writing to
"all_relocations". In that case an uninitialised r_symbol is passed
to free at the end of process_got_section_contents.
Tom de Vries [Mon, 8 Dec 2025 08:30:25 +0000 (09:30 +0100)]
[gdb/build] Re-add *.[ch] in gdb.pot
In commit 4a40fe05bf0 ("[gdb/build] Handle gdbsupport and gdbserver in
gdb.pot"), in order to handle '*.cc' files I did:
...
- -name '*.[hc]' -print
+ -name '*.[hc]' -o -name '*.cc' -print
...
but failed to understand that this no longer printed the '*.[hc]' names.
Fix this by adding a '-print' for '*.[hc]'.
Tested by doing:
...
$ cd build/gdb
$ make po/gdb.pot
...
$ grep -c symtab.c po/gdb.pot
102
...
H.J. Lu [Sat, 6 Dec 2025 02:17:39 +0000 (10:17 +0800)]
elf: Add SHT_SUNW_ctf and SHT_SUNW_symnsort
On Solaris 11.4, there is SHT_SUNW_symnsort and no SHT_SUNW_symtabnsort.
SHT_SUNW_symnsort is defined to 0x6fffffec, which is the same as
SHT_SUNW_symtabnsort. There is also SHT_SUNW_ctf. Add SHT_SUNW_ctf and
rename SHT_SUNW_symtabnsort to SHT_SUNW_symnsort. Move SHT_SUNW_phname
after SHT_SUNW_symnsort.
binutils/
* readelf.c (get_solaris_section_type): Add SHT_SUNW_ctf and
SHT_SUNW_symnsort. Move SHT_SUNW_phname after SHT_SUNW_symnsort.
Remove SHT_SUNW_symtabnsort.
include/
* elf/common.h (SHT_SUNW_ctf): New.
(SHT_SUNW_symtabnsort): Renamed to ...
(SHT_SUNW_symnsort): This.
(SHT_SUNW_phname): Moved after SHT_SUNW_symnsort.
Tom Tromey [Fri, 5 Dec 2025 18:43:08 +0000 (11:43 -0700)]
Unconditionally pass is_a_field_of_this in c-exp.y
In a review to a different patch of mine, Simon asked for this change.
The idea here is that there's no need to pass null as the "field of
this" parameter, as lookup_language_this checks the language anyway.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Tom de Vries [Sun, 7 Dec 2025 09:59:54 +0000 (10:59 +0100)]
[gdb/contrib] Check clean files in check-whitespace-pre-commit.sh
The pre-commit check check-whitespace checks diffs.
Consequently, we detect something like this:
...
$ echo >> gdb/testsuite/lib/gdb.exp
$ git commit -a -m trailing-empty-line
...
check-whitespace.........................................................Failed
- hook id: check-whitespace
- duration: 0.01s
- exit code: 2
gdb/testsuite/lib/gdb.exp:11717: new blank line at EOF.
...
But say we work around the failing check using --no-verify, then we no longer
detect it after the commit has succeeded:
...
$ git commit -a -m trailing-empty-line --no-verify
[detached HEAD e6302105522] trailing-empty-line
1 file changed, 1 insertion(+)
$ pre-commit run --all-files check-whitespace
check-whitespace.........................................................Passed
- hook id: check-whitespace
- duration: 0.3s
...
Fix this in check-whitespace-pre-commit.sh by distinguishing between clean and
other files. Doing so is easier to do in a more advanced scripting language,
so rewrite into python.
Since a recent commit, gdb/testsuite is clean, so I'm using that as
simple classifier for now.
For the other files we do what we did before, and check just the staging area:
...
$ git --no-pager diff --staged --check "${other[@]}"
...
But for clean files, we check the entire file, including staged changes:
...
$ empty=$(git hash-object -t tree /dev/null)
$ git diff-index --cached --check $empty "${clean[@]}"
...
Consequently, we do see:
...
$ git commit -a -m trailing-empty-line --no-verify
[detached HEAD e6302105522] trailing-empty-line
1 file changed, 1 insertion(+)
$ pre-commit run --all-files check-whitespace
check-whitespace.........................................................Failed
- hook id: check-whitespace
- duration: 0.64s
- exit code: 2
gdb/testsuite/lib/gdb.exp:11717: new blank line at EOF.
...
elf: Renumber local dynamic symbols only if needed
caused regressions for hppa64-linux which adds local dynamic symbols,
__text_seg and __data_seg in elf64_hppa_late_size_sections. Set
has_local_dynsyms to true when adding __text_seg and __data_seg.
* elf64-hppa.c (elf64_hppa_late_size_sections): Set
has_local_dynsyms to true when adding __text_seg and __data_seg.
Andrew Burgess [Mon, 17 Nov 2025 14:08:57 +0000 (14:08 +0000)]
gdb: display a symbol more often in multi-file list output
I noticed that when a command line 'list foo.c:10' displays multiple
files, the symbol would always be shown as "???", e.g.:
file: "/tmp/foo.c", line number: 10, symbol: "???"
this is because, when the symtab_and_line is created for the
'foo.c:10', the pc and symbol are never filled in.
In this commit, I propose that, when we decide that the above header
line needs to be printed, we should attempt to lookup a symbol for the
relevant line, and if one is found, we can use that.
The symbol lookup is done by first calling find_pc_for_line, and then
using find_symbol_for_pc to find a suitable symbol.
On some configurations (SLES with glibc-devel installed), the compiler
links /usr/lib64/crit1.o (which contains some debug information) into
the final binary. As a result, the binary contains "some" debug
information, which makes the above pattern fail. The testcase is still
valid as we only really need the GPU code object (embedded in the main
binary) to not contain debug information, so this patch proposes to
relax this first step by using "gdb_load" instead.
Tested on x86_64-linux + AMDGPU gfx1031.
Change-Id: Id903f62e170af69c001b39f4681602a54e2fdaf1 Approved-By: Tom Tromey <tom@tromey.com>
gdb, linespec: avoid multiple locations with same PC
broke GDB's ability to list multiple source files using a 'list'
command. In GDB 16 and earlier something like 'list foo.c:10' could
print multiple results if there were multiple 'foo.c' files compiled
into the executable.
The above commit added a filter to add_sal_to_sals (linespec.c) such
that multiple sals in the same program space, but with the same pc
value, could not be added, only the first sal would actually be
recorded. The problem with this is that add_sal_to_sals is used from
decode_digits_list_mode (also linespec.c) where the pc value is forced
to zero. This force to zero makes sense I think as there might not be
any compiled code for the requested line (this is for 'list' after
all), so there might not be a valid pc to use.
I'm not a fan of using '0' as a special pc value, there are embedded
targets where 0 is a valid pc value, but given we're already using 0
here, I propose to just roll with it.
So, my proposal is that, if the pc is 0, add_sal_to_sals should always
add the sal. This fixes the decode_digits_list_mode, but should keep
the fix that c7a45b98a614 introduced.
In --help option, adds znver6 to the list of CPUs under -march.
Please find the ISA descriptions for AVX512_BMM instructions below.
AVX512 Bit Manipulation Instructions
====================================
The AVX512BMM instructions include Bit Matrix Multiply and Bit Reversal
operations.
CPUID
-----
Support is indicated by the new CPUID 8000_0021, EAX bit 23, labeled AVX512_BMM.
DESCRIPTION
-----------
256 BIT VERSIONS
----------------
16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR reduction.
A ymm register holds a 16x16 bit matrix. The third source matrix for
accumulation is in ymm1.
512 BIT VERSIONS
----------------
2 parallel 16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR
reduction.
Each 256-bit chunk of a zmm register holds a 16x16 bit matrix. The third source
matrices for accumulation are in zmm1.
DESCRIPTION
-----------
Bit reversal within a byte boundary. Only applied to input bytes where the
corresponding mask bit is set; otherwise, bytes are left untouched or zeroed out
if zero masking is indicated.
gas/ChangeLog:
* NEWS: Add znver6 ARCH.
* config/tc-i386.c: Add znver6 ARCH, avx512_bmm SUBARCH.
* doc/c-i386.texi: Likewise.
* testsuite/gas/i386/i386.exp: Add znver6 test cases.
* testsuite/gas/i386/x86-64.exp: Add znver6 test cases.
* testsuite/gas/i386/arch-16-znver6.d: New test.
* testsuite/gas/i386/arch-16.d: New test.
* testsuite/gas/i386/arch-16.s: New test.
* testsuite/gas/i386/avx512_bmm.d: New test.
* testsuite/gas/i386/avx512_bmm.s: New test.
* testsuite/gas/i386/avx512_bmm_vl-inval.l: New test.
* testsuite/gas/i386/avx512_bmm_vl-inval.s: New test.
* testsuite/gas/i386/avx512_bmm_vl.d: New test.
* testsuite/gas/i386/avx512_bmm_vl.s: New test.
* testsuite/gas/i386/x86-64-arch-6-znver6.d: New test.
* testsuite/gas/i386/x86-64-arch-6.d: New test.
* testsuite/gas/i386/x86-64-arch-6.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm-bad.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm-bad.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.l: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.s: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl.d: New test.
* testsuite/gas/i386/x86-64-avx512_bmm_vl.s: New test.
Jan Beulich [Fri, 5 Dec 2025 09:12:34 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NCI-NDD-NF and testing
To reflect spec version 007's introduction of the three-way APX-NCI-NDD-NF
also introduce a respective ISA specifier, without that actually having a
counterpart in opcodes.
Add a testcase to cover all four new ISA specifiers.
Jan Beulich [Fri, 5 Dec 2025 09:12:12 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NF
While spec version 007 introduced the three-way APX-NCI-NDD-NF, let's
split the three aspects (NCI, NDD, and NF) in gas. For NF we only need to
guard the {nf} pseudo-prefix.
Jan Beulich [Fri, 5 Dec 2025 09:12:00 +0000 (10:12 +0100)]
x86: sub-divide APX_F - NDD
While spec version 007 introduced the three-way APX-NCI-NDD-NF, let's
split the three aspects (NCI, NDD, and NF) in gas. Note that NDD also
applies to a number of EVEX-encoded insns with EVEX.ndd clear.
Some extra logic is needed in cpu_flags_match() to avoid the need to
add APX_NDD to CPU_FLAGS_COMMON.
Tom de Vries [Fri, 5 Dec 2025 07:24:06 +0000 (08:24 +0100)]
[gdb/testsuite] Fix gdb.base/long_long.exp on arm
On armv7hl-suse-linux-gnu, I run into:
...
(gdb) p/f val.oct
$26 = -5.9822653797615723e-120
(gdb) FAIL: gdb.base/long_long.exp: p/f val.oct
...
There's some complicated logic here in the test-case:
...
if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
# ARM FPA floating point numbers are not strictly little endian or big
# endian, but a hybrid. They are in little endian format with the two
# words swapped in big endian format.
# EABI targets default to natural-endian VFP format.
if { ([istarget "arm*-*-*"]) \
&& !([istarget "*-*-*eabi*"] || \
[istarget "*-*-mingw32ce*"] || \
[istarget "*-*-openbsd*"]) } then {
# assume the long long represents a floating point double in ARM format
gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
} else {
# assume the long long represents a floating point double in little
# endian format
gdb_test "p/f val.oct" "-5.9822653797615723e-120"
}
} else {
gdb_test "p/f val.oct" "-2.42716126e-15"
}
...
which makes the test-case expect the ARM FPA variant.
I think trying to pin down the exact circumstances under which we have ARM FPA
is unnecessary, so I could live with:
...
set re_val_oct_f [string_to_regexp "-5.9822653797615723e-120"]
if { [istarget "arm*-*-*"] } {
set re_val_oct_f_arm_fpa [string_to_regexp "2.1386676354387559e+265"]
re_val_oct_f "$re_val_oct_f|$re_val_oct_f_arm_fpa"
}
....
But instead, I propose to just drop the arm-specific part.
I doubt whether an ARM VPA setup is still part of any test matrix. And if it
is, then I expect other tests to fail as well for the same reason. The ARM
FPA logic is used only once in the test-case, but -5.9822653797615723e-120 is
used more frequently.
Indeed, I wonder the same about setups where -2.42716126e-15 is expected.
On such a setup, won't this fail as well:
...
gdb_test "x/2gf g" "3.5127005640885037e-303.*-5.9822653797615723e-120"
...
?
Unfortunately I'm not sure what setup to use to trigger the -2.42716126e-15
case.
Fix this as good as possible by choosing once between -5.9822653797615723e-120
and -2.42716126e-15, assigning it to re_val_oct_f, and using it everywhere
where those constants are used.
gdb: handle unlimited screen width case in print_gdb_hints
was merged that deleted some of the code I'd spotted. All that's left
is a 'return' that can be removed, there's nothing after the 'if'
block, the function just returns.
There should be no user visible changes after this commit.
Tom Tromey [Thu, 4 Dec 2025 14:36:59 +0000 (07:36 -0700)]
Fix 'ptype' of a certain Ada modular type
If an Ada modular type is the same size as gdb's own ULONGEST, ptype
will show "mod 0". This happens because ada_modulus does:
return (ULONGEST) high.const_val () + 1;
This patch cleans this up, replacing ada_modulus with a function to
return the upper bound (if available), and then fixing the various
callers. The type-printing caller still does the "+1", but now this
is done with a gdb_mpz.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33690 Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon Marchi [Tue, 2 Dec 2025 21:09:26 +0000 (16:09 -0500)]
gdb: remove find_target_at
... to make the current_inferior reference bubble up one level. Since
find_target_at would become a trivial wrapper around
inferior::target_at, remove it. I think it's clearer anyway to see
explicitly that the "subject" of the method call is the inferior.
Change-Id: I73ec44d37e7afea6e85b1689af65e32ae8e5a695 Approved-By: Tom Tromey <tom@tromey.com>
Alice Carlotti [Tue, 4 Nov 2025 12:22:52 +0000 (12:22 +0000)]
aarch64: Enable `-M notes' by default
We already print other instruction comments, such as condition code
aliases, by default. The `-M no-notes' option has been available in
Binutils for over 7 years, so if anyone does need the notes to be
disabled then they can do so explicitly.
Alice Carlotti [Wed, 5 Nov 2025 12:06:14 +0000 (12:06 +0000)]
aarch64: Refactor sysreg operand printing
This hopefully makes the logic clearer. It also adds NULL checks before
recording notes, and explicitly compares the inexactness of inexact
matches (although this extra comparison isn't used for any existing
encodings).
Alice Carlotti [Tue, 4 Nov 2025 12:28:56 +0000 (12:28 +0000)]
aarch64: Fix incorrect sysreg notes operand notes
When support for Armv8-R was added in 2020, aarch64_print_operand was
modified to check architecture features when searching for a system
register name. However, this mismatch is then conflated with
read-only/write-only mismatches, leading to incorrect note emission when
reading a read-only or writing a write-only system register that is not
available in whichever of Armv8-A or Armv8-R we are using.
The original code also segfaults when parsing `msr mpuir_el1, w1'. This
segfault arises while suggesting alternative assembler input with
corrected qualifiers, due to a missing NULL check when attempting to
emit notes. The segfault is unreachable after this change, but a
subsequent patch will incorporate NULL checking anyway.
Once notes are enabled by default, an existing `mrs x0, mpuir_el1' test
will verify that the incorrect notes are no longer generated.
Alice Carlotti [Wed, 5 Nov 2025 13:21:02 +0000 (13:21 +0000)]
aarch64: Improve comment for aarch64_opnd_info.sysreg.flags
This field is used differently during assembly and disassembly. It
would be nice if we could make this more consistent, but for now just
extend the comment to explain what is going on.
Patrick Monnerat [Sat, 29 Nov 2025 14:48:55 +0000 (15:48 +0100)]
gdb: handle unlimited screen width case in print_gdb_hints
This avoids a crash when this function is called while screen width is
unlimited. In such a case (unconditionally occurring in insight), WIDTH
is returned as a negative signed integer, so it has to be compared to
another signed integer, not a size_t.
Also remove an unused WIDTH-sized variable that may fail in the above
case.
Tom de Vries [Thu, 4 Dec 2025 09:29:52 +0000 (10:29 +0100)]
[gdb/testsuite] Fix build-id check in gdb.python/py-missing-objfile.exp
I recently added two requires in test-case gdb.python/py-missing-objfile.exp:
...
# The following tests assume that the build-ids of binfile and libfile can be
# found in the core file.
require {expect_build_id_in_core_file $binfile}
require {expect_build_id_in_core_file $libfile}
...
However, at the point where the check is done, the files are no longer
available at that location, which makes the require fail.
First, make the problem visible, by making proc expect_build_id_in_core_file
throw an error if the filename argument specifies a non-existing file.
Then, fix test-case gdb.python/py-missing-objfile.exp by moving the calls to
expect_build_id_in_core_file to a point where the files exist.