gas: User readable warnings if SFrame FDE is not generated

The following generic warning message, which is printed whenever the
assembler skips generation of SFrame FDE, is not very helpful for the
user:

  skipping SFrame FDE; CFI insn <name> (0x<hexval>)

Whenever possible print meaningful warning messages, when the assembler
skips generation of SFrame FDE:

- skipping SFrame FDE; non-SP/FP register <regno> in .cfi_def_cfa
- skipping SFrame FDE; non-SP/FP register <regno> in
  .cfi_def_cfa_register
- skipping SFrame FDE; .cfi_def_cfa_offset without CFA base register
  in effect
- skipping SFrame FDE; {FP|RA} register <regno> in .cfi_val_offset
- skipping SFrame FDE; {SP|FP|RA} register <regno> in in .cfi_register
- skipping SFrame FDE; .cfi_remember_state without prior SFrame FRE
  state
- skipping SFrame FDE; non-default RA register <regno>

gas/
	* gen-sframe.h (SFRAME_FRE_BASE_REG_INVAL): New macro for
	invalid SFrame FRE CFA base register value of -1.
	* gen-sframe.c: User readable warnings if SFrame FDE is not
	generated.

gas/testsuite/
	* gas/cfi-sframe/common-empty-1.d: Update generic SFrame test
	case to updated warning message texts.
	* gas/cfi-sframe/common-empty-2.d: Likewise.
	* gas/cfi-sframe/common-empty-3.d: Likewise.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
This commit is contained in:
Jens Remus 2024-07-04 10:34:12 +02:00
parent 397582abe7
commit 536119a44c
5 changed files with 72 additions and 28 deletions

View File

@ -869,7 +869,7 @@ sframe_row_entry_new (void)
struct sframe_row_entry *fre = XCNEW (struct sframe_row_entry);
/* Reset cfa_base_reg to -1. A value of 0 will imply some valid register
for the supported arches. */
fre->cfa_base_reg = -1;
fre->cfa_base_reg = SFRAME_FRE_BASE_REG_INVAL;
fre->merge_candidate = true;
/* Reset the mangled RA status bit to zero by default. We will initialize it in
sframe_row_entry_initialize () with the sticky bit if set. */
@ -924,6 +924,23 @@ sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
}
/* Return SFrame register name for SP, FP, and RA, or NULL if other. */
static const char *
sframe_register_name (unsigned int reg)
{
if (reg == SFRAME_CFA_SP_REG)
return "SP";
else if (reg == SFRAME_CFA_FP_REG)
return "FP";
#ifdef SFRAME_FRE_RA_TRACKING
else if (reg == SFRAME_CFA_RA_REG)
return "RA";
#endif
else
return NULL;
}
/* Translate DW_CFA_advance_loc into SFrame context.
Return SFRAME_XLATE_OK if success. */
@ -992,7 +1009,11 @@ sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
SFrame stack trace info for the function. */
if (cfi_insn->u.r != SFRAME_CFA_SP_REG
&& cfi_insn->u.r != SFRAME_CFA_FP_REG)
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
{
as_warn (_("skipping SFrame FDE; non-SP/FP register %u in .cfi_def_cfa"),
cfi_insn->u.r);
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
}
sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
cur_fre->merge_candidate = false;
@ -1017,7 +1038,12 @@ sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
skip creating SFrame stack trace info for the function. */
if (cfi_insn->u.r != SFRAME_CFA_SP_REG
&& cfi_insn->u.r != SFRAME_CFA_FP_REG)
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
{
as_warn (_("skipping SFrame FDE; "
"non-SP/FP register %u in .cfi_def_cfa_register"),
cfi_insn->u.r);
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
}
sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
sframe_fre_set_cfa_offset (cur_fre, last_fre->cfa_offset);
cur_fre->merge_candidate = false;
@ -1048,7 +1074,13 @@ sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
cur_fre->merge_candidate = false;
}
else
return SFRAME_XLATE_ERR_NOTREPRESENTED;
{
/* No CFA base register in effect. Non-SP/FP CFA base register should
not occur, as sframe_xlate_do_def_cfa[_register] would detect this. */
as_warn (_("skipping SFrame FDE; "
".cfi_def_cfa_offset without CFA base register in effect"));
return SFRAME_XLATE_ERR_NOTREPRESENTED;
}
return SFRAME_XLATE_OK;
}
@ -1098,13 +1130,16 @@ sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
register is not interesting (FP or RA reg), the current DW_CFA_val_offset
instruction can be safely skipped without sacrificing the asynchronicity of
stack trace information. */
if (cfi_insn->u.r == SFRAME_CFA_FP_REG)
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
if (cfi_insn->u.r == SFRAME_CFA_FP_REG
#ifdef SFRAME_FRE_RA_TRACKING
else if (sframe_ra_tracking_p ()
&& cfi_insn->u.r == SFRAME_CFA_RA_REG)
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
|| (sframe_ra_tracking_p () && cfi_insn->u.r == SFRAME_CFA_RA_REG)
#endif
)
{
as_warn (_("skipping SFrame FDE; %s register %u in .cfi_val_offset"),
sframe_register_name (cfi_insn->u.r), cfi_insn->u.r);
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
}
/* Safe to skip. */
return SFRAME_XLATE_OK;
@ -1126,7 +1161,11 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
|| (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
#endif
|| cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
{
as_warn (_("skipping SFrame FDE; %s register %u in .cfi_register"),
sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
}
/* Safe to skip. */
return SFRAME_XLATE_OK;
@ -1144,7 +1183,11 @@ sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
early with non-zero error code, this will cause no SFrame stack trace
info for the function involved. */
if (!last_fre)
return SFRAME_XLATE_ERR_INVAL;
{
as_warn (_("skipping SFrame FDE; "
".cfi_remember_state without prior SFrame FRE state"));
return SFRAME_XLATE_ERR_INVAL;
}
if (!xlate_ctx->remember_fre)
xlate_ctx->remember_fre = sframe_row_entry_new ();
@ -1332,21 +1375,19 @@ sframe_do_cfi_insn (struct sframe_xlate_ctx *xlate_ctx,
default:
/* Following skipped operations do, however, impact the asynchronicity:
- CFI_escape. */
err = SFRAME_XLATE_ERR_NOTREPRESENTED;
}
/* An error here will cause no SFrame FDE later. Warn the user because this
will affect the overall coverage and hence, asynchronicity. */
if (err)
{
const char *cfi_name = sframe_get_cfi_name (op);
if (!cfi_name)
cfi_name = _("(unknown)");
as_warn (_("skipping SFrame FDE; CFI insn %s (%#x)"),
cfi_name, op);
{
const char *cfi_name = sframe_get_cfi_name (op);
if (!cfi_name)
cfi_name = _("(unknown)");
as_warn (_("skipping SFrame FDE; CFI insn %s (%#x)"),
cfi_name, op);
err = SFRAME_XLATE_ERR_NOTREPRESENTED;
}
}
/* Any error will cause no SFrame FDE later. The user has already been
warned. */
return err;
}
@ -1363,7 +1404,8 @@ sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
/* SFrame format cannot represent a non-default DWARF return column reg. */
if (xlate_ctx->dw_fde->return_column != DWARF2_DEFAULT_RETURN_COLUMN)
{
as_warn (_("skipping SFrame FDE due to non-default DWARF return column"));
as_warn (_("skipping SFrame FDE; non-default RA register %u"),
xlate_ctx->dw_fde->return_column);
return SFRAME_XLATE_ERR_NOTREPRESENTED;
}

View File

@ -24,6 +24,8 @@
#define SFRAME_FRE_ELEM_LOC_REG 0
#define SFRAME_FRE_ELEM_LOC_STACK 1
#define SFRAME_FRE_BASE_REG_INVAL ((unsigned int)-1)
/* SFrame Frame Row Entry (FRE).
A frame row entry is a slice of the frame and can be valid for a set of

View File

@ -1,5 +1,5 @@
#as: --gsframe
#warning: skipping SFrame FDE; CFI insn DW_CFA_remember_state \(0xa\)
#warning: skipping SFrame FDE; \.cfi_remember_state without prior SFrame FRE state
#objdump: --sframe=.sframe
#name: Uninteresting cfi directives generate an empty SFrame section
#...

View File

@ -1,5 +1,5 @@
#as: --gsframe
#warning: skipping SFrame FDE; CFI insn DW_CFA_def_cfa_offset \(0xe\)
#warning: skipping SFrame FDE; \.cfi_def_cfa_offset without CFA base register in effect
#objdump: --sframe=.sframe
#name: SFrame supports only FP/SP based CFA
#...

View File

@ -1,5 +1,5 @@
#as: --gsframe
#warning: skipping SFrame FDE due to non-default DWARF return column
#warning: skipping SFrame FDE; non-default RA register 0
#objdump: --sframe=.sframe
#name: SFrame supports only default return column
#...