[RFC 16/28] [SFrame-V3] gas: sframe: output new FDE type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME

Jens Remus jremus@linux.ibm.com
Tue Dec 16 10:45:46 GMT 2025


On 12/16/2025 7:12 AM, Indu Bhagat wrote:
> On 12/15/25 4:30 AM, Jens Remus wrote:
>> On 12/9/2025 10:07 AM, Indu Bhagat wrote:
>>> 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.
>>
>> In my quick and dirty s390x experiement I noticed that it seems as if
>> there is always RA tracking information in a FLEX_TOPMOST_FRAME FRE
>> (4 "offsets": 2x CFA + 2x RA) even if there would only be CFA tracking
>> information in a regular FRE (1 offset: 1x CFA).  Is that what you
>> mention above?  Why is that so, I cannot follow.  I would expect that
>> only to exist if the RA tracking info is different from the fixed RA
>> offset.
>>
> 
> Yes, RA offsets are always present in flexible frame.
> 
> Even for ABIs not tracking RA (and hence, fixed RA offset), when it
> comes to flexible frames, they may encode an alternative recovery
> rule, e.g.,
>   RA = REG
>   RA = CFA + offset (non-standard offset)
> 
> If we only emit RA offsets for flexible frames "when needed", the
> stack tracer has no way to tell whether the offset at index 2 and 3
> are for RA or FP...

Couldn't it be implemented as I did for s390x and use a padding RA
offset of SFRAME_FRE_RA_OFFSET_INVALID whenever there is FP without
RA tracking information?  That is what you currently do with a
RA offset of zero.  That way FREs with only CFA tracking infor would
only have 2 offsets instead of 4.  This pattern occurs on s390x.

>>> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
>>
>>> @@ -587,39 +599,84 @@ sframe_fde_free (struct sframe_func_entry *sframe_fde)
>>>      size FRE_OFFSET_SIZE.  Write out the offsets in order - CFA, RA, FP.  */
>>>     static unsigned int
>>> -output_sframe_row_entry_offsets (const struct sframe_func_entry *sframe_fde ATTRIBUTE_UNUSED,
>>> +output_sframe_row_entry_offsets (const struct sframe_func_entry *sframe_fde,
>>>                    const struct sframe_row_entry *sframe_fre,
>>>                    unsigned int fre_offset_size)
>>> -
>>>   {
>>>     unsigned int fre_write_offsets = 0;
>>>       unsigned int idx = sframe_fre_offset_func_map_index (fre_offset_size);
>>>     gas_assert (idx < SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX);
>>>   -  /* Write out the offsets in order - cfa, fp, ra.  */
>>> -  fre_offset_func_map[idx].out_func (sframe_fre->cfa_offset);
>>> -  fre_write_offsets++;
>>> -
>>> -  if (sframe_ra_tracking_p ())
>>> +  if (sframe_fde->fde_flex_topmost_p)
>>>       {
>>> -      if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
>>> +      /* SFrame FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME.  */
>>> +      /* Output CFA related FRE offsets.  */
>>> +      uint8_t reg_data
>>> +    = SFRAME_V3_FLEX_FDE_REG_ENCODE (sframe_fre->cfa_base_reg,
>>> +                     sframe_fre->cfa_deref_p,
>>> +                     1 /* reg_p.  */);
>>> +      offsetT offset_data = sframe_fre->cfa_offset;
>>> +      fre_offset_func_map[idx].out_func (reg_data);
>>> +      fre_offset_func_map[idx].out_func (offset_data);
>>> +      fre_write_offsets += 2;
>>> +
>>> +      /* Not expected.  Flexible Topmost Frame FDEs are not implemented ATM
>>> +     for ABIs other than SFRAME_ABI_AMD64_ENDIAN_LITTLE.  If need arises,
>>> +     the implementation may be added later as it will be backwards
>>> +     compatible to add a new FDE type for those ABIs.  */
>>> +      if (sframe_ra_tracking_p ())
>>> +    gas_assert (false);
>>
>> I guess you added this to detect implementation errors.  Is this really
>> required in the final version?
>>
> 
> This does not exist in the final version.
> 
> The code is amended in a later patch ("gas: sframe: add handling for
> .cfi_register for FP and RA").  When we add handling for .cfi_register
> RA, XX.

What I meant:  Couldn't this patch already include the complete logic
to write out the FRE offsets?  I don't think the logic is tied to the
later patch.

>> I wonder whether it would make sense to introduce a new target-
>> configurable knob to opt-in into FLEX_TOPMOST_FRAME (see also my other
>> patch reviews):
>>
>> /* Whether to support SFrame FLEX_TOPMOST_FRAME.  */
>> extern bool x86_sframe_flex_topmost_frame_p (void);
>> #define sframe_flex_topmost_frame_p x86_sframe_flex_topmost_frame_p
>>
>> And then change above to (and update the comment accordingly):
>>
>> if (!sframe_flex_topmost_frame_p ())
>>    gas_assert (false);
>>
> 
> Hmm, I see.  I can try it out. May be it helps make things clearer that some ABIs wont emit flexible frames ATM.
> 
>>> +
>>> +      /* RA tracking enabled or not, emit two offsets for RA.
>>> +     Aside, emitting SFRAME_FRE_RA_OFFSET_INVALID is equivalent to emitting
>>> +     SFRAME_V3_FLEX_FDE_REG_ENCODE (0, 0, 0).
>>> +     FIXME - This may change later when we implement handling .cfi_register
>>> +     RA, reg.  Emit two 0 offsets for now.  */
>>> +      fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
>>> +      /* FIXME Offset 0 for now.  */
>>> +      fre_offset_func_map[idx].out_func (0);

An offset value of 0 is equivalent to SFRAME_FRE_RA_OFFSET_INVALID.
Let's make this RA tracking info optional.  Either using a padding
RA offset or by using your suggestion using a bit mask below.

>>> +      fre_write_offsets += 2;
>>
>> Why?  Why can't RA be handled like FP below?
>>
> 
> See above.  If we only emit RA offsets when necessary, the stack tracer has
> no way to tell whether offsets at index 2 and 3 are information for RA or
> FP ATM.
> 
> I thought about adding the first offset as mask (8-bit) for flexible FDEs:
>  bit 0 indicate RA offsets present
>  bit 1 indicate FP offsets present
>  bit 2 indicate SP offsets present
>  bit 3-7 are unused.
> 
> We see in the longjmp routines or in unwind-dw2.S on AMD64, tracking SP is
> used. Not high occurrence.
> 
> But I havent prusued this.  What do you think about this ?

I am fine with either approach, as long as we can make the RA tracking
info optional, so that there can be FLEX_TOPMOST_FRAME FREs with only
CFA tracking info.

Why would the additional first "offset" (I really would then use
different terminology) be 8-bit? Wouldn't it be 8/16/32-bit as
all of the other FRE offsets?  So basically we would start with
8-bit, but if more than 8-bit would be required it could be
extended to use more, which would then enforce a different FRE
offset size on all offsets.

>>> +
>>> +      if (sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
>>>       {
>>> -      fre_offset_func_map[idx].out_func (sframe_fre->ra_offset);
>>> -      fre_write_offsets++;
>>> -    }
>>> -      /* For s390x write padding RA offset, if FP without RA saved.  */
>>> -      else if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG
>>> -           && sframe_fre->fp_loc == SFRAME_FRE_ELEM_LOC_STACK)
>>> -    {
>>> -      fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID);
>>> -      fre_write_offsets++;
>>> +      /* Output FP related FRE offsets.  */
>>> +      reg_data = SFRAME_V3_FLEX_FDE_REG_ENCODE (sframe_fre->fp_reg,
>>> +                            sframe_fre->fp_deref_p,
>>> +                            1 /* reg_p.  */);
>>> +      offset_data = sframe_fre->fp_offset;
>>> +      fre_offset_func_map[idx].out_func (reg_data);
>>> +      fre_offset_func_map[idx].out_func (offset_data);
>>> +      fre_write_offsets += 2;
>>>       }
>>>       }
Regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com

IBM

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



More information about the Binutils mailing list