uint8_t sfd_ctx_abi_arch;
int8_t sfd_ctx_fixed_fp_offset;
int8_t sfd_ctx_fixed_ra_offset;
+ uint8_t dctx_version;
+ uint8_t ectx_version;
int encerr = 0;
struct elf_link_hash_table *htab;
if (!sfd_ctx_abi_arch)
return false;
- htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_1,
+ htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2,
0, /* SFrame flags. */
sfd_ctx_abi_arch,
sfd_ctx_fixed_fp_offset,
return false;
}
+ /* Check that all .sframe sections being linked have the same version. */
+ dctx_version = sframe_decoder_get_version (sfd_ctx);
+ ectx_version = sframe_encoder_get_version (sfe_ctx);
+ if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version)
+ {
+ _bfd_error_handler
+ (_("input SFrame sections with different format versions prevent"
+ " .sframe generation"));
+ return false;
+ }
+
+
/* Iterate over the function descriptor entries and the FREs of the
function from the decoder context. Add each of them to the encoder
context, if suitable. */
for (i = 0; i < num_fidx; i++)
{
unsigned int num_fres = 0;
- int32_t func_start_address;
+ int32_t func_start_addr;
bfd_vma address;
uint32_t func_size = 0;
unsigned char func_info = 0;
unsigned int r_offset = 0;
bool pltn_reloc_by_hand = false;
unsigned int pltn_r_offset = 0;
+ uint8_t rep_block_size = 0;
- if (!sframe_decoder_get_funcdesc (sfd_ctx, i, &num_fres, &func_size,
- &func_start_address, &func_info))
+ if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size,
+ &func_start_addr, &func_info,
+ &rep_block_size))
{
/* If function belongs to a deleted section, skip editing the
function descriptor entry. */
/* FIXME For testing only. Cleanup later. */
// address += (sec->output_section->vma);
- func_start_address = address;
+ func_start_addr = address;
}
/* Update the encoder context with updated content. */
- int err = sframe_encoder_add_funcdesc (sfe_ctx, func_start_address,
- func_size, func_info,
- num_fres);
+ int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr,
+ func_size, func_info,
+ rep_block_size, num_fres);
cur_fidx++;
BFD_ASSERT (!err);
}
break;
}
- *ectx = sframe_encode (SFRAME_VERSION_1,
+ *ectx = sframe_encode (SFRAME_VERSION_2,
0,
SFRAME_ABI_AMD64_ENDIAN_LITTLE,
SFRAME_CFA_FIXED_FP_INVALID,
{
/* Add SFrame FDE for plt0, the function start address is updated later
at _bfd_elf_merge_section_sframe time. */
- sframe_encoder_add_funcdesc (*ectx,
- 0, /* func start addr. */
- plt0_entry_size,
- func_info,
- 0 /* Num FREs. */);
+ sframe_encoder_add_funcdesc_v2 (*ectx,
+ 0, /* func start addr. */
+ plt0_entry_size,
+ func_info,
+ 16,
+ 0 /* Num FREs. */);
sframe_frame_row_entry plt0_fre;
unsigned int num_plt0_fres = htab->sframe_plt->plt0_num_fres;
for (unsigned int j = 0; j < num_plt0_fres; j++)
function start address = plt0_entry_size. As usual, this will be
updated later at _bfd_elf_merge_section_sframe, by when the
sections are relocated. */
- sframe_encoder_add_funcdesc (*ectx,
- plt0_entry_size, /* func start addr. */
- dpltsec->size - plt0_entry_size,
- func_info,
- 0 /* Num FREs. */);
+ sframe_encoder_add_funcdesc_v2 (*ectx,
+ plt0_entry_size, /* func start addr. */
+ dpltsec->size - plt0_entry_size,
+ func_info,
+ 16,
+ 0 /* Num FREs. */);
sframe_frame_row_entry pltn_fre;
/* Now add the FREs for pltn. Simply adding the two FREs suffices due
static void
sframe_set_version (uint32_t sframe_version ATTRIBUTE_UNUSED)
{
- sframe_ver_ops.format_version = SFRAME_VERSION_1;
+ sframe_ver_ops.format_version = SFRAME_VERSION_2;
+
+ /* These operations remain the same for SFRAME_VERSION_2 as fre_info and
+ func_info have not changed from SFRAME_VERSION_1. */
sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
#else
out_one (func_info);
#endif
+ out_one (0);
+ out_two (0);
}
static void
(void) sframe_seg;
/* Setup the version specific access functions. */
- sframe_set_version (SFRAME_VERSION_1);
+ sframe_set_version (SFRAME_VERSION_2);
/* Process all fdes and create SFrame stack trace information. */
create_sframe_all ();
Contents of the SFrame section .sframe:
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 3
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 2
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 2
Num FREs: 6
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 1
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 1
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 1
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 3
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 3
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 3
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 3
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 2
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 1
Num FREs: 4
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 0
Num FREs: 0
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 0
Num FREs: 0
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: NONE
Num FDEs: 0
Num FREs: 0
int32_t *func_start_address,
unsigned char *func_info);
+/* Get the data (NUM_FRES, FUNC_SIZE, FUNC_START_ADDRESS, FUNC_INFO,
+ REP_BLOCK_SIZE) from the function descriptor entry at index I'th
+ in the decoder CTX. If failed, return error code.
+ This API is only available from SFRAME_VERSION_2. */
+extern int
+sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *ctx,
+ unsigned int i,
+ uint32_t *num_fres,
+ uint32_t *func_size,
+ int32_t *func_start_address,
+ unsigned char *func_info,
+ uint8_t *rep_block_size);
+
/* SFrame textual dump. */
extern void
dump_sframe (sframe_decoder_ctx *decoder, uint64_t addr);
unsigned char func_info,
uint32_t num_fres);
+/* Add a new function descriptor entry with START_ADDR, FUNC_SIZE, FUNC_INFO
+ and REP_BLOCK_SIZE to the encoder. */
+extern int
+sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *encoder,
+ int32_t start_addr,
+ uint32_t func_size,
+ unsigned char func_info,
+ uint8_t rep_block_size,
+ uint32_t num_fres);
+
/* Serialize the contents of the encoder and return the buffer. ENCODED_SIZE
is updated to the size of the buffer. Sets ERRP if failure. */
extern char *
/* 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_1
+#define SFRAME_VERSION SFRAME_VERSION_2
/* Various flags for SFrame. */
------------------------------------------------------------------------
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. */
#source: sframe-bar.s
#objdump: --sframe=.sframe
#ld: -shared
-#name: SFrame Simple link
+#name: SFrame simple link
.*: file format .*
Contents of the SFrame section .sframe:
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: SFRAME_F_FDE_SORTED
Num FDEs: 2
Num FREs: 2
Contents of the SFrame section .sframe:
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: SFRAME_F_FDE_SORTED
#...
#source: sframe-bar.s
#objdump: --sframe=.sframe
#ld: -shared
-#name: SFrame Simple link
+#name: SFrame simple link
.*: +file format .*
Contents of the SFrame section .sframe:
Header :
- Version: SFRAME_VERSION_1
+ Version: SFRAME_VERSION_2
Flags: SFRAME_F_FDE_SORTED
#...
sframe_find_fre;
sframe_decoder_get_num_fidx;
sframe_decoder_get_funcdesc;
+ sframe_decoder_get_funcdesc_v2;
sframe_decoder_get_fre;
sframe_encode;
sframe_encoder_free;
sframe_encoder_get_num_fidx;
sframe_encoder_add_fre;
sframe_encoder_add_funcdesc;
+ sframe_encoder_add_funcdesc_v2;
sframe_encoder_write;
dump_sframe;
sframe_errmsg;
static void
dump_sframe_header (sframe_decoder_ctx *sfd_ctx)
{
- const char *verstr = NULL;
+ uint8_t ver;
+ uint8_t flags;
+ char *flags_str;
+ const char *ver_str = NULL;
const sframe_header *header = &(sfd_ctx->sfd_header);
/* Prepare SFrame section version string. */
const char *version_names[]
= { "NULL",
- "SFRAME_VERSION_1" };
- unsigned char ver = header->sfh_preamble.sfp_version;
+ "SFRAME_VERSION_1",
+ "SFRAME_VERSION_2" };
+
+ /* PS: Keep SFRAME_HEADER_FLAGS_STR_MAX_LEN in sync if adding more members to
+ this array. */
+ const char *flag_names[]
+ = { "SFRAME_F_FDE_SORTED",
+ "SFRAME_F_FRAME_POINTER" };
+
+ ver = sframe_decoder_get_version (sfd_ctx);
if (ver <= SFRAME_VERSION)
- verstr = version_names[ver];
+ ver_str = version_names[ver];
/* Prepare SFrame section flags string. */
- unsigned char flags = header->sfh_preamble.sfp_flags;
- char *flags_str
- = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN);
+ flags = header->sfh_preamble.sfp_flags;
+ flags_str = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN);
if (flags)
{
- const char *flag_names[]
- = { "SFRAME_F_FDE_SORTED",
- "SFRAME_F_FRAME_POINTER" };
- unsigned char flags = header->sfh_preamble.sfp_flags;
if (flags & SFRAME_F_FDE_SORTED)
strcpy (flags_str, flag_names[0]);
if (flags & SFRAME_F_FRAME_POINTER)
printf ("\n");
printf (" %s :\n", subsec_name);
printf ("\n");
- printf (" Version: %s\n", verstr);
+ printf (" Version: %s\n", ver_str);
printf (" Flags: %s\n", flags_str);
- printf (" Num FDEs: %d\n", header->sfh_num_fdes);
+ printf (" Num FDEs: %d\n", sframe_decoder_get_num_fidx (sfd_ctx));
printf (" Num FREs: %d\n", header->sfh_num_fres);
free (flags_str);
void
dump_sframe (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr)
{
+ uint8_t ver;
+
dump_sframe_header (sfd_ctx);
- dump_sframe_functions (sfd_ctx, sec_addr);
+
+ ver = sframe_decoder_get_version (sfd_ctx);
+ if (ver == SFRAME_VERSION)
+ dump_sframe_functions (sfd_ctx, sec_addr);
+ else
+ printf ("\n No further information can be displayed. %s",
+ "SFrame version not supported\n");
}
{
unsigned char all_flags = SFRAME_F_FDE_SORTED | SFRAME_F_FRAME_POINTER;
/* Check preamble is valid. */
- if ((hp->sfh_preamble.sfp_magic != SFRAME_MAGIC)
- || (hp->sfh_preamble.sfp_version != SFRAME_VERSION)
- || ((hp->sfh_preamble.sfp_flags | all_flags) != all_flags))
+ if (hp->sfh_preamble.sfp_magic != SFRAME_MAGIC
+ || (hp->sfh_preamble.sfp_version != SFRAME_VERSION_1
+ && hp->sfh_preamble.sfp_version != SFRAME_VERSION_2)
+ || (hp->sfh_preamble.sfp_flags | all_flags) != all_flags)
return false;
/* Check offsets are valid. */
{
int32_t start_ip, end_ip;
int32_t func_start_addr;
- uint32_t rep_block_size;
+ uint8_t rep_block_size;
uint32_t fde_type;
int32_t masked_pc;
bool mask_p;
bool ret;
ret = false;
- /* FIXME - the rep_block_size should be encoded in the format somehow. For
- AMD64, each pltN entry stub in .plt is 16 bytes. */
- rep_block_size = 16;
if (!fdep)
return ret;
func_start_addr = fdep->sfde_func_start_address;
fde_type = sframe_get_fde_type (fdep);
mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK);
+ rep_block_size = fdep->sfde_func_rep_size;
if (!mask_p)
{
return 0;
}
+int
+sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *dctx,
+ unsigned int i,
+ uint32_t *num_fres,
+ uint32_t *func_size,
+ int32_t *func_start_address,
+ unsigned char *func_info,
+ uint8_t *rep_block_size)
+{
+ sframe_func_desc_entry *fdp;
+ int err = 0;
+
+ if (dctx == NULL || func_start_address == NULL
+ || num_fres == NULL || func_size == NULL
+ || sframe_decoder_get_version (dctx) == SFRAME_VERSION_1)
+ return sframe_set_errno (&err, SFRAME_ERR_INVAL);
+
+ fdp = sframe_decoder_get_funcdesc_at_index (dctx, i);
+
+ if (fdp == NULL)
+ return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND);
+
+ *num_fres = fdp->sfde_func_num_fres;
+ *func_start_address = fdp->sfde_func_start_address;
+ *func_size = fdp->sfde_func_size;
+ *func_info = fdp->sfde_func_info;
+ *rep_block_size = fdp->sfde_func_rep_size;
+
+ return 0;
+}
/* Get the FRE_IDX'th FRE of the function at FUNC_IDX'th function
descriptor entry in the SFrame decoder CTX. Returns error code as
applicable. */
return -1;
}
+/* Add a new function descriptor entry with START_ADDR, FUNC_SIZE, FUNC_INFO
+ and REP_BLOCK_SIZE to the encoder.
+
+ This API is valid only for SFrame format version 2. */
+
+int
+sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *encoder,
+ int32_t start_addr,
+ uint32_t func_size,
+ unsigned char func_info,
+ uint8_t rep_block_size,
+ uint32_t num_fres __attribute__ ((unused)))
+{
+ sf_fde_tbl *fd_info;
+ int err;
+
+ if (encoder == NULL
+ || sframe_encoder_get_version (encoder) == SFRAME_VERSION_1)
+ return sframe_set_errno (&err, SFRAME_ERR_INVAL);
+
+ err = sframe_encoder_add_funcdesc (encoder, start_addr, func_size, func_info,
+ num_fres);
+ if (err)
+ return SFRAME_ERR;
+
+ fd_info = encoder->sfe_funcdesc;
+ fd_info->entry[fd_info->count-1].sfde_func_rep_size = rep_block_size;
+
+ return 0;
+}
+
static int
sframe_sort_funcdesc (sframe_encoder_ctx *encoder)
{
unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
SFRAME_FDE_TYPE_PCMASK);
/* 5 pltN entries of 16 bytes each. */
- err = sframe_encoder_add_funcdesc (ectx, 0x1000, 16*5, finfo, 3);
+ err = sframe_encoder_add_funcdesc_v2 (ectx, 0x1000, 16*5, finfo, 16, 3);
if (err == -1)
return err;