[binutils-gdb] gas: sframe: i386: have the backend specify the RA too
Indu Bhagat
ibhagat@sourceware.org
Mon May 19 07:15:32 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9819d849419de078b46c3f123e9dbc6503ab36d0
commit 9819d849419de078b46c3f123e9dbc6503ab36d0
Author: Indu Bhagat <indu.bhagat@oracle.com>
Date: Mon May 19 00:01:29 2025 -0700
gas: sframe: i386: have the backend specify the RA too
To process some CFI directives like .cfi_undefined and .cfi_same_value,
it is necessary for correctness to detect all cases when the register
used is one of SP, FP or RA.
Currently, the backends needed to specify the SFRAME_CFA_RA_REG only in
the case of those ABIs where RA tracking was necessary, e.g. AArch64.
For AMD64, since the return address is always at a fixed offset from the
CFA, RA tracking was disabled.
The backends must now specify the applicable return address register via
SFRAME_CFA_RA_REG. This is necessary so that SFrame generation code can
then properly handle the cases when RA is used like so:
.cfi_undefined <RA>
or,
.cfi_same_value <RA>
Detecting these cases is necessary for correctness. E.g., on AMD64, we
need to skip FDE generation as the above constructs cannot be
represented in SFrame yet.
This change is a prerequisite to fixing the two PRs:
PR gas/32952 - sframe: incorrect handling of .cfi_undefined in gas
PR gas/32953 - sframe: incorrect handling of .cfi_same_value in gas
In the SFrame generation code in gen-sframe.c, instead of using
SFRAME_FRE_RA_TRACKING ifdef's, we now simply rely on the API
sframe_ra_tracking_p () to detect if RA-tracking is enabled for the
target.
While at it, use const variables for x86 backend.
ChangeLog:
* gas/config/tc-i386.c (x86_sframe_cfa_ra_reg): New definition.
* gas/config/tc-i386.h (REG_RA): New definition.
(SFRAME_CFA_RA_REG): New declaration.
* gas/gen-sframe.c (SFRAME_FRE_RA_TRACKING): Remove.
Diff:
---
gas/config/tc-i386.c | 14 +++++++-------
gas/config/tc-i386.h | 13 +++++++++++--
gas/gen-sframe.c | 34 ----------------------------------
3 files changed, 18 insertions(+), 43 deletions(-)
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 31d4bccaee3..162e28e0325 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -678,9 +678,13 @@ static int use_big_obj = 0;
/* 1 if generating code for a shared library. */
static int shared = 0;
-unsigned int x86_sframe_cfa_sp_reg;
+const unsigned int x86_sframe_cfa_sp_reg = REG_SP;
/* The other CFA base register for SFrame stack trace info. */
-unsigned int x86_sframe_cfa_fp_reg;
+const unsigned int x86_sframe_cfa_fp_reg = REG_FP;
+/* The return address register for SFrame stack trace info. For AMD64, RA
+ tracking is not needed, but some directives like .cfi_undefined may use
+ RA to indicate the outermost frame. */
+const unsigned int x86_sframe_cfa_ra_reg = REG_RA;
static ginsnS *x86_ginsn_new (const symbolS *, enum ginsn_gen_mode);
#endif
@@ -3702,13 +3706,9 @@ md_begin (void)
#if defined (OBJ_COFF) && defined (TE_PE)
x86_dwarf2_return_column = 32;
#else
- x86_dwarf2_return_column = 16;
+ x86_dwarf2_return_column = REG_RA;
#endif
x86_cie_data_alignment = -8;
-#ifdef OBJ_ELF
- x86_sframe_cfa_sp_reg = REG_SP;
- x86_sframe_cfa_fp_reg = REG_FP;
-#endif
}
else
{
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 19eb0bcecf2..ad8cec5a007 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -413,6 +413,9 @@ extern void tc_x86_frame_initial_instructions (void);
#define REG_FP 6
/* DWARF register number of the stack-pointer register in 64-bit mode. */
#define REG_SP 7
+/* DWARF register number of the (pseudo) return address register in 64-bit
+ mode. This is the same as reg RIP in i386-reg.tbl. */
+#define REG_RA 16
#define md_elf_section_type(str,len) i386_elf_section_type (str, len)
extern int i386_elf_section_type (const char *, size_t);
@@ -455,13 +458,19 @@ extern bool x86_support_sframe_p (void);
#define support_sframe_p x86_support_sframe_p
/* The stack pointer DWARF register number for SFrame CFA tracking. */
-extern unsigned int x86_sframe_cfa_sp_reg;
+extern const unsigned int x86_sframe_cfa_sp_reg;
#define SFRAME_CFA_SP_REG x86_sframe_cfa_sp_reg
/* The frame pointer DWARF register number for SFrame CFA and FP tracking. */
-extern unsigned int x86_sframe_cfa_fp_reg;
+extern const unsigned int x86_sframe_cfa_fp_reg;
#define SFRAME_CFA_FP_REG x86_sframe_cfa_fp_reg
+/* The return address DWARF register number for SFrame purposes. Although for
+ AMD64, RA tracking is disabled, specific constructs, like for indicating
+ the _start function, may use it. */
+extern const unsigned int x86_sframe_cfa_ra_reg;
+#define SFRAME_CFA_RA_REG x86_sframe_cfa_ra_reg
+
/* Whether SFrame return address tracking is needed. */
extern bool x86_sframe_ra_tracking_p (void);
#define sframe_ra_tracking_p x86_sframe_ra_tracking_p
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index aa46b9cb0b6..307025866c1 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -30,18 +30,6 @@
# define sizeof_member(type, member) (sizeof (((type *)0)->member))
#endif
-/* Whether frame row entries track RA.
-
- A target may not need return address tracking for stack tracing. If it
- does need the same, SFRAME_CFA_RA_REG must be defined with the return
- address register number. */
-
-#if defined (sframe_ra_tracking_p) && defined (SFRAME_CFA_RA_REG)
-# ifndef SFRAME_FRE_RA_TRACKING
-# define SFRAME_FRE_RA_TRACKING 1
-# endif
-#endif
-
/* SFrame FRE type selection optimization is an optimization for size.
There are three flavors of SFrame FRE representation in the binary format:
@@ -154,7 +142,6 @@ sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
fre->merge_candidate = false;
}
-#ifdef SFRAME_FRE_RA_TRACKING
static void
sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
{
@@ -162,7 +149,6 @@ sframe_fre_set_ra_track (struct sframe_row_entry *fre, offsetT ra_offset)
fre->ra_offset = ra_offset;
fre->merge_candidate = false;
}
-#endif
static void
sframe_fre_set_bp_track (struct sframe_row_entry *fre, offsetT bp_offset)
@@ -352,11 +338,9 @@ get_fre_num_offsets (struct sframe_row_entry *sframe_fre)
if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
fre_num_offsets++;
-#ifdef SFRAME_FRE_RA_TRACKING
if (sframe_ra_tracking_p ()
&& sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
fre_num_offsets++;
-#endif
return fre_num_offsets;
}
@@ -377,11 +361,9 @@ sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre)
cfa_offset_size = get_offset_size_in_bytes (sframe_fre->cfa_offset);
if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
bp_offset_size = get_offset_size_in_bytes (sframe_fre->bp_offset);
-#ifdef SFRAME_FRE_RA_TRACKING
if (sframe_ra_tracking_p ()
&& sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset);
-#endif
/* Get the maximum size needed to represent the offsets. */
max_offset_size = cfa_offset_size;
@@ -587,14 +569,12 @@ output_sframe_row_entry (symbolS *fde_start_addr,
fre_offset_func_map[idx].out_func (sframe_fre->cfa_offset);
fre_write_offsets++;
-#ifdef SFRAME_FRE_RA_TRACKING
if (sframe_ra_tracking_p ()
&& sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK)
{
fre_offset_func_map[idx].out_func (sframe_fre->ra_offset);
fre_write_offsets++;
}
-#endif
if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)
{
fre_offset_func_map[idx].out_func (sframe_fre->bp_offset);
@@ -926,10 +906,8 @@ sframe_register_name (unsigned int 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;
}
@@ -1102,14 +1080,12 @@ sframe_xlate_do_offset (struct sframe_xlate_ctx *xlate_ctx,
sframe_fre_set_bp_track (cur_fre, cfi_insn->u.ri.offset);
cur_fre->merge_candidate = false;
}
-#ifdef SFRAME_FRE_RA_TRACKING
else if (sframe_ra_tracking_p ()
&& cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
{
sframe_fre_set_ra_track (cur_fre, cfi_insn->u.ri.offset);
cur_fre->merge_candidate = false;
}
-#endif
/* This is used to track changes to non-rsp registers, skip all others
except FP / RA for now. */
return SFRAME_XLATE_OK;
@@ -1131,9 +1107,7 @@ sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_U
DW_CFA_val_offset instruction can be safely skipped without sacrificing
the asynchronicity of stack trace information. */
if (cfi_insn->u.ri.reg == SFRAME_CFA_FP_REG
-#ifdef SFRAME_FRE_RA_TRACKING
|| (sframe_ra_tracking_p () && cfi_insn->u.ri.reg == SFRAME_CFA_RA_REG)
-#endif
/* Ignore SP reg, if offset matches assumed default rule. */
|| (cfi_insn->u.ri.reg == SFRAME_CFA_SP_REG && cfi_insn->u.ri.offset != 0))
{
@@ -1159,9 +1133,7 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
instruction can be safely skipped without sacrificing the asynchronicity of
stack trace information. */
if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG
-#ifdef SFRAME_FRE_RA_TRACKING
|| (sframe_ra_tracking_p () && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
-#endif
/* Ignore SP reg, as it can be recovered from the CFA tracking info. */
)
{
@@ -1246,7 +1218,6 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
cur_fre->bp_offset = cie_fre->bp_offset;
cur_fre->merge_candidate = false;
}
-#ifdef SFRAME_FRE_RA_TRACKING
else if (sframe_ra_tracking_p ()
&& cfi_insn->u.r == SFRAME_CFA_RA_REG)
{
@@ -1255,7 +1226,6 @@ sframe_xlate_do_restore (struct sframe_xlate_ctx *xlate_ctx,
cur_fre->ra_offset = cie_fre->ra_offset;
cur_fre->merge_candidate = false;
}
-#endif
return SFRAME_XLATE_OK;
}
@@ -1365,9 +1335,7 @@ sframe_xlate_do_escape_expr (const struct sframe_xlate_ctx *xlate_ctx,
#undef CFI_ESC_NUM_EXP
if (reg == SFRAME_CFA_SP_REG || reg == SFRAME_CFA_FP_REG
-#ifdef SFRAME_FRE_RA_TRACKING
|| (sframe_ra_tracking_p () && reg == SFRAME_CFA_RA_REG)
-#endif
|| reg == xlate_ctx->cur_fre->cfa_base_reg)
{
as_warn (_("skipping SFrame FDE; "
@@ -1707,7 +1675,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;
@@ -1724,7 +1691,6 @@ sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
}
}
}
-#endif /* SFRAME_FRE_RA_TRACKING */
return SFRAME_XLATE_OK;
}
More information about the Binutils-cvs
mailing list