/* 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
#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
{
#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);
#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
# 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:
fre->merge_candidate = false;
}
-#ifdef SFRAME_FRE_RA_TRACKING
static void
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)
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;
}
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;
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);
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;
}
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;
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))
{
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. */
)
{
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)
{
cur_fre->ra_offset = cie_fre->ra_offset;
cur_fre->merge_candidate = false;
}
-#endif
return SFRAME_XLATE_OK;
}
#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; "
= get_dw_fde_end_addrS (xlate_ctx->dw_fde);
}
-#ifdef SFRAME_FRE_RA_TRACKING
if (sframe_ra_tracking_p ())
{
struct sframe_row_entry *fre;
}
}
}
-#endif /* SFRAME_FRE_RA_TRACKING */
return SFRAME_XLATE_OK;
}