@@ -251,7 +251,7 @@ fre_offset_func_map[SFRAME_FRE_OFFSET_FUNC_MAP_INDEX_MAX+1] =
static struct sframe_version_ops sframe_ver_ops;
/* SFrame (SFRAME_VERSION_1) set FRE info. */
-
+/*
static unsigned char
sframe_v1_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
unsigned int offset_size, bool mangled_ra_p)
@@ -261,6 +261,19 @@ sframe_v1_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
return fre_info;
}
+*/
+
+/* SFrame (SFRAME_VERSION_2) set FRE info. */
+
+static unsigned char
+sframe_v2_set_fre_info (unsigned int base_reg, unsigned int offset_flags,
+ unsigned int offset_size, bool mangled_ra_p)
+{
+ unsigned char fre_info;
+ fre_info = SFRAME_V2_FRE_INFO (base_reg, offset_flags, offset_size);
+ fre_info = SFRAME_V1_FRE_INFO_UPDATE_MANGLED_RA_P (mangled_ra_p, fre_info);
+ return fre_info;
+}
/* SFrame (SFRAME_VERSION_1) set function info. */
static unsigned char
@@ -280,10 +293,10 @@ sframe_set_version (uint32_t sframe_version ATTRIBUTE_UNUSED)
{
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_v2_set_fre_info;
- sframe_ver_ops.set_fre_info = sframe_v1_set_fre_info;
+ /* This operation remains the same for SFRAME_VERSION_2 as func_info
+ has not changed from SFRAME_VERSION_1. */
sframe_ver_ops.set_func_info = sframe_v1_set_func_info;
}
@@ -291,10 +304,10 @@ sframe_set_version (uint32_t sframe_version ATTRIBUTE_UNUSED)
/* SFrame set FRE info. */
static unsigned char
-sframe_set_fre_info (unsigned int base_reg, unsigned int num_offsets,
+sframe_set_fre_info (unsigned int base_reg, unsigned int offset_count_or_flags,
unsigned int offset_size, bool mangled_ra_p)
{
- return sframe_ver_ops.set_fre_info (base_reg, num_offsets,
+ return sframe_ver_ops.set_fre_info (base_reg, offset_count_or_flags,
offset_size, mangled_ra_p);
}
@@ -353,6 +366,24 @@ get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
return fre_num_offsets;
}
+/* Get offset flags necessary for the SFrame Frame Row Entry. */
+
+static unsigned int
+get_fre_offset_flags (struct sframe_row_entry *sframe_fre)
+{
+ /* CFA offset must always be present. */
+ unsigned int fre_offset_flags = 1 << SFRAME_FRE_CFA_OFFSET_IDX;
+
+ if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
+ fre_offset_flags |= 1 << SFRAME_FRE_FP_OFFSET_IDX;
+#ifdef SFRAME_FRE_RA_TRACKING
+ if (sframe_ra_tracking_p ()
+ && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
+ fre_offset_flags |= 1 << SFRAME_FRE_RA_OFFSET_IDX;
+#endif
+ return fre_offset_flags;
+}
+
/* Get the minimum necessary offset size (in bytes) for this
SFrame frame row entry. */
@@ -494,6 +525,7 @@ output_sframe_row_entry (symbolS *fde_start_addr,
{
unsigned char fre_info;
unsigned int fre_num_offsets;
+ unsigned int fre_offset_flags;
unsigned int fre_offset_size;
unsigned int fre_base_reg;
expressionS exp;
@@ -524,8 +556,9 @@ output_sframe_row_entry (symbolS *fde_start_addr,
size of offset in this frame row entry. */
fre_base_reg = get_fre_base_reg_id (sframe_fre);
fre_num_offsets = get_fre_num_offsets (sframe_fre);
+ fre_offset_flags = get_fre_offset_flags (sframe_fre);
fre_offset_size = sframe_get_fre_offset_size (sframe_fre);
- fre_info = sframe_set_fre_info (fre_base_reg, fre_num_offsets,
+ fre_info = sframe_set_fre_info (fre_base_reg, fre_offset_flags,
fre_offset_size, sframe_fre->mangled_ra_p);
out_one (fre_info);
@@ -1497,25 +1530,6 @@ sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
= get_dw_fde_end_addrS (xlate_ctx->dw_fde);
}
-#ifdef SFRAME_FRE_RA_TRACKING
- if (sframe_ra_tracking_p ())
- {
- struct sframe_row_entry *fre;
-
- /* Iterate over the scratchpad FREs and validate them. */
- for (fre = xlate_ctx->first_fre; fre; fre = fre->next)
- {
- /* SFrame format cannot represent FP on stack without RA on stack. */
- if (fre->ra_loc != SFRAME_FRE_ELEM_LOC_STACK
- && fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
- {
- as_warn (_("skipping SFrame FDE due to FP without RA on stack"));
- return SFRAME_XLATE_ERR_NOTREPRESENTED;
- }
- }
- }
-#endif /* SFRAME_FRE_RA_TRACKING */
-
return SFRAME_XLATE_OK;
}
@@ -241,14 +241,14 @@ 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).
+ - 4 bits: Flags for offsets. Upto 3 are allowed to track
+ all three of CFA, FP and RA (fixed 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 |
+ | Mangled-RA (aarch64) | Size of offsets | Flags for offsets | base_reg |
| Unused (amd64, s390) | | | |
----------------------------------------------------------------------------------
8 7 5 1 0
@@ -264,6 +264,11 @@ typedef struct sframe_fre_info
(((0 & 0x1) << 7) | (((offset_size) & 0x3) << 5) | \
(((offset_num) & 0xf) << 1) | ((base_reg_id) & 0x1))
+/* Note: Set mangled_ra_p to zero by default. */
+#define SFRAME_V2_FRE_INFO(base_reg_id, offset_flags, offset_size) \
+ (((0 & 0x1) << 7) | (((offset_size) & 0x3) << 5) | \
+ (((offset_flags) & 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))
@@ -273,6 +278,8 @@ typedef struct sframe_fre_info
#define SFRAME_V1_FRE_OFFSET_SIZE(data) (((data) >> 5) & 0x3)
#define SFRAME_V1_FRE_MANGLED_RA_P(data) (((data) >> 7) & 0x1)
+#define SFRAME_V2_FRE_OFFSET_FLAGS(data) (((data) >> 1) & 0xf)
+
/* SFrame Frame Row Entry definitions.
Used for AMD64, AARCH64, and S390.
@@ -115,7 +115,10 @@ sframe_get_hdr_size (sframe_header *sfh)
static uint8_t
sframe_fre_get_offset_count (uint8_t fre_info)
{
- return SFRAME_V1_FRE_OFFSET_COUNT (fre_info);
+ unsigned int fre_offset_flags = SFRAME_V2_FRE_OFFSET_FLAGS (fre_info);
+ const char flags_to_count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+ return flags_to_count[fre_offset_flags];
}
static uint8_t
@@ -130,6 +133,19 @@ sframe_get_fre_ra_mangled_p (uint8_t fre_info)
return SFRAME_V1_FRE_MANGLED_RA_P (fre_info);
}
+static int
+sframe_get_fre_offset_index (uint8_t fre_info, unsigned int tracked_offset)
+{
+ unsigned int fre_offset_flags = SFRAME_V2_FRE_OFFSET_FLAGS (fre_info);
+ const char flags_to_count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ unsigned int mask = (1 << tracked_offset) - 1;
+
+ if ((fre_offset_flags & (1 << tracked_offset)) == 0)
+ return -1;
+
+ return flags_to_count[fre_offset_flags & mask];
+}
+
/* Access functions for info from function descriptor entry. */
static uint32_t
@@ -680,7 +696,13 @@ int32_t
sframe_fre_get_cfa_offset (sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED,
sframe_frame_row_entry *fre, int *errp)
{
- return sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, errp);
+ int cfa_offset_idx = sframe_get_fre_offset_index (fre->fre_info,
+ SFRAME_FRE_CFA_OFFSET_IDX);
+ if (cfa_offset_idx == -1)
+ return sframe_set_errno (errp, SFRAME_ERR_FREOFFSET_NOPRESENT);
+ sframe_assert (cfa_offset_idx == 0);
+
+ return sframe_get_fre_offset (fre, cfa_offset_idx, errp);
}
/* Get the FP offset from the FRE. If the offset is invalid, sets errp. */
@@ -689,7 +711,7 @@ int32_t
sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
sframe_frame_row_entry *fre, int *errp)
{
- uint32_t fp_offset_idx = 0;
+ int fp_offset_idx;
int8_t fp_offset = sframe_decoder_get_fixed_fp_offset (dctx);
/* If the FP offset is not being tracked, return the fixed FP offset
from the SFrame header. */
@@ -700,13 +722,13 @@ sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
return fp_offset;
}
- /* In some ABIs, the stack offset to recover RA (using the CFA) from is
- fixed (like AMD64). In such cases, the stack offset to recover FP will
- appear at the second index. */
- fp_offset_idx = ((sframe_decoder_get_fixed_ra_offset (dctx)
- != SFRAME_CFA_FIXED_RA_INVALID)
- ? SFRAME_FRE_RA_OFFSET_IDX
- : SFRAME_FRE_FP_OFFSET_IDX);
+ /* Get the FP offset index and check that it is valid. */
+ fp_offset_idx = sframe_get_fre_offset_index (fre->fre_info,
+ SFRAME_FRE_FP_OFFSET_IDX);
+ if (fp_offset_idx == -1)
+ return sframe_set_errno (errp, SFRAME_ERR_FREOFFSET_NOPRESENT);
+
+ /* Otherwise, get the FP offset from the FRE. */
return sframe_get_fre_offset (fre, fp_offset_idx, errp);
}
@@ -716,6 +738,7 @@ int32_t
sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx,
sframe_frame_row_entry *fre, int *errp)
{
+ int ra_offset_idx;
int8_t ra_offset = sframe_decoder_get_fixed_ra_offset (dctx);
/* If the RA offset was not being tracked, return the fixed RA offset
from the SFrame header. */
@@ -726,8 +749,14 @@ sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx,
return ra_offset;
}
+ /* Get the RA offset index and check that it is valid. */
+ ra_offset_idx = sframe_get_fre_offset_index (fre->fre_info,
+ SFRAME_FRE_RA_OFFSET_IDX);
+ if (ra_offset_idx == -1)
+ return sframe_set_errno (errp, SFRAME_ERR_FREOFFSET_NOPRESENT);
+
/* Otherwise, get the RA offset from the FRE. */
- return sframe_get_fre_offset (fre, SFRAME_FRE_RA_OFFSET_IDX, errp);
+ return sframe_get_fre_offset (fre, ra_offset_idx, errp);
}
/* Get whether the RA is mangled. */