aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/generic/sframe.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/sframe.h')
-rw-r--r--sysdeps/generic/sframe.h367
1 files changed, 367 insertions, 0 deletions
diff --git a/sysdeps/generic/sframe.h b/sysdeps/generic/sframe.h
new file mode 100644
index 0000000..3f8ff1c
--- /dev/null
+++ b/sysdeps/generic/sframe.h
@@ -0,0 +1,367 @@
+/* SFrame format description.
+ Copyright (C) 2022-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SFRAME_H
+#define _SFRAME_H
+
+#include <sys/types.h>
+#include <limits.h>
+#include <stdint.h>
+#include <unwind.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* SFrame format.
+
+ SFrame format is a simple format to represent the information needed
+ for generating vanilla backtraces. SFrame format keeps track of the
+ minimal necessary information needed for stack tracing:
+ - Canonical Frame Address (CFA)
+ - Frame Pointer (FP)
+ - Return Address (RA)
+
+ The SFrame section itself has the following structure:
+
+ +--------+------------+---------+
+ | file | function | frame |
+ | header | descriptor | row |
+ | | entries | entries |
+ +--------+------------+---------+
+
+ The file header stores a magic number and version information, flags, and
+ the byte offset of each of the sections relative to the end of the header
+ itself. The file header also specifies the total number of Function
+ Descriptor Entries, Frame Row Entries and length of the FRE sub-section.
+
+ Following the header is a list of Function Descriptor Entries (FDEs).
+ This list may be sorted if the flags in the file header indicate it to be
+ so. The sort order, if applicable, is the order of functions in the
+ .text.* sections in the resulting binary artifact. Each Function
+ Descriptor Entry specifies the start PC of a function, the size in bytes
+ of the function and an offset to its first Frame Row Entry (FRE). Each FDE
+ additionally also specifies the type of FRE it uses to encode the stack
+ trace information.
+
+ Next, the SFrame Frame Row Entry sub-section is a list of variable size
+ records. Each entry represents stack trace information for a set of PCs
+ of the function. A singular Frame Row Entry is a self-sufficient record
+ which contains information on how to generate stack trace from the
+ applicable set of PCs.
+
+ */
+
+
+/* SFrame format versions. */
+#define SFRAME_VERSION_1 1
+#define SFRAME_VERSION_2 2
+/* SFrame magic number. */
+#define SFRAME_MAGIC 0xdee2
+/* Current version of SFrame format. */
+#define SFRAME_VERSION SFRAME_VERSION_2
+
+/* Various flags for SFrame. */
+
+/* Function Descriptor Entries are sorted on PC. */
+#define SFRAME_F_FDE_SORTED 0x1
+/* Functions preserve frame pointer. */
+#define SFRAME_F_FRAME_POINTER 0x2
+
+#define SFRAME_CFA_FIXED_FP_INVALID 0
+#define SFRAME_CFA_FIXED_RA_INVALID 0
+
+/* Supported ABIs/Arch. */
+#define SFRAME_ABI_AARCH64_ENDIAN_BIG 1 /* AARCH64 big endian. */
+#define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 /* AARCH64 little endian. */
+#define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 /* AMD64 little endian. */
+
+/* SFrame FRE types. */
+#define SFRAME_FRE_TYPE_ADDR1 0
+#define SFRAME_FRE_TYPE_ADDR2 1
+#define SFRAME_FRE_TYPE_ADDR4 2
+
+/* SFrame Function Descriptor Entry types.
+
+ The SFrame format has two possible representations for functions. The
+ choice of which type to use is made according to the instruction patterns
+ in the relevant program stub.
+
+ An SFrame FDE of type SFRAME_FDE_TYPE_PCINC is an indication
+ that the PCs in the FREs should be treated as increments in bytes. This is
+ used for a bulk of the executable code of a program, which contains
+ instructions with no specific pattern.
+
+ An SFrame FDE of type SFRAME_FDE_TYPE_PCMASK is an indication
+ that the PCs in the FREs should be treated as masks. This type is useful
+ for the cases when a small pattern of instructions in a program stub is
+ repeatedly to cover a specific functionality. Typical usescases are pltN
+ entries, trampolines etc. */
+
+/* Unwinders perform a (PC >= FRE_START_ADDR) to look up a matching FRE. */
+#define SFRAME_FDE_TYPE_PCINC 0
+/* Unwinders perform a (PC % REP_BLOCK_SIZE >= FRE_START_ADDR) to look up a
+ matching FRE. */
+#define SFRAME_FDE_TYPE_PCMASK 1
+
+typedef struct sframe_preamble
+{
+ uint16_t sfp_magic; /* Magic number (SFRAME_MAGIC). */
+ uint8_t sfp_version; /* Data format version number (SFRAME_VERSION). */
+ uint8_t sfp_flags; /* Flags. */
+} __attribute__ ((packed)) sframe_preamble;
+
+typedef struct sframe_header
+{
+ sframe_preamble sfh_preamble;
+ /* Information about the arch (endianness) and ABI. */
+ uint8_t sfh_abi_arch;
+ /* Offset for the Frame Pointer (FP) from CFA may be fixed for some
+ ABIs (e.g, in AMD64 when -fno-omit-frame-pointer is used). When fixed,
+ this field specifies the fixed stack frame offset and the individual
+ FREs do not need to track it. When not fixed, it is set to
+ SFRAME_CFA_FIXED_FP_INVALID, and the individual FREs may provide
+ the applicable stack frame offset, if any. */
+ int8_t sfh_cfa_fixed_fp_offset;
+ /* Offset for the Return Address from CFA is fixed for some ABIs
+ (e.g., AMD64 has it as CFA-8). When fixed, the header specifies the
+ fixed stack frame offset and the individual FREs do not track it. When
+ not fixed, it is set to SFRAME_CFA_FIXED_RA_INVALID, and individual
+ FREs provide the applicable stack frame offset, if any. */
+ int8_t sfh_cfa_fixed_ra_offset;
+ /* Number of bytes making up the auxiliary header, if any.
+ Some ABI/arch, in the future, may use this space for extending the
+ information in SFrame header. Auxiliary header is contained in
+ bytes sequentially following the sframe_header. */
+ uint8_t sfh_auxhdr_len;
+ /* Number of SFrame FDEs in this SFrame section. */
+ uint32_t sfh_num_fdes;
+ /* Number of SFrame Frame Row Entries. */
+ uint32_t sfh_num_fres;
+ /* Number of bytes in the SFrame Frame Row Entry section. */
+ uint32_t sfh_fre_len;
+ /* Offset of SFrame Function Descriptor Entry section. */
+ uint32_t sfh_fdeoff;
+ /* Offset of SFrame Frame Row Entry section. */
+ uint32_t sfh_freoff;
+} __attribute__ ((packed)) sframe_header;
+
+#define SFRAME_V1_HDR_SIZE(sframe_hdr) \
+ ((sizeof (sframe_header) + (sframe_hdr).sfh_auxhdr_len))
+
+/* Two possible keys for executable (instruction) pointers signing. */
+#define SFRAME_AARCH64_PAUTH_KEY_A 0 /* Key A. */
+#define SFRAME_AARCH64_PAUTH_KEY_B 1 /* Key B. */
+
+typedef struct sframe_func_desc_entry
+{
+ /* Function start address. Encoded as a signed offset, relative to the
+ beginning of the current FDE. */
+ int32_t sfde_func_start_address;
+ /* Size of the function in bytes. */
+ uint32_t sfde_func_size;
+ /* Offset of the first SFrame Frame Row Entry of the function, relative to the
+ beginning of the SFrame Frame Row Entry sub-section. */
+ uint32_t sfde_func_start_fre_off;
+ /* Number of frame row entries for the function. */
+ uint32_t sfde_func_num_fres;
+ /* Additional information for stack tracing from the function:
+ - 4-bits: Identify the FRE type used for the function.
+ - 1-bit: Identify the FDE type of the function - mask or inc.
+ - 1-bit: PAC authorization A/B key (aarch64).
+ - 2-bits: Unused.
+ ------------------------------------------------------------------------
+ | Unused | PAC auth A/B key (aarch64) | FDE type | FRE type |
+ | | Unused (amd64) | | |
+ ------------------------------------------------------------------------
+ 8 6 5 4 0 */
+ uint8_t sfde_func_info;
+ /* Size of the block of repeating insns. Used for SFrame FDEs of type
+ SFRAME_FDE_TYPE_PCMASK. */
+ uint8_t sfde_func_rep_size;
+ uint16_t sfde_func_padding2;
+} __attribute__ ((packed)) sframe_func_desc_entry;
+
+/* Macros to compose and decompose function info in FDE. */
+
+/* Note: Set PAC auth key to SFRAME_AARCH64_PAUTH_KEY_A by default. */
+#define SFRAME_V1_FUNC_INFO(fde_type, fre_enc_type) \
+ (((SFRAME_AARCH64_PAUTH_KEY_A & 0x1) << 5) | \
+ (((fde_type) & 0x1) << 4) | ((fre_enc_type) & 0xf))
+
+#define SFRAME_V1_FUNC_FRE_TYPE(data) ((data) & 0xf)
+#define SFRAME_V1_FUNC_FDE_TYPE(data) (((data) >> 4) & 0x1)
+#define SFRAME_V1_FUNC_PAUTH_KEY(data) (((data) >> 5) & 0x1)
+
+/* Set the pauth key as indicated. */
+#define SFRAME_V1_FUNC_INFO_UPDATE_PAUTH_KEY(pauth_key, fde_info) \
+ ((((pauth_key) & 0x1) << 5) | ((fde_info) & 0xdf))
+
+/* Size of stack frame offsets in an SFrame Frame Row Entry. A single
+ SFrame FRE has all offsets of the same size. Offset size may vary
+ across frame row entries. */
+#define SFRAME_FRE_OFFSET_1B 0
+#define SFRAME_FRE_OFFSET_2B 1
+#define SFRAME_FRE_OFFSET_4B 2
+
+/* An SFrame Frame Row Entry can be SP or FP based. */
+#define SFRAME_BASE_REG_FP 0
+#define SFRAME_BASE_REG_SP 1
+
+/* The index at which a specific offset is presented in the variable length
+ bytes of an FRE. */
+#define SFRAME_FRE_CFA_OFFSET_IDX 0
+/* The RA stack offset, if present, will always be at index 1 in the variable
+ length bytes of the FRE. */
+#define SFRAME_FRE_RA_OFFSET_IDX 1
+/* The FP stack offset may appear at offset 1 or 2, depending on the ABI as RA
+ may or may not be tracked. */
+#define SFRAME_FRE_FP_OFFSET_IDX 2
+
+typedef struct sframe_fre_info
+{
+ /* Information about
+ - 1 bit: base reg for CFA
+ - 4 bits: Number of offsets (N). A value of upto 3 is allowed to track
+ all three of CFA, FP and RA (fixed implicit order).
+ - 2 bits: information about size of the offsets (S) in bytes.
+ Valid values are SFRAME_FRE_OFFSET_1B, SFRAME_FRE_OFFSET_2B,
+ SFRAME_FRE_OFFSET_4B
+ - 1 bit: Mangled RA state bit (aarch64 only).
+ ----------------------------------------------------------------------------------
+ | Mangled-RA (aarch64) | Size of offsets | Number of offsets | base_reg |
+ | Unused (amd64) | | | |
+ ----------------------------------------------------------------------------------
+ 8 7 5 1 0
+
+ */
+ uint8_t fre_info;
+} sframe_fre_info;
+
+/* Macros to compose and decompose FRE info. */
+
+/* Note: Set mangled_ra_p to zero by default. */
+#define SFRAME_V1_FRE_INFO(base_reg_id, offset_num, offset_size) \
+ (((0 & 0x1) << 7) | (((offset_size) & 0x3) << 5) | \
+ (((offset_num) & 0xf) << 1) | ((base_reg_id) & 0x1))
+
+/* Set the mangled_ra_p bit as indicated. */
+#define SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P(mangled_ra_p, fre_info) \
+ ((((mangled_ra_p) & 0x1) << 7) | ((fre_info) & 0x7f))
+
+#define SFRAME_V1_FRE_CFA_BASE_REG_ID(data) ((data) & 0x1)
+#define SFRAME_V1_FRE_OFFSET_COUNT(data) (((data) >> 1) & 0xf)
+#define SFRAME_V1_FRE_OFFSET_SIZE(data) (((data) >> 5) & 0x3)
+#define SFRAME_V1_FRE_MANGLED_RA_P(data) (((data) >> 7) & 0x1)
+
+/* SFrame Frame Row Entry definitions.
+
+ Used for both AMD64 and AARCH64.
+
+ An SFrame Frame Row Entry is a self-sufficient record which contains
+ information on how to generate the stack trace for the specified range of
+ PCs. Each SFrame Frame Row Entry is followed by S*N bytes, where:
+ S is the size of the stack frame offset for the FRE, and
+ N is the number of stack frame offsets in the FRE
+
+ The interpretation of FRE stack offsets is ABI-specific:
+
+ AMD64:
+ offset1 (interpreted as CFA = BASE_REG + offset1)
+ if FP is being tracked
+ offset2 (intrepreted as FP = CFA + offset2)
+ fi
+
+ AARCH64:
+ offset1 (interpreted as CFA = BASE_REG + offset1)
+ if FP is being tracked (in other words, if frame record created)
+ offset2 (interpreted as RA = CFA + offset2)
+ offset3 (intrepreted as FP = CFA + offset3)
+ fi
+ Note that in AAPCS64, a frame record, if created, will save both FP and
+ LR on stack.
+*/
+
+/* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type. */
+typedef struct sframe_frame_row_entry_addr1
+{
+ /* Start address of the frame row entry. Encoded as an 1-byte unsigned
+ offset, relative to the start address of the function. */
+ uint8_t sfre_start_address;
+ sframe_fre_info sfre_info;
+} __attribute__ ((packed)) sframe_frame_row_entry_addr1;
+
+/* Upper limit of start address in sframe_frame_row_entry_addr1
+ is 0x100 (not inclusive). */
+#define SFRAME_FRE_TYPE_ADDR1_LIMIT \
+ (1ULL << ((SFRAME_FRE_TYPE_ADDR1 + 1) * 8))
+
+/* Used when SFRAME_FRE_TYPE_ADDR2 is specified as FRE type. */
+typedef struct sframe_frame_row_entry_addr2
+{
+ /* Start address of the frame row entry. Encoded as an 2-byte unsigned
+ offset, relative to the start address of the function. */
+ uint16_t sfre_start_address;
+ sframe_fre_info sfre_info;
+} __attribute__ ((packed)) sframe_frame_row_entry_addr2;
+
+/* Upper limit of start address in sframe_frame_row_entry_addr2
+ is 0x10000 (not inclusive). */
+#define SFRAME_FRE_TYPE_ADDR2_LIMIT \
+ (1ULL << ((SFRAME_FRE_TYPE_ADDR2 * 2) * 8))
+
+/* Used when SFRAME_FRE_TYPE_ADDR4 is specified as FRE type. */
+typedef struct sframe_frame_row_entry_addr4
+{
+ /* Start address of the frame row entry. Encoded as a 4-byte unsigned
+ offset, relative to the start address of the function. */
+ uint32_t sfre_start_address;
+ sframe_fre_info sfre_info;
+} __attribute__ ((packed)) sframe_frame_row_entry_addr4;
+
+/* Upper limit of start address in sframe_frame_row_entry_addr2
+ is 0x100000000 (not inclusive). */
+#define SFRAME_FRE_TYPE_ADDR4_LIMIT \
+ (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8))
+
+/* Used to pass frame information to stack trace routine. */
+typedef struct cframe
+{
+ _Unwind_Ptr pc;
+ _Unwind_Ptr sp;
+ _Unwind_Ptr fp;
+} frame;
+
+/* SFrame stack tracing support. */
+int __stacktrace_sframe (void **, int, frame *);
+libc_hidden_proto (__stacktrace_sframe);
+
+/* Helper used by SFrame tracing algorithm. */
+_Unwind_Ptr __getPC (void);
+libc_hidden_proto (__getPC);
+
+/* Helper used by SFrame tracing algorithm. */
+_Unwind_Ptr __getSP (void);
+libc_hidden_proto (__getSP);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SFRAME_H */