1*cb63e24eSchristos /* Public API to SFrame. 2*cb63e24eSchristos 3*cb63e24eSchristos Copyright (C) 2022-2024 Free Software Foundation, Inc. 4*cb63e24eSchristos 5*cb63e24eSchristos This file is part of libsframe. 6*cb63e24eSchristos 7*cb63e24eSchristos This program is free software; you can redistribute it and/or modify 8*cb63e24eSchristos it under the terms of the GNU General Public License as published by 9*cb63e24eSchristos the Free Software Foundation; either version 3 of the License, or 10*cb63e24eSchristos (at your option) any later version. 11*cb63e24eSchristos 12*cb63e24eSchristos This program is distributed in the hope that it will be useful, 13*cb63e24eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14*cb63e24eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*cb63e24eSchristos GNU General Public License for more details. 16*cb63e24eSchristos 17*cb63e24eSchristos You should have received a copy of the GNU General Public License 18*cb63e24eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19*cb63e24eSchristos 20*cb63e24eSchristos #ifndef _SFRAME_API_H 21*cb63e24eSchristos #define _SFRAME_API_H 22*cb63e24eSchristos 23*cb63e24eSchristos #include <sframe.h> 24*cb63e24eSchristos #include <stdbool.h> 25*cb63e24eSchristos 26*cb63e24eSchristos #ifdef __cplusplus 27*cb63e24eSchristos extern "C" 28*cb63e24eSchristos { 29*cb63e24eSchristos #endif 30*cb63e24eSchristos 31*cb63e24eSchristos typedef struct sframe_decoder_ctx sframe_decoder_ctx; 32*cb63e24eSchristos typedef struct sframe_encoder_ctx sframe_encoder_ctx; 33*cb63e24eSchristos 34*cb63e24eSchristos #define MAX_NUM_STACK_OFFSETS 3 35*cb63e24eSchristos 36*cb63e24eSchristos #define MAX_OFFSET_BYTES \ 37*cb63e24eSchristos ((SFRAME_FRE_OFFSET_4B * 2 * MAX_NUM_STACK_OFFSETS)) 38*cb63e24eSchristos 39*cb63e24eSchristos /* User interfacing SFrame Row Entry. 40*cb63e24eSchristos An abstraction provided by libsframe so the consumer is decoupled from 41*cb63e24eSchristos the binary format representation of the same. 42*cb63e24eSchristos 43*cb63e24eSchristos The members are best ordered such that they are aligned at their natural 44*cb63e24eSchristos boundaries. This helps avoid usage of undesirable misaligned memory 45*cb63e24eSchristos accesses. See PR libsframe/29856. */ 46*cb63e24eSchristos 47*cb63e24eSchristos typedef struct sframe_frame_row_entry 48*cb63e24eSchristos { 49*cb63e24eSchristos uint32_t fre_start_addr; 50*cb63e24eSchristos unsigned char fre_offsets[MAX_OFFSET_BYTES]; 51*cb63e24eSchristos unsigned char fre_info; 52*cb63e24eSchristos } sframe_frame_row_entry; 53*cb63e24eSchristos 54*cb63e24eSchristos #define SFRAME_ERR ((int) -1) 55*cb63e24eSchristos 56*cb63e24eSchristos /* This macro holds information about all the available SFrame 57*cb63e24eSchristos errors. It is used to form both an enum holding all the error 58*cb63e24eSchristos constants, and also the error strings themselves. To use, define 59*cb63e24eSchristos _SFRAME_FIRST and _SFRAME_ITEM to expand as you like, then 60*cb63e24eSchristos mention the macro name. See the enum after this for an example. */ 61*cb63e24eSchristos #define _SFRAME_ERRORS \ 62*cb63e24eSchristos _SFRAME_FIRST (SFRAME_ERR_VERSION_INVAL, "SFrame version not supported.") \ 63*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_NOMEM, "Out of Memory.") \ 64*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_INVAL, "Corrupt SFrame.") \ 65*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_BUF_INVAL, "Buffer does not contain SFrame data.") \ 66*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_DCTX_INVAL, "Corrupt SFrame decoder.") \ 67*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_ECTX_INVAL, "Corrupt SFrame encoder.") \ 68*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FDE_INVAL, "Corrput FDE.") \ 69*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FRE_INVAL, "Corrupt FRE.") \ 70*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FDE_NOTFOUND,"FDE not found.") \ 71*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FDE_NOTSORTED, "FDEs not sorted.") \ 72*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FRE_NOTFOUND,"FRE not found.") \ 73*cb63e24eSchristos _SFRAME_ITEM (SFRAME_ERR_FREOFFSET_NOPRESENT,"FRE offset not present.") 74*cb63e24eSchristos 75*cb63e24eSchristos #define SFRAME_ERR_BASE 2000 /* Base value for libsframe errnos. */ 76*cb63e24eSchristos 77*cb63e24eSchristos enum 78*cb63e24eSchristos { 79*cb63e24eSchristos #define _SFRAME_FIRST(NAME, STR) NAME = SFRAME_ERR_BASE 80*cb63e24eSchristos #define _SFRAME_ITEM(NAME, STR) , NAME 81*cb63e24eSchristos _SFRAME_ERRORS 82*cb63e24eSchristos #undef _SFRAME_ITEM 83*cb63e24eSchristos #undef _SFRAME_FIRST 84*cb63e24eSchristos }; 85*cb63e24eSchristos 86*cb63e24eSchristos /* Count of SFrame errors. */ 87*cb63e24eSchristos #define SFRAME_ERR_NERR (SFRAME_ERR_FREOFFSET_NOPRESENT - SFRAME_ERR_BASE + 1) 88*cb63e24eSchristos 89*cb63e24eSchristos /* Get the error message string. */ 90*cb63e24eSchristos 91*cb63e24eSchristos extern const char * 92*cb63e24eSchristos sframe_errmsg (int error); 93*cb63e24eSchristos 94*cb63e24eSchristos /* Create an FDE function info bye given an FRE_TYPE and an FDE_TYPE. */ 95*cb63e24eSchristos 96*cb63e24eSchristos extern unsigned char 97*cb63e24eSchristos sframe_fde_create_func_info (uint32_t fre_type, uint32_t fde_type); 98*cb63e24eSchristos 99*cb63e24eSchristos /* Gather the FRE type given the function size. */ 100*cb63e24eSchristos 101*cb63e24eSchristos extern uint32_t 102*cb63e24eSchristos sframe_calc_fre_type (size_t func_size); 103*cb63e24eSchristos 104*cb63e24eSchristos /* The SFrame Decoder. */ 105*cb63e24eSchristos 106*cb63e24eSchristos /* Decode the specified SFrame buffer CF_BUF of size CF_SIZE and return the 107*cb63e24eSchristos new SFrame decoder context. Sets ERRP for the caller if any error. */ 108*cb63e24eSchristos extern sframe_decoder_ctx * 109*cb63e24eSchristos sframe_decode (const char *cf_buf, size_t cf_size, int *errp); 110*cb63e24eSchristos 111*cb63e24eSchristos /* Free the decoder context. */ 112*cb63e24eSchristos extern void 113*cb63e24eSchristos sframe_decoder_free (sframe_decoder_ctx **dctx); 114*cb63e24eSchristos 115*cb63e24eSchristos /* Get the size of the SFrame header from the decoder context DCTX. */ 116*cb63e24eSchristos extern unsigned int 117*cb63e24eSchristos sframe_decoder_get_hdr_size (sframe_decoder_ctx *dctx); 118*cb63e24eSchristos 119*cb63e24eSchristos /* Get the SFrame's abi/arch info. */ 120*cb63e24eSchristos extern uint8_t 121*cb63e24eSchristos sframe_decoder_get_abi_arch (sframe_decoder_ctx *dctx); 122*cb63e24eSchristos 123*cb63e24eSchristos /* Get the format version from the SFrame decoder context DCTX. */ 124*cb63e24eSchristos extern uint8_t 125*cb63e24eSchristos sframe_decoder_get_version (sframe_decoder_ctx *dctx); 126*cb63e24eSchristos 127*cb63e24eSchristos /* Return the number of function descriptor entries in the SFrame decoder 128*cb63e24eSchristos DCTX. */ 129*cb63e24eSchristos extern uint32_t 130*cb63e24eSchristos sframe_decoder_get_num_fidx (sframe_decoder_ctx *dctx); 131*cb63e24eSchristos 132*cb63e24eSchristos /* Get the fixed FP offset from the decoder context DCTX. */ 133*cb63e24eSchristos extern int8_t 134*cb63e24eSchristos sframe_decoder_get_fixed_fp_offset (sframe_decoder_ctx *dctx); 135*cb63e24eSchristos 136*cb63e24eSchristos /* Get the fixed RA offset from the decoder context DCTX. */ 137*cb63e24eSchristos extern int8_t 138*cb63e24eSchristos sframe_decoder_get_fixed_ra_offset (sframe_decoder_ctx *dctx); 139*cb63e24eSchristos 140*cb63e24eSchristos /* Find the function descriptor entry which contains the specified address. 141*cb63e24eSchristos 142*cb63e24eSchristos Note: This function is deprecated and will be removed from future release 143*cb63e24eSchristos X+2 of the library. */ 144*cb63e24eSchristos extern void * 145*cb63e24eSchristos sframe_get_funcdesc_with_addr (sframe_decoder_ctx *dctx, int32_t addr, 146*cb63e24eSchristos int *errp); 147*cb63e24eSchristos 148*cb63e24eSchristos /* Find the SFrame Frame Row Entry which contains the PC. Returns 149*cb63e24eSchristos SFRAME_ERR if failure. */ 150*cb63e24eSchristos 151*cb63e24eSchristos extern int 152*cb63e24eSchristos sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, 153*cb63e24eSchristos sframe_frame_row_entry *frep); 154*cb63e24eSchristos 155*cb63e24eSchristos /* Get the FRE_IDX'th FRE of the function at FUNC_IDX'th function 156*cb63e24eSchristos index entry in the SFrame decoder CTX. Returns error code as 157*cb63e24eSchristos applicable. */ 158*cb63e24eSchristos extern int 159*cb63e24eSchristos sframe_decoder_get_fre (sframe_decoder_ctx *ctx, 160*cb63e24eSchristos unsigned int func_idx, 161*cb63e24eSchristos unsigned int fre_idx, 162*cb63e24eSchristos sframe_frame_row_entry *fre); 163*cb63e24eSchristos 164*cb63e24eSchristos /* Get the data (NUM_FRES, FUNC_START_ADDRESS) from the function 165*cb63e24eSchristos descriptor entry at index I'th in the decoder CTX. If failed, 166*cb63e24eSchristos return error code. */ 167*cb63e24eSchristos extern int 168*cb63e24eSchristos sframe_decoder_get_funcdesc (sframe_decoder_ctx *ctx, 169*cb63e24eSchristos unsigned int i, 170*cb63e24eSchristos uint32_t *num_fres, 171*cb63e24eSchristos uint32_t *func_size, 172*cb63e24eSchristos int32_t *func_start_address, 173*cb63e24eSchristos unsigned char *func_info); 174*cb63e24eSchristos 175*cb63e24eSchristos /* Get the data (NUM_FRES, FUNC_SIZE, FUNC_START_ADDRESS, FUNC_INFO, 176*cb63e24eSchristos REP_BLOCK_SIZE) from the function descriptor entry at index I'th 177*cb63e24eSchristos in the decoder CTX. If failed, return error code. 178*cb63e24eSchristos This API is only available from SFRAME_VERSION_2. */ 179*cb63e24eSchristos extern int 180*cb63e24eSchristos sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *ctx, 181*cb63e24eSchristos unsigned int i, 182*cb63e24eSchristos uint32_t *num_fres, 183*cb63e24eSchristos uint32_t *func_size, 184*cb63e24eSchristos int32_t *func_start_address, 185*cb63e24eSchristos unsigned char *func_info, 186*cb63e24eSchristos uint8_t *rep_block_size); 187*cb63e24eSchristos 188*cb63e24eSchristos /* SFrame textual dump. */ 189*cb63e24eSchristos extern void 190*cb63e24eSchristos dump_sframe (sframe_decoder_ctx *decoder, uint64_t addr); 191*cb63e24eSchristos 192*cb63e24eSchristos /* Get the base reg id from the FRE info. Sets errp if fails. */ 193*cb63e24eSchristos extern uint8_t 194*cb63e24eSchristos sframe_fre_get_base_reg_id (sframe_frame_row_entry *fre, int *errp); 195*cb63e24eSchristos 196*cb63e24eSchristos /* Get the CFA offset from the FRE. If the offset is invalid, sets errp. */ 197*cb63e24eSchristos extern int32_t 198*cb63e24eSchristos sframe_fre_get_cfa_offset (sframe_decoder_ctx *dtcx, 199*cb63e24eSchristos sframe_frame_row_entry *fre, int *errp); 200*cb63e24eSchristos 201*cb63e24eSchristos /* Get the FP offset from the FRE. If the offset is invalid, sets errp. */ 202*cb63e24eSchristos extern int32_t 203*cb63e24eSchristos sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx, 204*cb63e24eSchristos sframe_frame_row_entry *fre, int *errp); 205*cb63e24eSchristos 206*cb63e24eSchristos /* Get the RA offset from the FRE. If the offset is invalid, sets errp. */ 207*cb63e24eSchristos extern int32_t 208*cb63e24eSchristos sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx, 209*cb63e24eSchristos sframe_frame_row_entry *fre, int *errp); 210*cb63e24eSchristos 211*cb63e24eSchristos /* Get whether the RA is mangled. */ 212*cb63e24eSchristos 213*cb63e24eSchristos extern bool 214*cb63e24eSchristos sframe_fre_get_ra_mangled_p (sframe_decoder_ctx *dctx, 215*cb63e24eSchristos sframe_frame_row_entry *fre, int *errp); 216*cb63e24eSchristos 217*cb63e24eSchristos /* The SFrame Encoder. */ 218*cb63e24eSchristos 219*cb63e24eSchristos /* Create an encoder context with the given SFrame format version VER, FLAGS 220*cb63e24eSchristos and ABI information. Sets errp if failure. */ 221*cb63e24eSchristos extern sframe_encoder_ctx * 222*cb63e24eSchristos sframe_encode (uint8_t ver, uint8_t flags, uint8_t abi_arch, 223*cb63e24eSchristos int8_t fixed_fp_offset, int8_t fixed_ra_offset, int *errp); 224*cb63e24eSchristos 225*cb63e24eSchristos /* Free the encoder context. */ 226*cb63e24eSchristos extern void 227*cb63e24eSchristos sframe_encoder_free (sframe_encoder_ctx **encoder); 228*cb63e24eSchristos 229*cb63e24eSchristos /* Get the size of the SFrame header from the encoder ctx ENCODER. */ 230*cb63e24eSchristos extern unsigned int 231*cb63e24eSchristos sframe_encoder_get_hdr_size (sframe_encoder_ctx *encoder); 232*cb63e24eSchristos 233*cb63e24eSchristos /* Get the abi/arch info from the SFrame encoder context CTX. */ 234*cb63e24eSchristos extern uint8_t 235*cb63e24eSchristos sframe_encoder_get_abi_arch (sframe_encoder_ctx *encoder); 236*cb63e24eSchristos 237*cb63e24eSchristos /* Get the format version from the SFrame encoder context ENCODER. */ 238*cb63e24eSchristos extern uint8_t 239*cb63e24eSchristos sframe_encoder_get_version (sframe_encoder_ctx *encoder); 240*cb63e24eSchristos 241*cb63e24eSchristos /* Return the number of function descriptor entries in the SFrame encoder 242*cb63e24eSchristos ENCODER. */ 243*cb63e24eSchristos extern uint32_t 244*cb63e24eSchristos sframe_encoder_get_num_fidx (sframe_encoder_ctx *encoder); 245*cb63e24eSchristos 246*cb63e24eSchristos /* Add an FRE to function at FUNC_IDX'th function descriptor index entry in 247*cb63e24eSchristos the encoder context. */ 248*cb63e24eSchristos extern int 249*cb63e24eSchristos sframe_encoder_add_fre (sframe_encoder_ctx *encoder, 250*cb63e24eSchristos unsigned int func_idx, 251*cb63e24eSchristos sframe_frame_row_entry *frep); 252*cb63e24eSchristos 253*cb63e24eSchristos /* Add a new function descriptor entry with START_ADDR, FUNC_SIZE and NUM_FRES 254*cb63e24eSchristos to the encoder. */ 255*cb63e24eSchristos extern int 256*cb63e24eSchristos sframe_encoder_add_funcdesc (sframe_encoder_ctx *encoder, 257*cb63e24eSchristos int32_t start_addr, 258*cb63e24eSchristos uint32_t func_size, 259*cb63e24eSchristos unsigned char func_info, 260*cb63e24eSchristos uint32_t num_fres); 261*cb63e24eSchristos 262*cb63e24eSchristos /* Add a new function descriptor entry with START_ADDR, FUNC_SIZE, FUNC_INFO 263*cb63e24eSchristos and REP_BLOCK_SIZE to the encoder. */ 264*cb63e24eSchristos extern int 265*cb63e24eSchristos sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *encoder, 266*cb63e24eSchristos int32_t start_addr, 267*cb63e24eSchristos uint32_t func_size, 268*cb63e24eSchristos unsigned char func_info, 269*cb63e24eSchristos uint8_t rep_block_size, 270*cb63e24eSchristos uint32_t num_fres); 271*cb63e24eSchristos 272*cb63e24eSchristos /* Serialize the contents of the encoder and return the buffer. ENCODED_SIZE 273*cb63e24eSchristos is updated to the size of the buffer. Sets ERRP if failure. */ 274*cb63e24eSchristos extern char * 275*cb63e24eSchristos sframe_encoder_write (sframe_encoder_ctx *encoder, 276*cb63e24eSchristos size_t *encoded_size, int *errp); 277*cb63e24eSchristos 278*cb63e24eSchristos #ifdef __cplusplus 279*cb63e24eSchristos } 280*cb63e24eSchristos #endif 281*cb63e24eSchristos 282*cb63e24eSchristos #endif /* _SFRAME_API_H */ 283