mirror of
https://github.com/bminor/binutils-gdb.git
synced 2026-02-04 18:21:29 +00:00
[SFrame-V3] gas: sframe: testsuite: handle .cfi_register FP/RA for flex FDE
Use SFrame FDE of type SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME. When FP, RA were moved to a general-purpose register, the SFrame generation previously warned and skipped the FDE (except on s390x). This patch updates the translator to detect .cfi_register for RA (and FP), tracks the destination register in the SFrame row entry, and emits the register in the relevant FRE offsets in SFrame FDE type SFRAME_FDE_TYPE_FLEX. gas/ * gen-sframe.c (sframe_row_entry_initialize): Propagate ra_reg and ra_deref_p. (sframe_xlate_do_register): Handle .cfi_register for RA/FP on AMD64 by setting flex_p and recording the register. gas/testsuite/gas/ * cfi-sframe/cfi-sframe.exp: Run new test. * cfi-sframe/cfi-sframe-x86_64-5.d: New test. * cfi-sframe/cfi-sframe-x86_64-5.s: Simple test for checking FLEX FDE generation for `.cfi_register REG_RA, XX`. * cfi-sframe/cfi-sframe-x86_64-esc-expr-3.d: New test. * cfi-sframe/cfi-sframe-x86_64-esc-expr-3.s: New test with DWARF expression for REG_FP, followed by .cfi_register and .cfi_offset for REG_FP. * cfi-sframe/cfi-sframe-x86_64-ra-undefined-flex-1.d: New test. * cfi-sframe/cfi-sframe-x86_64-ra-undefined-flex-1.s: New test for FLEX FDE with undefined RA.
This commit is contained in:
@@ -1164,6 +1164,7 @@ sframe_row_entry_initialize (struct sframe_row_entry *cur_fre,
|
||||
cur_fre->ra_loc = prev_fre->ra_loc;
|
||||
cur_fre->ra_reg = prev_fre->ra_reg;
|
||||
cur_fre->ra_offset = prev_fre->ra_offset;
|
||||
cur_fre->ra_deref_p = prev_fre->ra_deref_p;
|
||||
/* Treat RA mangling as a sticky bit. It retains its value until another
|
||||
.cfi_negate_ra_state is seen. */
|
||||
cur_fre->mangled_ra_p = prev_fre->mangled_ra_p;
|
||||
@@ -1489,6 +1490,18 @@ s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
|
||||
}
|
||||
|
||||
/* Translate DW_CFA_register into SFrame context.
|
||||
|
||||
This opcode indicates: Previous value of register1 is register2. This is
|
||||
not representable in SFrame stack trace format. Detect the use of registers
|
||||
interesting to SFrame (FP, RA for this opcode), and skip FDE generation
|
||||
while warning the user.
|
||||
|
||||
Two exceptions apply though:
|
||||
- for S390X, the stack offsets are used to carry register number in
|
||||
default FDE types. So invoke S390X specific handling.
|
||||
- for AMD64, the flexible topmost frame encoding
|
||||
SFRAME_FDE_TYPE_FLEX can be used for FP, RA registers.
|
||||
|
||||
Return SFRAME_XLATE_OK if success. */
|
||||
|
||||
static int
|
||||
@@ -1498,15 +1511,33 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
|
||||
/* Conditionally invoke S390-specific implementation. */
|
||||
if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
|
||||
return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
|
||||
else if (sframe_support_flex_fde_p ())
|
||||
{
|
||||
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
|
||||
|
||||
/* Previous value of register1 is register2. However, if the specified
|
||||
register1 is not interesting (FP or RA reg), the current DW_CFA_register
|
||||
instruction can be safely skipped without sacrificing the asynchronicity of
|
||||
stack trace information. */
|
||||
if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG
|
||||
|| cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
|
||||
/* Ignore SP reg, as it can be recovered from the CFA tracking info. */
|
||||
)
|
||||
if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
|
||||
{
|
||||
sframe_fre_set_fp_track (cur_fre, 0);
|
||||
cur_fre->fp_loc = SFRAME_FRE_ELEM_LOC_REG;
|
||||
cur_fre->fp_reg = cfi_insn->u.rr.reg2;
|
||||
cur_fre->fp_deref_p = false;
|
||||
cur_fre->merge_candidate = false;
|
||||
xlate_ctx->flex_p = true;
|
||||
}
|
||||
else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
|
||||
{
|
||||
sframe_fre_set_ra_track (cur_fre, 0);
|
||||
cur_fre->ra_loc = SFRAME_FRE_ELEM_LOC_REG;
|
||||
cur_fre->ra_reg = cfi_insn->u.rr.reg2;
|
||||
cur_fre->ra_deref_p = false;
|
||||
cur_fre->merge_candidate = false;
|
||||
xlate_ctx->flex_p = true;
|
||||
}
|
||||
}
|
||||
else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG
|
||||
/* Ignore SP reg, as it can be recovered from the CFA tracking
|
||||
info. */
|
||||
|| cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
|
||||
{
|
||||
as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
|
||||
sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
|
||||
|
||||
21
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-5.d
Normal file
21
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-5.d
Normal file
@@ -0,0 +1,21 @@
|
||||
#as: --gsframe
|
||||
#objdump: --sframe=.sframe
|
||||
#name: DW_CFA_register RA in flex FDE type
|
||||
#...
|
||||
|
||||
Contents of the SFrame section .sframe:
|
||||
Header :
|
||||
|
||||
Version: SFRAME_VERSION_3
|
||||
Flags: SFRAME_F_FDE_FUNC_START_PCREL
|
||||
CFA fixed RA offset: -8
|
||||
Num FDEs: 1
|
||||
Num FREs: 3
|
||||
|
||||
Function Index :
|
||||
|
||||
func idx \[0\]: pc = 0x0, size = 7 bytes, attr = "F"
|
||||
STARTPC +CFA +FP +RA +
|
||||
0+0000 +sp\+8 +u +f +
|
||||
0+0004 +sp\+40 +u +f +
|
||||
0+0005 +sp\+0 +u +r2\+0 +
|
||||
12
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-5.s
Normal file
12
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-5.s
Normal file
@@ -0,0 +1,12 @@
|
||||
# Testcase to check FLEX FDE generation for .cfi_register RIP, XX
|
||||
.type foo, @function
|
||||
foo:
|
||||
.cfi_startproc
|
||||
sub $0x20,%rsp
|
||||
.cfi_adjust_cfa_offset 0x20
|
||||
popq %rcx
|
||||
.cfi_register rip, 2
|
||||
.cfi_def_cfa_offset 0
|
||||
jmp *%rcx
|
||||
.cfi_endproc
|
||||
.size foo, .-foo
|
||||
26
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-esc-expr-3.d
Normal file
26
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-esc-expr-3.d
Normal file
@@ -0,0 +1,26 @@
|
||||
#as: --gsframe
|
||||
#objdump: --sframe=.sframe
|
||||
#name: Flex FDE with RA state transition
|
||||
#...
|
||||
Contents of the SFrame section .sframe:
|
||||
|
||||
Header :
|
||||
|
||||
Version: SFRAME_VERSION_3
|
||||
Flags: SFRAME_F_FDE_FUNC_START_PCREL
|
||||
#? CFA fixed FP offset: \-?\d+
|
||||
#? CFA fixed RA offset: \-?\d+
|
||||
Num FDEs: 1
|
||||
Num FREs: 5
|
||||
|
||||
Function Index :
|
||||
|
||||
func idx \[0\]: pc = 0x0, size = 17 bytes, attr = "F"
|
||||
STARTPC +CFA +FP +RA +
|
||||
0+0000 +sp\+8 +u +f +
|
||||
0+0004 +sp\+40 +u +f +
|
||||
0+0008 +sp\+40 +\(fp\+48\) +U +
|
||||
0+000c +sp\+40 +r3\+0 +U +
|
||||
0+0010 +sp\+8 +c\+16 +U +
|
||||
|
||||
#pass
|
||||
18
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-esc-expr-3.s
Normal file
18
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-esc-expr-3.s
Normal file
@@ -0,0 +1,18 @@
|
||||
# Testcase for transition of tracked entity (rbp) from DWARF expression, to
|
||||
# register, and finally to CFA+offset.
|
||||
.type foo, @function
|
||||
foo:
|
||||
.cfi_startproc
|
||||
.long 0
|
||||
.cfi_adjust_cfa_offset 0x20
|
||||
.long 0
|
||||
# DW_CFA_expression, (uleb)reg, length, DW_OP_breg6, (sleb)offset
|
||||
.cfi_escape 0x10,0x6,0x2,0x76,sleb128(48)
|
||||
.long 0
|
||||
.cfi_register rbp, 3
|
||||
.long 0
|
||||
.cfi_offset rbp, 16
|
||||
.cfi_def_cfa rsp, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size foo, .-foo
|
||||
@@ -0,0 +1,23 @@
|
||||
#as: --gsframe -O0
|
||||
#objdump: --sframe=.sframe
|
||||
#name: SFrame generation on x86_64 - .cfi_undefined RA
|
||||
#...
|
||||
Contents of the SFrame section .sframe:
|
||||
|
||||
Header :
|
||||
|
||||
Version: SFRAME_VERSION_3
|
||||
Flags: SFRAME_F_FDE_FUNC_START_PCREL
|
||||
CFA fixed RA offset: \-8
|
||||
Num FDEs: 1
|
||||
Num FREs: 5
|
||||
|
||||
Function Index :
|
||||
|
||||
func idx \[0\]: pc = 0x0, size = 7 bytes, attr = "F"
|
||||
STARTPC +CFA +FP +RA +
|
||||
0+0000 +sp\+8 +u +f +
|
||||
0+0001 +sp\+16 +c\-16 +U +
|
||||
0+0004 +fp\+16 +c\-16 +U +
|
||||
0+0005 +fp\+16 +c\-16 +r3\+0 +
|
||||
0+0006 +RA undefined
|
||||
@@ -0,0 +1,15 @@
|
||||
# Testcase with FLEX FDE generation due to RA using reg on AMD64
|
||||
# Also, tagged as outermost frame.
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset rbp, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register rbp
|
||||
nop
|
||||
.cfi_register rip, rbx
|
||||
nop
|
||||
.cfi_undefined rip
|
||||
.cfi_def_cfa rsp, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
@@ -62,8 +62,10 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
|
||||
run_dump_test "cfi-sframe-x86_64-2"
|
||||
run_dump_test "cfi-sframe-x86_64-3"
|
||||
run_dump_test "cfi-sframe-x86_64-4"
|
||||
run_dump_test "cfi-sframe-x86_64-5"
|
||||
run_dump_test "cfi-sframe-x86_64-esc-expr-1"
|
||||
run_dump_test "cfi-sframe-x86_64-esc-expr-2"
|
||||
run_dump_test "cfi-sframe-x86_64-esc-expr-3"
|
||||
run_dump_test "cfi-sframe-x86_64-pr33170"
|
||||
run_dump_test "cfi-sframe-x86_64-pr33756"
|
||||
run_dump_test "cfi-sframe-x86_64-signal-1"
|
||||
@@ -73,6 +75,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
|
||||
run_dump_test "cfi-sframe-x86_64-empty-4"
|
||||
run_dump_test "cfi-sframe-x86_64-empty-pr33277"
|
||||
run_dump_test "cfi-sframe-x86_64-ra-undefined-1"
|
||||
run_dump_test "cfi-sframe-x86_64-ra-undefined-flex-1"
|
||||
set ASFLAGS "$old_ASFLAGS"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user