[PATCH 4/4] gas: sframe: handle .cfi_same_value

Indu Bhagat indu.bhagat@oracle.com
Wed May 14 23:39:22 GMT 2025


On 5/13/25 8:51 AM, Jens Remus wrote:
> On 13.05.2025 15:13, Jan Beulich wrote:
>> On 11.05.2025 09:35, Indu Bhagat wrote:
>>> Fix PR gas/32953 - sframe: incorrect handling of .cfi_same_value in gas
>>>
>>> As per documentation, .cfi_same_value indicates that: Current value of
>>> register is the same like in the previous frame, i.e. no restoration
>>> needed.  SFrame has no means to encode this information.
>>>
>>> Skip generating FDE, but warn if it is for a register of interest.
>>> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
>>> index a87d464fd5f..f989627193f 100644
>>> --- a/gas/gen-sframe.c
>>> +++ b/gas/gen-sframe.c
>>> @@ -1533,6 +1533,32 @@ sframe_xlate_do_cfi_undefined (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUT
>>>     return SFRAME_XLATE_OK;
>>>   }
>>>   
>>> +/* Translate DW_CFA_same_value into SFrame context.
>>> +
>>> +   DW_CFA_undefined op implies that current value of register is the same like
>> Nit: DW_CFA_same_value and perhaps "indicates" in place of "implies".
>>
>>> +   in the previous frame, i.e. no restoration needed.  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_same_value.
>> Generally I'm having a hard time seeing when "same value" would need using.
>> Aiui the absence of any information means the register is unchanged (at
>> least as long as mandated so by the ABI). And a register which had its value
>> restored would be indicated by .cfi_restore. Hence it's not clear to me
>> whether "unable to represent" is really applicable here.
> This is about what generation of SFrame should do when encountering
> .cfi_same_value for one of its tracked registers (FP and optionally RA)
> and possibly also the SP register.  If that cannot be properly
> represented in SFrame the generation of the FDE needs to be skipped.
> 
> As I have written in my separate feedback to this patch, I think that
> .cfi_same_value for FP and RA needs to be represented by clearing the
> SFrame information for the respective register.  Ignoring the CFI
> directive (as it had been done so far) or resetting the SFrame
> information for the respective register to the one from FRE[0] would be
> wrong.  This assumes that for FP and RA .cfi_same_value and .cfi_restore
> would result same.
> 
> While .cfi_same_value <SP> (value at call site) and .cfi_restore <SP>
> (value at function entry) may indicate different SP values on x86-64 due
> to the call instruction altering the SP, I think this could be ignored,
> assuming the CFA definition was updated as well.

(Incorporated Jens' feedback elsewhere on the thread.  But replying 
here, to hopefully answer Jan's question on what is meant by "unable to 
represent" with respect to SFrame).

So this is what I have now:

/* Translate DW_CFA_same_value into SFrame context.

    DW_CFA_same_value op implies that current value of register is the 
same like
    in the previous frame, i.e. no restoration needed.  In SFrame stack 
trace
    format, whether or not we can encode "no restoration needed" is case
    specific.

    For SFRAME_CFA_RA_REG, perform an ABI-sensitive check.  For AMD64, 
SFrame
    can only represent the fact that REG_RA is at a fixed offset from 
CFA; IOW,
    restoration is always necessary.  Hence, .cfi_same_value REG_RA 
cannot be
    represented in SFrame.  For AArch64, since RA-tracking is enabled, the
    manner to restore REG_RA is, in theory, encodable.  So, for
    DW_CFA_same_value, reset the SFrame FRE state for REG_RA to indicate 
that
    register does not need restoration.  P.S.: Even though resetting 
just REG_RA
    may be contradicting the AArch64 ABI (as Frame Record contains both 
FP and
    LR), sframe_xlate_do_same_value () does not detect the case and 
assumes the
    users' DW_CFA_same_value SFRAME_CFA_RA_REG has a sound reason.

    SFrame based stacktracers will implement CFA-based SP recovery for 
all ABIs:
    SP for previous frame is based on the applicable CFA-rule.  There is no
    representation in SFrame to indicate "no restoration needed" for 
REG_SP.  So
    skip generating the SFrame FDE if DW_CFA_same_value is seen for
    SFRAME_CFA_SP_REG.

    For SFRAME_CFA_FP_REG, reset the state of the current FRE to 
indicate that
    the value is the same as previous frame.

    Return SFRAME_XLATE_OK if success.  */

static int
sframe_xlate_do_same_value (const struct sframe_xlate_ctx *xlate_ctx,
			    const struct cfi_insn_data *cfi_insn)
{
   /* For most ABIs, "no restoration" semantic (indicated by 
DW_CFA_same_value)
      for SP or RA may be violating ABI rules.  More importantly, SFrame 
cannot
      encode such information.  */
   if (cfi_insn->u.r == SFRAME_CFA_SP_REG
       || (!sframe_ra_tracking_p () && cfi_insn->u.r == SFRAME_CFA_RA_REG))
     {
       as_warn (_("skipping SFrame FDE; %s reg %u in .cfi_same_value"),
	       sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
       return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
     }

   struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;

   if (cfi_insn->u.r == SFRAME_CFA_RA_REG)
     {
       cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_REG;
       cur_fre->ra_offset = 0;
       cur_fre->merge_candidate = false;
     }
   else if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
     {
       cur_fre->bp_loc = SFRAME_FRE_ELEM_LOC_REG;
       cur_fre->bp_offset = 0;
       cur_fre->merge_candidate = false;
     }

   /* Safe to skip.  */
   return SFRAME_XLATE_OK;
}


More information about the Binutils mailing list