From: Indu Bhagat Date: Mon, 19 May 2025 07:05:17 +0000 (-0700) Subject: gas: sframe: handle .cfi_undefined X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4917deea42ae90506f6c1cf196fb10fa17645fc;p=thirdparty%2Fbinutils-gdb.git gas: sframe: handle .cfi_undefined Fix PR gas/32952 - sframe: incorrect handling of .cfi_undefined in gas In context of SFrame generation, it is incorrect to simply ignore all .cfi_undefined. We may ignore only those .cfi_undefined which are for registers of no interest (similar to whats done for other CFI directives). gas/ * gen-sframe.c (sframe_xlate_do_cfi_undefined): New definition. (sframe_do_cfi_insn): Handle .cfi_undefined. gas/testsuite/ * gas/cfi-sframe/cfi-sframe.exp: Add new tests. * gas/cfi-sframe/cfi-sframe-common-10.d: New test. * gas/cfi-sframe/cfi-sframe-common-10.s: New test. * gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d: New test. * gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s: New test. --- diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c index aedeb3603a0..a29c959db1c 100644 --- a/gas/gen-sframe.c +++ b/gas/gen-sframe.c @@ -1508,6 +1508,32 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx, return err; } +/* Translate DW_CFA_undefined into SFrame context. + + DW_CFA_undefined op indicates that from now on, the previous value of + register can’t be restored anymore. In SFrame stack trace, we cannot + represent such a semantic. So, we skip generating an SFrame FDE for this, + when a register of interest is used with DW_CFA_undefined. + + Return SFRAME_XLATE_OK if success. */ + +static int +sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED, + const struct cfi_insn_data *cfi_insn) +{ + if (cfi_insn->u.r == SFRAME_CFA_FP_REG + || cfi_insn->u.r == SFRAME_CFA_RA_REG + || cfi_insn->u.r == SFRAME_CFA_SP_REG) + { + as_warn (_("no SFrame FDE emitted; %s reg %u in .cfi_undefined"), + sframe_register_name (cfi_insn->u.r), cfi_insn->u.r); + return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */ + } + + /* Safe to skip. */ + return SFRAME_XLATE_OK; +} + /* Returns the DWARF call frame instruction name or fake CFI name for the specified CFI opcode, or NULL if the value is not recognized. */ @@ -1611,6 +1637,8 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx, These do not impact the coverage of the basic stack tracing information as conveyed in the SFrame format. */ case DW_CFA_undefined: + err = sframe_xlate_do_cfi_undefined (xlate_ctx, cfi_insn); + break; case DW_CFA_same_value: break; default: diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.d new file mode 100644 index 00000000000..106e05d160b --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.d @@ -0,0 +1,22 @@ +#as: --gsframe +#objdump: --sframe=.sframe +#name: SFrame cfi_undefined test +#... +Contents of the SFrame section .sframe: + + Header : + + Version: SFRAME_VERSION_2 + Flags: NONE +#? CFA fixed FP offset: \-?\d+ +#? CFA fixed RA offset: \-?\d+ + Num FDEs: 1 + Num FREs: 2 + + Function Index : + func idx \[0\]: pc = 0x0, size = 8 bytes + STARTPC + CFA + FP + RA + +#... + 0+0004 +sp\+16 +u +[uf] + + +#pass diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.s new file mode 100644 index 00000000000..7761edaf2b7 --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-common-10.s @@ -0,0 +1,12 @@ +## cfi_undefined when used with "not interesting" registers (from the +## perspective of SFrame section, non SP/FP/RA registers are not +## interesting) does not affect the asynchronicity of the SFrame +## stack trace information. Such CFI directives can be skipped for SFrame +## stack trace info generation. + .cfi_startproc + .long 0 + .cfi_def_cfa_offset 16 + .cfi_undefined 1 + .cfi_undefined 2 + .long 0 + .cfi_endproc diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d new file mode 100644 index 00000000000..43f09e09d27 --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d @@ -0,0 +1,17 @@ +#as: --gsframe +#warning: SP reg 7 in \.cfi\_undefined +#objdump: --sframe=.sframe +#name: DW_CFA_undefined with register SP +#... +Contents of the SFrame section .sframe: + + Header : + + Version: SFRAME_VERSION_2 + Flags: NONE +#? CFA fixed FP offset: \-?\d+ +#? CFA fixed RA offset: \-?\d+ + Num FDEs: 0 + Num FREs: 0 + +#pass diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s new file mode 100644 index 00000000000..fae3bbf932a --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s @@ -0,0 +1,6 @@ + .cfi_startproc + .long 0 + .cfi_def_cfa_offset 16 + .cfi_undefined 7 + .long 0 + .cfi_endproc diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp index b353e27ce56..ad5602fc373 100644 --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp @@ -79,6 +79,7 @@ if { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \ run_dump_test "cfi-sframe-common-7" run_dump_test "cfi-sframe-common-8" run_dump_test "cfi-sframe-common-9" + run_dump_test "cfi-sframe-common-10" run_dump_test "common-empty-1" run_dump_test "common-empty-2" @@ -94,6 +95,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then { 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" + run_dump_test "cfi-sframe-x86_64-empty-4" set ASFLAGS "$old_ASFLAGS" } }