[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