[RFC 15/28] [SFrame-V3] include: sframe: reserve 4 bits for new FDE types
Jens Remus
jremus@linux.ibm.com
Thu Dec 11 17:36:43 GMT 2025
More information about the Binutils mailing list
Thu Dec 11 17:36:43 GMT 2025
- Previous message (by thread): [RFC 15/28] [SFrame-V3] include: sframe: reserve 4 bits for new FDE types
- Next message (by thread): [RFC 15/28] [SFrame-V3] include: sframe: reserve 4 bits for new FDE types
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hello Indu,
I am trying to wrap my head around the new FLEX_TOPMOST_FRAME encoding.
On 12/9/2025 10:07 AM, Indu Bhagat wrote:
> In SFrame V2, the FDE representation caters to the most common cases of
> stack trace metadata:
> - CFA is SP/FP based,
> - FP/RA offsets, if present are CFA based (except some cases in s390x
> where reg can be encoded).
>
> Introduce an additional FDE type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME,
> which can encode a more flexible set of CFA, FP and RA recovery rules.
> Some of the patterns supported include:
> - CFA may be non-SP/FP based.
> - CFA, FP may encode dereferencing of register after offset adjustment
> - RA may be in a non-default register.
>
> The important bit here is that since SFrame does not track all
> callee-saved registers, the above-mentioned recovery rules must only be
> done for top-most frames (by the stack tracer).
>
> Adding a new FDE type does have implications for a stack tracer in that
> it needs to:
> - Check the FDE type before interpreting the Stack offsets data.
> - If the FDE type is SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME, and the
> recovery rules employ the use of any non-SP/FP based register, the
> stack tracer must proceed only if it is the topmost frame on stack.
Can this be summarize to: Recovery rules that employ arbitrary register
contents (other than SP/FP) are only allowed in the topmost frame?
>
> For each of CFA and RA two offsets are always used. The two offsets
> represent the information as follows:
> - (minimum 8-bit) offset1 to encode register like:
> (regnum << 3) | unused << 2 | deref << 1 | reg_p (=1)
> - offset2 to encode offset: offset
>
> reg_p = 1 indicates a register, reg_p = 0 indicates CFA.
>
> The offsets are in the usual order: CFA, RA, FP if present.
Is it required to have this flexibility for both CFA and RA/FP? Would
it be an alternative to use the common encoding but leave some features
as "reserved" in each?
> For example, for FP/RA tracking,
>
> a) If the reg is REG1 for FP/RA tracking,
> - Encoding:
> + offset1 to encode register: (REG1 << 3) | unused << 2 | deref << 1 | reg_p (=1)
> + offset2 to encode offset: offset
> - Action:
> + if deref, FP/RA = \*(REG1 + offset) (e.g., seen for FP recovery
> with certain DRAP patterns on x86_64)
How can this be expressed by CFI directives? Could you please provide
an example?
> + if no deref, FP/RA = REG1 + offset
Should s390x use that to encode FP/RA saved in register? Since that is
only supported for topmost frames FLEX_TOPMOST_FRAME seems a good fit.
It would remove the need for a s390x-specific encoding and would also
make your patch "[RFC 13/28] [SFrame-V3] include: sframe: s390x: keep
unused bits when possible" obsolete.
It would be interesting to see the .sframe section size penalty though.
I would need to implement a prototype to compare based on your patch
"[RFC 21/28] [SFrame-V3] gas: sframe: add handling for .cfi_register
for FP and RA". Have you had considered this? If yes why didn't you
decide for that approach?
> b) If the reg is CFA for FP/RA tracking,
> - Encoding:
> + [=Effectively Padding] offset1 to encode register:
> (( 0 << 3 ) | unused << 2 | 0 << 1 | reg_p (=0))
Nit:
(( 0 << 3 ) | unused << 2 | deref << 1 | reg_p (=0))
> + offset2 to encode offset: offset
> - Action:
> + if deref, FP/RA = *(CFA + offset)
Makes sense.
> + if no deref, FP/RA = CFA + offset (pattern shouldnt be seen for
> RA)
This could be used to represent .cfi_val_offset with FP/RA register,
correct? Although I have only ever seen .cfi_val_offset with
SP register so far.
> Next for CFA tracking,
> - Action:
> + if deref, CFA = *(reg + offset) (e.g., seen for CFA recovery in
> some stack realignment patterns on AMD64)
How can this be expressed by CFI directives? Could you please provide
an example?
> + if no deref, CFA = reg + offset (e.g., for .cfi_def_cfa 2, 8, or
> .cfi_def_cfa 10, 0)
This is used to represent .cfi_def_cfa[_offset|_register] with non-SP/FP
register, as in the following example, correct?
.cfi_def_cfa <non-SP/FP-reg>, <offset>
Is encoded as:
offset1 = (regnum=<non-SP/FP-reg>) << 3 | (deref=0) << 1 | (reg_p=1)
offset2 = <offset>
>
> Expected usage of this FDE type is quite low (DRAP on x86_64).
So a FLEX_TOPMOST_FRAME would encode SP/FP-based CFA using the register
number instead of the FRE use_fp flag? This then requires knowledge of
the SP and FP DWARF register numbers in the stacktracer, so that it can
decide whether a rule is allowed in a non-topmost frame. In the Kernel
I would hide those in unwind user sframe, so that the common unwind user
framework does not need to have this knowledge (see SP_OFFSET and
FP_OFFSET CFA rules below).
To support a most of the new FLEX_TOPMOST_FRAME encoding in the Kernel
common unwind user framework, I roughly assume the following high-level
changes:
For the CFA:
+enum unwind_user_cfa_rule_type {
+ UNWIND_USER_CFA_RT_SP_OFFSET, // CFA = SP + offset (formerly .use_fp=false)
+ UNWIND_USER_CFA_RT_FP_OFFSET, // CFA = FP + offset (formerly .use_fp=true)
+ UNWIND_USER_CFA_RT_REG_OFFSET, // CFA = <non-SP/FP register> + offset
+ UNWIND_USER_CFA_RT_REG_OFFSET_DEREF, // CFA = *(<non-SP/FP register> + offset)
+};
+
+struct unwind_user_cfa_rule {
+ enum unwind_user_cfa_rule_type type;
+ s32 offset;
+ int regnum;
+};
Note that I omitted the following exotic cases. Not sure whether they
need to be supported?
UNWIND_USER_CFA_RT_SP_OFFSET_DEREF, // CFA = *(SP + offset)
UNWIND_USER_CFA_RT_FP_OFFSET_DEREF, // CFA = *(FP + offset)
The SP_OFFSET and FP_OFFSET cases hide the need for unwind user to know
their architecture-specific DWARF register numbers. unwind user sframe
would need to know them, depending on whether SFrame V3 still uses the
FDE use_fp flag.
For FP/RA:
enum unwind_user_rule_type {
UNWIND_USER_RT_UNKNOWN, // FP/RA = 0 (used with unwind user fp on s390 using back chain)
UNWIND_USER_RT_RETAIN, // FP/RA = FP/RA
- UNWIND_USER_RT_STACK,
- UNWIND_USER_RT_REG,
+ UNWIND_USER_RT_CFA_OFFSET_DEREF, // FP/RA = *(CFA + offset) (formerly UNWIND_USER_LOC_STACK)
+ UNWIND_USER_RT_REG_OFFSET, // FP/RA = register + offset (formerly UNWIND_USER_LOC_REG)
+ UNWIND_USER_RT_REG_OFFSET_DEREF, // FP/RA = *(register + offset)
};
struct unwind_user_rule {
enum unwind_user_rule_type type;
- union {
- s32 offset;
- int regnum;
- };
+ s32 offset;
+ int regnum;
};
Note that the following omitted case would be required for
.cfi_val_offset <FP/RA> and could easily be added:
UNWIND_USER_RT_CFA_OFFSET, // FP/RA = CFA + offset
struct unwind_user_frame {
- s32 cfa_off; // now .cfa.offset
- s32 sp_off; // moved
+ struct unwind_user_cfa_rule cfa;
struct unwind_user_rule ra;
struct unwind_user_rule fp;
- bool use_fp; // now .cfa.type = SP_OFFSET/FP_OFFSET (formerly .use_fp=false/true)
+ s32 sp_off;
bool outermost;
};
Note that rule types that contain "_REG_" are only allowed in the
topmost frame.
Maybe the _DEREF cases could better be represented as follows, but that
would allow all kinds of dereference variations that are not sensible,
e.g. UNKNOWN or RETAIN with deref=true.
struct unwind_user_[cfa_]rule {
...
bool deref;
};
Thoughts?
Thanks and 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/
- Previous message (by thread): [RFC 15/28] [SFrame-V3] include: sframe: reserve 4 bits for new FDE types
- Next message (by thread): [RFC 15/28] [SFrame-V3] include: sframe: reserve 4 bits for new FDE types
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list