binutils (2.41)

(root)/
include/
sframe.h
       1  /* SFrame format description.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of libsframe.
       5  
       6     libsframe is free software; you can redistribute it and/or modify it
       7     under the terms of the GNU General Public License as published by the Free
       8     Software Foundation; either version 3, or (at your option) any later
       9     version.
      10  
      11     This program is distributed in the hope that it will be useful, but
      12     WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14     See the GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; see the file COPYING.  If not see
      18     <http://www.gnu.org/licenses/>.  */
      19  
      20  #ifndef	_SFRAME_H
      21  #define	_SFRAME_H
      22  
      23  #include <sys/types.h>
      24  #include <limits.h>
      25  #include <stdint.h>
      26  
      27  #include "ansidecl.h"
      28  
      29  #ifdef	__cplusplus
      30  extern "C"
      31  {
      32  #endif
      33  
      34  /* SFrame format.
      35  
      36     SFrame format is a simple format to represent the information needed
      37     for generating vanilla backtraces.  SFrame format keeps track of the
      38     minimal necessary information needed for stack tracing:
      39       - Canonical Frame Address (CFA)
      40       - Frame Pointer (FP)
      41       - Return Address (RA)
      42  
      43     The SFrame section itself has the following structure:
      44  
      45         +--------+------------+---------+
      46         |  file  |  function  | frame   |
      47         | header | descriptor |  row    |
      48         |        |   entries  | entries |
      49         +--------+------------+---------+
      50  
      51     The file header stores a magic number and version information, flags, and
      52     the byte offset of each of the sections relative to the end of the header
      53     itself.  The file header also specifies the total number of Function
      54     Descriptor Entries, Frame Row Entries and length of the FRE sub-section.
      55  
      56     Following the header is a list of Function Descriptor Entries (FDEs).
      57     This list may be sorted if the flags in the file header indicate it to be
      58     so.  The sort order, if applicable, is the order of functions in the
      59     .text.* sections in the resulting binary artifact.  Each Function
      60     Descriptor Entry specifies the start PC of a function, the size in bytes
      61     of the function and an offset to its first Frame Row Entry (FRE).  Each FDE
      62     additionally also specifies the type of FRE it uses to encode the stack
      63     trace information.
      64  
      65     Next, the SFrame Frame Row Entry sub-section is a list of variable size
      66     records.  Each entry represents stack trace information for a set of PCs
      67     of the function.  A singular Frame Row Entry is a self-sufficient record
      68     which contains information on how to generate stack trace from the
      69     applicable set of PCs.
      70  
      71     */
      72  
      73  
      74  /* SFrame format versions.  */
      75  #define SFRAME_VERSION_1	1
      76  #define SFRAME_VERSION_2	2
      77  /* SFrame magic number.  */
      78  #define SFRAME_MAGIC		0xdee2
      79  /* Current version of SFrame format.  */
      80  #define SFRAME_VERSION	SFRAME_VERSION_2
      81  
      82  /* Various flags for SFrame.  */
      83  
      84  /* Function Descriptor Entries are sorted on PC.  */
      85  #define SFRAME_F_FDE_SORTED	0x1
      86  /* Functions preserve frame pointer.  */
      87  #define SFRAME_F_FRAME_POINTER 0x2
      88  
      89  #define SFRAME_CFA_FIXED_FP_INVALID 0
      90  #define SFRAME_CFA_FIXED_RA_INVALID 0
      91  
      92  /* Supported ABIs/Arch.  */
      93  #define SFRAME_ABI_AARCH64_ENDIAN_BIG      1 /* AARCH64 big endian.  */
      94  #define SFRAME_ABI_AARCH64_ENDIAN_LITTLE   2 /* AARCH64 little endian.  */
      95  #define SFRAME_ABI_AMD64_ENDIAN_LITTLE     3 /* AMD64 little endian.  */
      96  
      97  /* SFrame FRE types.  */
      98  #define SFRAME_FRE_TYPE_ADDR1	0
      99  #define SFRAME_FRE_TYPE_ADDR2	1
     100  #define SFRAME_FRE_TYPE_ADDR4	2
     101  
     102  /* SFrame Function Descriptor Entry types.
     103  
     104     The SFrame format has two possible representations for functions.  The
     105     choice of which type to use is made according to the instruction patterns
     106     in the relevant program stub.
     107  
     108     An SFrame FDE of type SFRAME_FDE_TYPE_PCINC is an indication
     109     that the PCs in the FREs should be treated as increments in bytes.  This is
     110     used for a bulk of the executable code of a program, which contains
     111     instructions with no specific pattern.
     112  
     113     An SFrame FDE of type SFRAME_FDE_TYPE_PCMASK is an indication
     114     that the PCs in the FREs should be treated as masks.  This type is useful
     115     for the cases when a small pattern of instructions in a program stub is
     116     repeatedly to cover a specific functionality.  Typical usescases are pltN
     117     entries, trampolines etc.  */
     118  
     119  /* Unwinders perform a (PC >= FRE_START_ADDR) to look up a matching FRE.  */
     120  #define SFRAME_FDE_TYPE_PCINC   0
     121  /* Unwinders perform a (PC % REP_BLOCK_SIZE >= FRE_START_ADDR) to look up a
     122     matching FRE.  */
     123  #define SFRAME_FDE_TYPE_PCMASK  1
     124  
     125  typedef struct sframe_preamble
     126  {
     127    uint16_t sfp_magic;	/* Magic number (SFRAME_MAGIC).  */
     128    uint8_t sfp_version;	/* Data format version number (SFRAME_VERSION).  */
     129    uint8_t sfp_flags;	/* Flags.  */
     130  } ATTRIBUTE_PACKED sframe_preamble;
     131  
     132  typedef struct sframe_header
     133  {
     134    sframe_preamble sfh_preamble;
     135    /* Information about the arch (endianness) and ABI.  */
     136    uint8_t sfh_abi_arch;
     137    /* Offset for the Frame Pointer (FP) from CFA may be fixed for some
     138       ABIs (e.g, in AMD64 when -fno-omit-frame-pointer is used).  When fixed,
     139       this field specifies the fixed stack frame offset and the individual
     140       FREs do not need to track it.  When not fixed, it is set to
     141       SFRAME_CFA_FIXED_FP_INVALID, and the individual FREs may provide
     142       the applicable stack frame offset, if any.  */
     143    int8_t sfh_cfa_fixed_fp_offset;
     144    /* Offset for the Return Address from CFA is fixed for some ABIs
     145       (e.g., AMD64 has it as CFA-8).  When fixed, the header specifies the
     146       fixed stack frame offset and the individual FREs do not track it.  When
     147       not fixed, it is set to SFRAME_CFA_FIXED_RA_INVALID, and individual
     148       FREs provide the applicable stack frame offset, if any.  */
     149    int8_t sfh_cfa_fixed_ra_offset;
     150    /* Number of bytes making up the auxiliary header, if any.
     151       Some ABI/arch, in the future, may use this space for extending the
     152       information in SFrame header.  Auxiliary header is contained in
     153       bytes sequentially following the sframe_header.  */
     154    uint8_t sfh_auxhdr_len;
     155    /* Number of SFrame FDEs in this SFrame section.  */
     156    uint32_t sfh_num_fdes;
     157    /* Number of SFrame Frame Row Entries.  */
     158    uint32_t sfh_num_fres;
     159    /* Number of bytes in the SFrame Frame Row Entry section. */
     160    uint32_t sfh_fre_len;
     161    /* Offset of SFrame Function Descriptor Entry section.  */
     162    uint32_t sfh_fdeoff;
     163    /* Offset of SFrame Frame Row Entry section.  */
     164    uint32_t sfh_freoff;
     165  } ATTRIBUTE_PACKED sframe_header;
     166  
     167  #define SFRAME_V1_HDR_SIZE(sframe_hdr)	\
     168    ((sizeof (sframe_header) + (sframe_hdr).sfh_auxhdr_len))
     169  
     170  /* Two possible keys for executable (instruction) pointers signing.  */
     171  #define SFRAME_AARCH64_PAUTH_KEY_A    0 /* Key A.  */
     172  #define SFRAME_AARCH64_PAUTH_KEY_B    1 /* Key B.  */
     173  
     174  typedef struct sframe_func_desc_entry
     175  {
     176    /* Function start address.  Encoded as a signed offset, relative to the
     177       beginning of the current FDE.  */
     178    int32_t sfde_func_start_address;
     179    /* Size of the function in bytes.  */
     180    uint32_t sfde_func_size;
     181    /* Offset of the first SFrame Frame Row Entry of the function, relative to the
     182       beginning of the SFrame Frame Row Entry sub-section.  */
     183    uint32_t sfde_func_start_fre_off;
     184    /* Number of frame row entries for the function.  */
     185    uint32_t sfde_func_num_fres;
     186    /* Additional information for stack tracing from the function:
     187       - 4-bits: Identify the FRE type used for the function.
     188       - 1-bit: Identify the FDE type of the function - mask or inc.
     189       - 1-bit: PAC authorization A/B key (aarch64).
     190       - 2-bits: Unused.
     191       ------------------------------------------------------------------------
     192       |     Unused    |  PAC auth A/B key (aarch64) |  FDE type |   FRE type   |
     193       |               |        Unused (amd64)       |           |              |
     194       ------------------------------------------------------------------------
     195       8               6                             5           4              0     */
     196    uint8_t sfde_func_info;
     197    /* Size of the block of repeating insns.  Used for SFrame FDEs of type
     198       SFRAME_FDE_TYPE_PCMASK.  */
     199    uint8_t sfde_func_rep_size;
     200    uint16_t sfde_func_padding2;
     201  } ATTRIBUTE_PACKED sframe_func_desc_entry;
     202  
     203  /* Macros to compose and decompose function info in FDE.  */
     204  
     205  /* Note: Set PAC auth key to SFRAME_AARCH64_PAUTH_KEY_A by default.  */
     206  #define SFRAME_V1_FUNC_INFO(fde_type, fre_enc_type) \
     207    (((SFRAME_AARCH64_PAUTH_KEY_A & 0x1) << 5) | \
     208     (((fde_type) & 0x1) << 4) | ((fre_enc_type) & 0xf))
     209  
     210  #define SFRAME_V1_FUNC_FRE_TYPE(data)	  ((data) & 0xf)
     211  #define SFRAME_V1_FUNC_FDE_TYPE(data)	  (((data) >> 4) & 0x1)
     212  #define SFRAME_V1_FUNC_PAUTH_KEY(data)	  (((data) >> 5) & 0x1)
     213  
     214  /* Set the pauth key as indicated.  */
     215  #define SFRAME_V1_FUNC_INFO_UPDATE_PAUTH_KEY(pauth_key, fde_info) \
     216    ((((pauth_key) & 0x1) << 5) | ((fde_info) & 0xdf))
     217  
     218  /* Size of stack frame offsets in an SFrame Frame Row Entry.  A single
     219     SFrame FRE has all offsets of the same size.  Offset size may vary
     220     across frame row entries.  */
     221  #define SFRAME_FRE_OFFSET_1B	  0
     222  #define SFRAME_FRE_OFFSET_2B	  1
     223  #define SFRAME_FRE_OFFSET_4B	  2
     224  
     225  /* An SFrame Frame Row Entry can be SP or FP based.  */
     226  #define SFRAME_BASE_REG_FP	0
     227  #define SFRAME_BASE_REG_SP	1
     228  
     229  /* The index at which a specific offset is presented in the variable length
     230     bytes of an FRE.  */
     231  #define SFRAME_FRE_CFA_OFFSET_IDX   0
     232  /* The RA stack offset, if present, will always be at index 1 in the variable
     233     length bytes of the FRE.  */
     234  #define SFRAME_FRE_RA_OFFSET_IDX    1
     235  /* The FP stack offset may appear at offset 1 or 2, depending on the ABI as RA
     236     may or may not be tracked.  */
     237  #define SFRAME_FRE_FP_OFFSET_IDX    2
     238  
     239  typedef struct sframe_fre_info
     240  {
     241    /* Information about
     242       - 1 bit: base reg for CFA
     243       - 4 bits: Number of offsets (N).  A value of upto 3 is allowed to track
     244       all three of CFA, FP and RA (fixed implicit order).
     245       - 2 bits: information about size of the offsets (S) in bytes.
     246       Valid values are SFRAME_FRE_OFFSET_1B, SFRAME_FRE_OFFSET_2B,
     247       SFRAME_FRE_OFFSET_4B
     248       - 1 bit: Mangled RA state bit (aarch64 only).
     249       ----------------------------------------------------------------------------------
     250       | Mangled-RA (aarch64) |  Size of offsets   |   Number of offsets    |   base_reg |
     251       |  Unused (amd64)      |                    |                        |            |
     252       ----------------------------------------------------------------------------------
     253       8                     7                    5                        1            0
     254  
     255       */
     256    uint8_t fre_info;
     257  } sframe_fre_info;
     258  
     259  /* Macros to compose and decompose FRE info.  */
     260  
     261  /* Note: Set mangled_ra_p to zero by default.  */
     262  #define SFRAME_V1_FRE_INFO(base_reg_id, offset_num, offset_size) \
     263    (((0 & 0x1) << 7) | (((offset_size) & 0x3) << 5) | \
     264     (((offset_num) & 0xf) << 1) | ((base_reg_id) & 0x1))
     265  
     266  /* Set the mangled_ra_p bit as indicated.  */
     267  #define SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P(mangled_ra_p, fre_info) \
     268    ((((mangled_ra_p) & 0x1) << 7) | ((fre_info) & 0x7f))
     269  
     270  #define SFRAME_V1_FRE_CFA_BASE_REG_ID(data)	  ((data) & 0x1)
     271  #define SFRAME_V1_FRE_OFFSET_COUNT(data)	  (((data) >> 1) & 0xf)
     272  #define SFRAME_V1_FRE_OFFSET_SIZE(data)		  (((data) >> 5) & 0x3)
     273  #define SFRAME_V1_FRE_MANGLED_RA_P(data)	  (((data) >> 7) & 0x1)
     274  
     275  /* SFrame Frame Row Entry definitions.
     276  
     277     Used for both AMD64 and AARCH64.
     278  
     279     An SFrame Frame Row Entry is a self-sufficient record which contains
     280     information on how to generate the stack trace for the specified range of
     281     PCs.  Each SFrame Frame Row Entry is followed by S*N bytes, where:
     282       S is the size of the stack frame offset for the FRE, and
     283       N is the number of stack frame offsets in the FRE
     284  
     285     The offsets are interpreted in order as follows:
     286  
     287      offset1 (interpreted as CFA = BASE_REG + offset1)
     288  
     289      if RA is being tracked
     290        offset2 (interpreted as RA = CFA + offset2)
     291        if FP is being tracked
     292  	offset3 (intrepreted as FP = CFA + offset2)
     293        fi
     294      else
     295        if FP is being tracked
     296  	offset2 (intrepreted as FP = CFA + offset2)
     297        fi
     298      fi
     299  */
     300  
     301  /* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type.  */
     302  typedef struct sframe_frame_row_entry_addr1
     303  {
     304    /* Start address of the frame row entry.  Encoded as an 1-byte unsigned
     305       offset, relative to the start address of the function.  */
     306    uint8_t sfre_start_address;
     307    sframe_fre_info sfre_info;
     308  } ATTRIBUTE_PACKED sframe_frame_row_entry_addr1;
     309  
     310  /* Upper limit of start address in sframe_frame_row_entry_addr1
     311     is 0x100 (not inclusive).  */
     312  #define SFRAME_FRE_TYPE_ADDR1_LIMIT   \
     313    (1ULL << ((SFRAME_FRE_TYPE_ADDR1 + 1) * 8))
     314  
     315  /* Used when SFRAME_FRE_TYPE_ADDR2 is specified as FRE type.  */
     316  typedef struct sframe_frame_row_entry_addr2
     317  {
     318    /* Start address of the frame row entry.  Encoded as an 2-byte unsigned
     319       offset, relative to the start address of the function.  */
     320    uint16_t sfre_start_address;
     321    sframe_fre_info sfre_info;
     322  } ATTRIBUTE_PACKED sframe_frame_row_entry_addr2;
     323  
     324  /* Upper limit of start address in sframe_frame_row_entry_addr2
     325     is 0x10000 (not inclusive).  */
     326  #define SFRAME_FRE_TYPE_ADDR2_LIMIT   \
     327    (1ULL << ((SFRAME_FRE_TYPE_ADDR2 * 2) * 8))
     328  
     329  /* Used when SFRAME_FRE_TYPE_ADDR4 is specified as FRE type.  */
     330  typedef struct sframe_frame_row_entry_addr4
     331  {
     332    /* Start address of the frame row entry.  Encoded as a 4-byte unsigned
     333       offset, relative to the start address of the function.  */
     334    uint32_t sfre_start_address;
     335    sframe_fre_info sfre_info;
     336  } ATTRIBUTE_PACKED sframe_frame_row_entry_addr4;
     337  
     338  /* Upper limit of start address in sframe_frame_row_entry_addr2
     339     is 0x100000000 (not inclusive).  */
     340  #define SFRAME_FRE_TYPE_ADDR4_LIMIT   \
     341    (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8))
     342  
     343  #ifdef	__cplusplus
     344  }
     345  #endif
     346  
     347  #endif				/* _SFRAME_H */