From: Indu Bhagat Date: Mon, 19 May 2025 07:01:29 +0000 (-0700) Subject: gas: sframe: i386: have the backend specify the RA too X-Git-Tag: binutils-2_45~559 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9819d849419de078b46c3f123e9dbc6503ab36d0;p=thirdparty%2Fbinutils-gdb.git 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 or, .cfi_same_value 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 --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; }