]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: sframe: i386: have the backend specify the RA too
authorIndu Bhagat <indu.bhagat@oracle.com>
Mon, 19 May 2025 07:01:29 +0000 (00:01 -0700)
committerIndu Bhagat <indu.bhagat@oracle.com>
Mon, 19 May 2025 07:01:29 +0000 (00:01 -0700)
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.

gas/config/tc-i386.c
gas/config/tc-i386.h
gas/gen-sframe.c

index 31d4bccaee368aa6e9f1770f1759a46c9715ad16..162e28e03259efca14dc80e327b3a4a965a17e7b 100644 (file)
@@ -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
     {
index 19eb0bcecf25e451bdbd264beaee0a99fb193980..ad8cec5a0074a44e1f0e668532604039529d2225 100644 (file)
@@ -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
index aa46b9cb0b63ff939e21f2c2178fc570db01791e..307025866c14360b51847de13d8b4127a3804f43 100644 (file)
 # 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;
 }