gas: sframe: fix PR gas/33170

SFrame generation code assumes that since DW_CFA_restore means
restoration of the state of the register to the one at the beginning of
the function, there must be a state to restore to (hence the gas_assert
(cie_fre)).

This assumption needs adjustment.  DW_CFA_restore may be present in the
very beginning of a (e.g., cold) function, with no initialized state for
SFrame functions to restore to.

gas/
	PR gas/33170
	* gas/gen-sframe.c (sframe_xlate_do_restore): Use current FRE if
	CIE FRE is not yet setup.
gas/testsuite/
	PR gas/33170
	* gas/cfi-sframe/cfi-sframe.exp: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-pr33170.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-pr33170.s: New test.
This commit is contained in:
Indu Bhagat
2025-07-17 15:17:36 -07:00
parent 58fe9ce1d6
commit 83eeaf9178
4 changed files with 71 additions and 4 deletions

View File

@@ -1286,11 +1286,18 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
list of FREs for the specific function. */
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
/* PR gas/33170. It is valid to have a:
.cfi_restore N
even at the entry of a function; in which case cie_fre is not yet setup.
Point cie_fre to cur_fre, and let the machinery proceed to update
merge_candidate as usual. */
if (cie_fre == NULL)
cie_fre = cur_fre;
/* Change the rule for the indicated register to the rule assigned to
it by the initial_instructions in the CIE. */
gas_assert (cie_fre);
/* SFrame FREs track only CFA and FP / RA for backtracing purposes;
skip the other .cfi_restore directives. */
it by the initial_instructions in the CIE. SFrame FREs track only CFA
and FP / RA for backtracing purposes; skip the other .cfi_restore
directives. */
if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
{
gas_assert (cur_fre);

View File

@@ -0,0 +1,19 @@
#as: --gsframe
#objdump: --sframe=.sframe
#name: SFrame generation on x86_64 pr31170
#...
Contents of the SFrame section .sframe:
Header :
Version: SFRAME_VERSION_2
Flags: SFRAME_F_FDE_FUNC_START_PCREL
CFA fixed RA offset: \-8
Num FDEs: 1
Num FREs: 2
Function Index :
func idx \[0\]: pc = 0x0, size = 50 bytes
STARTPC +CFA +FP +RA +
0+0000 +fp\+16 +c\-16 +f +
0+002d +fp\+16 +c\-16 +f +

View File

@@ -0,0 +1,40 @@
# PR gas/33170
# Ennsure graceful handling.
.section .text.unlikely
.cfi_startproc
.type XZ.cold, @function
XZ.cold:
.L1:
.cfi_def_cfa 6, 16
.cfi_offset 3, -56
.cfi_offset 6, -16
.cfi_offset 12, -48
.cfi_offset 13, -40
.cfi_offset 14, -32
.cfi_offset 15, -24
.L2:
.cfi_restore 12
.cfi_restore 13
movl $56, %esi
movq %r14, %rdi
call _Z@PLT
movq %r12, -32(%rbp)
movq %r13, -24(%rbp)
movq %r14, -16(%rbp)
movq %r15, -8(%rbp)
.cfi_offset 12, -48
.cfi_offset 13, -40
.cfi_offset 14, -32
.cfi_offset 15, -24
jne .L3
movq %rbx, %rdi
call bar@PLT
.L3:
movq -32(%rbp), %r12
.cfi_remember_state
.cfi_restore 12
jmp .L4
.L4:
.cfi_restore_state
call _ZF@PLT
.cfi_endproc

View File

@@ -58,6 +58,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
set ASFLAGS "$ASFLAGS --64"
run_dump_test "cfi-sframe-x86_64-1"
run_dump_test "cfi-sframe-x86_64-2"
run_dump_test "cfi-sframe-x86_64-pr33170"
run_dump_test "cfi-sframe-x86_64-empty-1"
run_dump_test "cfi-sframe-x86_64-empty-2"
run_dump_test "cfi-sframe-x86_64-empty-3"