[SFrame-V3] include: sframe: reserve 5 bits for new FDE types
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, 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 topmost 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 variable length bytes
trailing the SFrame FRE header as stack offsets.
- If the FDE type is SFRAME_FDE_TYPE_FLEX, 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.
For CFA, RA, and FP, up to two "offsets" may be 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
The offsets are in the usual order: CFA, RA, FP if present.
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)
+ if no deref, FP/RA = REG1 + offset
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))
+ offset2 to encode offset: offset
- Action:
+ if deref, FP/RA = *(CFA + offset)
+ if no deref, FP/RA = CFA + offset (pattern shouldnt be seen for
RA)
Next for CFA tracking,
- Action:
+ if deref, CFA = *(reg + offset) (e.g., seen for CFA recovery in
some stack realignment patterns on AMD64)
+ if no deref, CFA = reg + offset (e.g., for .cfi_def_cfa 2, 8, or
.cfi_def_cfa 10, 0)
Expected usage of this FDE type is quite low (DRAP on x86_64).
NB: In SFrame V2, we did use the the term 'FDE Type' for the two
designated 'PC Type' for the SFrame FDEs (SFRAME_FDE_TYPE_PCINC,
SFRAME_FDE_TYPE_PCMASK). In hindsight, 'FDE Type' was inappropriate
term. In a subsequent commit, we will fix this terminology for SFrame
V3.
include/
* sframe.h (SFRAME_FDE_TYPE_FLEX): New SFrame FDE type.
(SFRAME_V3_FDE_TYPE_MASK): New constant definition.
(SFRAME_V3_FDE_TYPE): New macro definition.
(SFRAME_V3_SET_FDE_TYPE): Likewise.
(SFRAME_V3_FLEX_FDE_REG_ENCODE): Macro to encode register in the
SFrame offset data.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_NUM): New definition.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_DEREF_P): Likewise.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_P): Likewise.