aboutsummaryrefslogtreecommitdiff
path: root/gas/gen-sframe.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/gen-sframe.c')
-rw-r--r--gas/gen-sframe.c108
1 files changed, 84 insertions, 24 deletions
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index d082b97..ac14278 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -330,7 +330,7 @@ get_num_sframe_fres (void);
/* Get CFA base register ID as represented in SFrame Frame Row Entry. */
static unsigned int
-get_fre_base_reg_id (struct sframe_row_entry *sframe_fre)
+get_fre_base_reg_id (const struct sframe_row_entry *sframe_fre)
{
unsigned int cfi_insn_cfa_base_reg = sframe_fre->cfa_base_reg;
unsigned fre_base_reg = SFRAME_BASE_REG_SP;
@@ -348,7 +348,7 @@ get_fre_base_reg_id (struct sframe_row_entry *sframe_fre)
/* Get number of offsets necessary for the SFrame Frame Row Entry. */
static unsigned int
-get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
+get_fre_num_offsets (const struct sframe_row_entry *sframe_fre)
{
/* Atleast 1 must always be present (to recover CFA). */
unsigned int fre_num_offsets = 1;
@@ -368,7 +368,7 @@ get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
SFrame frame row entry. */
static unsigned int
-sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre)
+sframe_get_fre_offset_size (const struct sframe_row_entry *sframe_fre)
{
unsigned int max_offset_size = 0;
unsigned int cfa_offset_size = 0;
@@ -549,7 +549,7 @@ sframe_fde_free (struct sframe_func_entry *sframe_fde)
static void
output_sframe_row_entry (symbolS *fde_start_addr,
symbolS *fde_end_addr,
- struct sframe_row_entry *sframe_fre)
+ const struct sframe_row_entry *sframe_fre)
{
unsigned char fre_info;
unsigned int fre_num_offsets;
@@ -624,7 +624,7 @@ output_sframe_row_entry (symbolS *fde_start_addr,
static void
output_sframe_funcdesc (symbolS *start_of_fre_section,
symbolS *fre_symbol,
- struct sframe_func_entry *sframe_fde)
+ const struct sframe_func_entry *sframe_fde)
{
expressionS exp;
symbolS *dw_fde_start_addrS, *dw_fde_end_addrS;
@@ -897,7 +897,7 @@ sframe_xlate_ctx_finalize (struct sframe_xlate_ctx *xlate_ctx,
static void
sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx,
- struct sframe_row_entry *fre)
+ struct sframe_row_entry *fre)
{
gas_assert (xlate_ctx && fre);
@@ -924,7 +924,7 @@ sframe_xlate_ctx_add_fre (struct sframe_xlate_ctx *xlate_ctx,
static void
sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
- struct sframe_row_entry *prev_fre)
+ const struct sframe_row_entry *prev_fre)
{
gas_assert (prev_fre);
cur_fre->cfa_base_reg = prev_fre->cfa_base_reg;
@@ -958,7 +958,7 @@ sframe_register_name (unsigned int reg)
static int
sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
/* Get the scratchpad FRE currently being updated as the cfi_insn's
@@ -1004,7 +1004,7 @@ sframe_xlate_do_advance_loc (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
/* Get the scratchpad FRE. This FRE will eventually get linked in. */
@@ -1039,9 +1039,9 @@ sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
- struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
+ const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
/* Get the scratchpad FRE. This FRE will eventually get linked in. */
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
@@ -1071,7 +1071,7 @@ sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
/* The scratchpad FRE currently being updated with each cfi_insn
being interpreted. This FRE eventually gets linked in into the
@@ -1105,7 +1105,7 @@ sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
/* The scratchpad FRE currently being updated with each cfi_insn
being interpreted. This FRE eventually gets linked in into the
@@ -1172,7 +1172,7 @@ sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_U
static int
s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
/* The scratchpad FRE currently being updated with each cfi_insn
being interpreted. This FRE eventually gets linked in into the
@@ -1201,8 +1201,8 @@ s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
Return SFRAME_XLATE_OK if success. */
static int
-sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
- struct cfi_insn_data *cfi_insn)
+sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
+ const struct cfi_insn_data *cfi_insn)
{
/* Conditionally invoke S390-specific implementation. */
if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
@@ -1232,7 +1232,7 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
static int
sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
{
- struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
+ const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
/* If there is no FRE state to remember, nothing to do here. Return
early with non-zero error code, this will cause no SFrame stack trace
@@ -1278,7 +1278,7 @@ sframe_xlate_do_restore_state (struct sframe_xlate_ctx *xlate_ctx)
static int
sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
struct sframe_row_entry *cie_fre = xlate_ctx->first_fre;
/* The scratchpad FRE currently being updated with each cfi_insn
@@ -1321,7 +1321,7 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
+ const struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
{
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
@@ -1338,7 +1338,7 @@ sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
static int
sframe_xlate_do_aarch64_negate_ra_state_with_pc (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
- struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
+ const struct cfi_insn_data *cfi_insn ATTRIBUTE_UNUSED)
{
as_warn (_("no SFrame FDE emitted; .cfi_negate_ra_state_with_pc"));
/* The used signing method should be encoded inside the FDE in SFrame v3.
@@ -1358,7 +1358,7 @@ sframe_xlate_do_aarch64_negate_ra_state_with_pc (struct sframe_xlate_ctx *xlate_
static int
sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
unsigned char abi_arch = sframe_get_abi_arch ();
@@ -1510,6 +1510,64 @@ warn_and_exit:
return err;
}
+/* Handle DW_CFA_GNU_args_size in .cfi_escape.
+
+ The purpose of DW_CFA_GNU_args_size is to adjust SP when performing stack
+ unwinding for exception handling. For stack tracing needs,
+ DW_CFA_GNU_args_size can be ignored, when CFA is FP-based. This is because
+ if the topmost frame is that of the catch block, the SP has been restored to
+ correct value by exception handling logic. From this point of interest in
+ the catch block now, stack tracing intends to go backwards to the caller
+ frame. If CFA restoration does not need SP, DW_CFA_GNU_args_size can be
+ ignored for stack tracing.
+
+ Continue to warn and not emit SFrame FDE if CFA is SP based. The pattern
+ where the CFA is SP based and there is a DW_CFA_GNU_args_size for
+ SP-adjustment is not entirely clear.
+
+ Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
+ caller must warn. The caller then must also set
+ SFRAME_XLATE_ERR_NOTREPRESENTED for their callers. */
+
+static int
+sframe_xlate_do_escape_gnu_args_size (const struct sframe_xlate_ctx *xlate_ctx,
+ const struct cfi_insn_data *cfi_insn,
+ bool *caller_warn_p)
+{
+ const struct cfi_escape_data *e = cfi_insn->u.esc;
+ unsigned int i = 0;
+
+ /* Check for (DW_CFA_GNU_args_size offset) sequence. */
+#define CFI_ESC_NUM_EXP 1
+ offsetT items[CFI_ESC_NUM_EXP] = {0};
+ while (e->next)
+ {
+ e = e->next;
+ if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant
+ || e->type != CFI_ESC_byte
+ || e->reloc != TC_PARSE_CONS_RETURN_NONE)
+ goto warn_and_exit;
+ items[i] = e->exp.X_add_number;
+ i++;
+ }
+ if (i == 0)
+ goto warn_and_exit;
+
+#undef CFI_ESC_NUM_EXP
+
+ offsetT offset = items[0];
+
+ struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
+ gas_assert (cur_fre);
+ /* If CFA is FP based, safe to skip. */
+ if (offset == 0 || cur_fre->cfa_base_reg == SFRAME_CFA_FP_REG)
+ return SFRAME_XLATE_OK;
+
+warn_and_exit:
+ *caller_warn_p = true;
+ return SFRAME_XLATE_OK;
+}
+
/* Handle CFI_escape in SFrame context.
.cfi_escape CFI directive allows the user to add arbitrary data to the
@@ -1573,7 +1631,9 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
err = sframe_xlate_do_escape_val_offset (xlate_ctx, cfi_insn, &warn_p);
break;
- /* FIXME - Also add processing for DW_CFA_GNU_args_size in future? */
+ case DW_CFA_GNU_args_size:
+ err = sframe_xlate_do_escape_gnu_args_size (xlate_ctx, cfi_insn, &warn_p);
+ break;
default:
warn_p = true;
@@ -1725,7 +1785,7 @@ sframe_get_cfi_name (int cfi_opc)
static int
sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
- struct cfi_insn_data *cfi_insn)
+ const struct cfi_insn_data *cfi_insn)
{
int err = 0;
@@ -1805,7 +1865,7 @@ static int
sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
const struct fde_entry *dw_fde)
{
- struct cfi_insn_data *cfi_insn;
+ const struct cfi_insn_data *cfi_insn;
int err = SFRAME_XLATE_OK;
xlate_ctx->dw_fde = dw_fde;