|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
| 2 | +/* |
| 3 | + * Copyright (C) 2023, Oracle and/or its affiliates. |
| 4 | + * |
| 5 | + * This file contains definitions for the SFrame stack tracing format, which is |
| 6 | + * documented at https://sourceware.org/binutils/docs |
| 7 | + */ |
| 8 | +#ifndef _SFRAME_H |
| 9 | +#define _SFRAME_H |
| 10 | + |
| 11 | +#include <linux/types.h> |
| 12 | + |
| 13 | +#define SFRAME_VERSION_1 1 |
| 14 | +#define SFRAME_VERSION_2 2 |
| 15 | +#define SFRAME_MAGIC 0xdee2 |
| 16 | + |
| 17 | +/* Function Descriptor Entries are sorted on PC. */ |
| 18 | +#define SFRAME_F_FDE_SORTED 0x1 |
| 19 | +/* Frame-pointer based stack tracing. Defined, but not set. */ |
| 20 | +#define SFRAME_F_FRAME_POINTER 0x2 |
| 21 | + |
| 22 | +#define SFRAME_CFA_FIXED_FP_INVALID 0 |
| 23 | +#define SFRAME_CFA_FIXED_RA_INVALID 0 |
| 24 | + |
| 25 | +/* Supported ABIs/Arch. */ |
| 26 | +#define SFRAME_ABI_AARCH64_ENDIAN_BIG 1 /* AARCH64 big endian. */ |
| 27 | +#define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 /* AARCH64 little endian. */ |
| 28 | +#define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 /* AMD64 little endian. */ |
| 29 | + |
| 30 | +/* SFrame FRE types. */ |
| 31 | +#define SFRAME_FRE_TYPE_ADDR1 0 |
| 32 | +#define SFRAME_FRE_TYPE_ADDR2 1 |
| 33 | +#define SFRAME_FRE_TYPE_ADDR4 2 |
| 34 | + |
| 35 | +/* |
| 36 | + * SFrame Function Descriptor Entry types. |
| 37 | + * |
| 38 | + * The SFrame format has two possible representations for functions. The |
| 39 | + * choice of which type to use is made according to the instruction patterns |
| 40 | + * in the relevant program stub. |
| 41 | + */ |
| 42 | + |
| 43 | +/* Unwinders perform a (PC >= FRE_START_ADDR) to look up a matching FRE. */ |
| 44 | +#define SFRAME_FDE_TYPE_PCINC 0 |
| 45 | +/* |
| 46 | + * Unwinders perform a (PC & FRE_START_ADDR_AS_MASK >= FRE_START_ADDR_AS_MASK) |
| 47 | + * to look up a matching FRE. Typical usecases are pltN entries, trampolines |
| 48 | + * etc. |
| 49 | + */ |
| 50 | +#define SFRAME_FDE_TYPE_PCMASK 1 |
| 51 | + |
| 52 | +/** |
| 53 | + * struct sframe_preamble - SFrame Preamble. |
| 54 | + * @magic: Magic number (SFRAME_MAGIC). |
| 55 | + * @version: Format version number (SFRAME_VERSION). |
| 56 | + * @flags: Various flags. |
| 57 | + */ |
| 58 | +struct sframe_preamble { |
| 59 | + u16 magic; |
| 60 | + u8 version; |
| 61 | + u8 flags; |
| 62 | +} __packed; |
| 63 | + |
| 64 | +/** |
| 65 | + * struct sframe_header - SFrame Header. |
| 66 | + * @preamble: SFrame preamble. |
| 67 | + * @abi_arch: Identify the arch (including endianness) and ABI. |
| 68 | + * @cfa_fixed_fp_offset: Offset for the Frame Pointer (FP) from CFA may be |
| 69 | + * fixed for some ABIs ((e.g, in AMD64 when -fno-omit-frame-pointer is |
| 70 | + * used). When fixed, this field specifies the fixed stack frame offset |
| 71 | + * and the individual FREs do not need to track it. When not fixed, it |
| 72 | + * is set to SFRAME_CFA_FIXED_FP_INVALID, and the individual FREs may |
| 73 | + * provide the applicable stack frame offset, if any. |
| 74 | + * @cfa_fixed_ra_offset: Offset for the Return Address from CFA is fixed for |
| 75 | + * some ABIs. When fixed, this field specifies the fixed stack frame |
| 76 | + * offset and the individual FREs do not need to track it. When not |
| 77 | + * fixed, it is set to SFRAME_CFA_FIXED_FP_INVALID. |
| 78 | + * @auxhdr_len: Number of bytes making up the auxiliary header, if any. |
| 79 | + * Some ABI/arch, in the future, may use this space for extending the |
| 80 | + * information in SFrame header. Auxiliary header is contained in bytes |
| 81 | + * sequentially following the sframe_header. |
| 82 | + * @num_fdes: Number of SFrame FDEs in this SFrame section. |
| 83 | + * @num_fres: Number of SFrame Frame Row Entries. |
| 84 | + * @fre_len: Number of bytes in the SFrame Frame Row Entry section. |
| 85 | + * @fdes_off: Offset of SFrame Function Descriptor Entry section. |
| 86 | + * @fres_off: Offset of SFrame Frame Row Entry section. |
| 87 | + */ |
| 88 | +struct sframe_header { |
| 89 | + struct sframe_preamble preamble; |
| 90 | + u8 abi_arch; |
| 91 | + s8 cfa_fixed_fp_offset; |
| 92 | + s8 cfa_fixed_ra_offset; |
| 93 | + u8 auxhdr_len; |
| 94 | + u32 num_fdes; |
| 95 | + u32 num_fres; |
| 96 | + u32 fre_len; |
| 97 | + u32 fdes_off; |
| 98 | + u32 fres_off; |
| 99 | +} __packed; |
| 100 | + |
| 101 | +#define SFRAME_HDR_SIZE(sframe_hdr) \ |
| 102 | + ((sizeof(struct sframe_header) + (sframe_hdr).auxhdr_len)) |
| 103 | + |
| 104 | +/* Two possible keys for executable (instruction) pointers signing. */ |
| 105 | +#define SFRAME_AARCH64_PAUTH_KEY_A 0 /* Key A. */ |
| 106 | +#define SFRAME_AARCH64_PAUTH_KEY_B 1 /* Key B. */ |
| 107 | + |
| 108 | +/** |
| 109 | + * struct sframe_fde - SFrame Function Descriptor Entry. |
| 110 | + * @start_addr: Function start address. Encoded as a signed offset, |
| 111 | + * relative to the current FDE. |
| 112 | + * @size: Size of the function in bytes. |
| 113 | + * @fres_off: Offset of the first SFrame Frame Row Entry of the function, |
| 114 | + * relative to the beginning of the SFrame Frame Row Entry sub-section. |
| 115 | + * @fres_num: Number of frame row entries for the function. |
| 116 | + * @info: Additional information for deciphering the stack trace |
| 117 | + * information for the function. Contains information about SFrame FRE |
| 118 | + * type, SFrame FDE type, PAC authorization A/B key, etc. |
| 119 | + * @rep_size: Block size for SFRAME_FDE_TYPE_PCMASK |
| 120 | + * @padding: Unused |
| 121 | + */ |
| 122 | +struct sframe_fde { |
| 123 | + s32 start_addr; |
| 124 | + u32 size; |
| 125 | + u32 fres_off; |
| 126 | + u32 fres_num; |
| 127 | + u8 info; |
| 128 | + u8 rep_size; |
| 129 | + u16 padding; |
| 130 | +} __packed; |
| 131 | + |
| 132 | +/* |
| 133 | + * 'func_info' in SFrame FDE contains additional information for deciphering |
| 134 | + * the stack trace information for the function. In V1, the information is |
| 135 | + * organized as follows: |
| 136 | + * - 4-bits: Identify the FRE type used for the function. |
| 137 | + * - 1-bit: Identify the FDE type of the function - mask or inc. |
| 138 | + * - 1-bit: PAC authorization A/B key (aarch64). |
| 139 | + * - 2-bits: Unused. |
| 140 | + * --------------------------------------------------------------------- |
| 141 | + * | Unused | PAC auth A/B key (aarch64) | FDE type | FRE type | |
| 142 | + * | | Unused (amd64) | | | |
| 143 | + * --------------------------------------------------------------------- |
| 144 | + * 8 6 5 4 0 |
| 145 | + */ |
| 146 | + |
| 147 | +/* Note: Set PAC auth key to SFRAME_AARCH64_PAUTH_KEY_A by default. */ |
| 148 | +#define SFRAME_FUNC_INFO(fde_type, fre_enc_type) \ |
| 149 | + (((SFRAME_AARCH64_PAUTH_KEY_A & 0x1) << 5) | \ |
| 150 | + (((fde_type) & 0x1) << 4) | ((fre_enc_type) & 0xf)) |
| 151 | + |
| 152 | +#define SFRAME_FUNC_FRE_TYPE(data) ((data) & 0xf) |
| 153 | +#define SFRAME_FUNC_FDE_TYPE(data) (((data) >> 4) & 0x1) |
| 154 | +#define SFRAME_FUNC_PAUTH_KEY(data) (((data) >> 5) & 0x1) |
| 155 | + |
| 156 | +/* |
| 157 | + * Size of stack frame offsets in an SFrame Frame Row Entry. A single |
| 158 | + * SFrame FRE has all offsets of the same size. Offset size may vary |
| 159 | + * across frame row entries. |
| 160 | + */ |
| 161 | +#define SFRAME_FRE_OFFSET_1B 0 |
| 162 | +#define SFRAME_FRE_OFFSET_2B 1 |
| 163 | +#define SFRAME_FRE_OFFSET_4B 2 |
| 164 | + |
| 165 | +/* An SFrame Frame Row Entry can be SP or FP based. */ |
| 166 | +#define SFRAME_BASE_REG_FP 0 |
| 167 | +#define SFRAME_BASE_REG_SP 1 |
| 168 | + |
| 169 | +/* |
| 170 | + * The index at which a specific offset is presented in the variable length |
| 171 | + * bytes of an FRE. |
| 172 | + */ |
| 173 | +#define SFRAME_FRE_CFA_OFFSET_IDX 0 |
| 174 | +/* |
| 175 | + * The RA stack offset, if present, will always be at index 1 in the variable |
| 176 | + * length bytes of the FRE. |
| 177 | + */ |
| 178 | +#define SFRAME_FRE_RA_OFFSET_IDX 1 |
| 179 | +/* |
| 180 | + * The FP stack offset may appear at offset 1 or 2, depending on the ABI as RA |
| 181 | + * may or may not be tracked. |
| 182 | + */ |
| 183 | +#define SFRAME_FRE_FP_OFFSET_IDX 2 |
| 184 | + |
| 185 | +/* |
| 186 | + * 'fre_info' in SFrame FRE contains information about: |
| 187 | + * - 1 bit: base reg for CFA |
| 188 | + * - 4 bits: Number of offsets (N). A value of up to 3 is allowed to track |
| 189 | + * all three of CFA, FP and RA (fixed implicit order). |
| 190 | + * - 2 bits: information about size of the offsets (S) in bytes. |
| 191 | + * Valid values are SFRAME_FRE_OFFSET_1B, SFRAME_FRE_OFFSET_2B, |
| 192 | + * SFRAME_FRE_OFFSET_4B |
| 193 | + * - 1 bit: Mangled RA state bit (aarch64 only). |
| 194 | + * --------------------------------------------------------------- |
| 195 | + * | Mangled-RA (aarch64) | Size of | Number of | base_reg | |
| 196 | + * | Unused (amd64) | offsets | offsets | | |
| 197 | + * --------------------------------------------------------------- |
| 198 | + * 8 7 5 1 0 |
| 199 | + */ |
| 200 | + |
| 201 | +/* Note: Set mangled_ra_p to zero by default. */ |
| 202 | +#define SFRAME_FRE_INFO(base_reg_id, offset_num, offset_size) \ |
| 203 | + (((0 & 0x1) << 7) | (((offset_size) & 0x3) << 5) | \ |
| 204 | + (((offset_num) & 0xf) << 1) | ((base_reg_id) & 0x1)) |
| 205 | + |
| 206 | +/* Set the mangled_ra_p bit as indicated. */ |
| 207 | +#define SFRAME_FRE_INFO_UPDATE_MANGLED_RA_P(mangled_ra_p, fre_info) \ |
| 208 | + ((((mangled_ra_p) & 0x1) << 7) | ((fre_info) & 0x7f)) |
| 209 | + |
| 210 | +#define SFRAME_FRE_CFA_BASE_REG_ID(data) ((data) & 0x1) |
| 211 | +#define SFRAME_FRE_OFFSET_COUNT(data) (((data) >> 1) & 0xf) |
| 212 | +#define SFRAME_FRE_OFFSET_SIZE(data) (((data) >> 5) & 0x3) |
| 213 | +#define SFRAME_FRE_MANGLED_RA_P(data) (((data) >> 7) & 0x1) |
| 214 | + |
| 215 | +#endif /* _SFRAME_H */ |
0 commit comments