summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/dwarf2-frame.c67
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-restore.S50
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-restore.exp37
5 files changed, 133 insertions, 32 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c6ac1f79ecf..e95f19478ac 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2009-06-30 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ gdb/10275
+ * dwarf2-frame.c (dwarf2_frame_state): Move cfa_offset, cfa_reg,
+ cfa_how and cfa_exp into regs and adjust users.
+
2009-06-30 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2read.c (inherit_abstract_dies): Work around GCC PR 40573.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 67265f2d7ec..315d349cf49 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -164,19 +164,19 @@ struct dwarf2_frame_state
struct dwarf2_frame_state_reg *reg;
int num_regs;
+ LONGEST cfa_offset;
+ ULONGEST cfa_reg;
+ enum {
+ CFA_UNSET,
+ CFA_REG_OFFSET,
+ CFA_EXP
+ } cfa_how;
+ gdb_byte *cfa_exp;
+
/* Used to implement DW_CFA_remember_state. */
struct dwarf2_frame_state_reg_info *prev;
} regs;
- LONGEST cfa_offset;
- ULONGEST cfa_reg;
- gdb_byte *cfa_exp;
- enum {
- CFA_UNSET,
- CFA_REG_OFFSET,
- CFA_EXP
- } cfa_how;
-
/* The PC described by the current frame state. */
CORE_ADDR pc;
@@ -502,21 +502,22 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
break;
case DW_CFA_def_cfa:
- insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
if (fs->armcc_cfa_offsets_sf)
utmp *= fs->data_align;
- fs->cfa_offset = utmp;
- fs->cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_offset = utmp;
+ fs->regs.cfa_how = CFA_REG_OFFSET;
break;
case DW_CFA_def_cfa_register:
- insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
- fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg,
- eh_frame_p);
- fs->cfa_how = CFA_REG_OFFSET;
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
+ fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch,
+ fs->regs.cfa_reg,
+ eh_frame_p);
+ fs->regs.cfa_how = CFA_REG_OFFSET;
break;
case DW_CFA_def_cfa_offset:
@@ -525,7 +526,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
if (fs->armcc_cfa_offsets_sf)
utmp *= fs->data_align;
- fs->cfa_offset = utmp;
+ fs->regs.cfa_offset = utmp;
/* cfa_how deliberately not set. */
break;
@@ -533,10 +534,11 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
break;
case DW_CFA_def_cfa_expression:
- insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_exp_len);
- fs->cfa_exp = insn_ptr;
- fs->cfa_how = CFA_EXP;
- insn_ptr += fs->cfa_exp_len;
+ insn_ptr = read_uleb128 (insn_ptr, insn_end,
+ &fs->regs.cfa_exp_len);
+ fs->regs.cfa_exp = insn_ptr;
+ fs->regs.cfa_how = CFA_EXP;
+ insn_ptr += fs->regs.cfa_exp_len;
break;
case DW_CFA_expression:
@@ -589,17 +591,18 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
break;
case DW_CFA_def_cfa_sf:
- insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
- fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg,
- eh_frame_p);
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
+ fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch,
+ fs->regs.cfa_reg,
+ eh_frame_p);
insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
- fs->cfa_offset = offset * fs->data_align;
- fs->cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_offset = offset * fs->data_align;
+ fs->regs.cfa_how = CFA_REG_OFFSET;
break;
case DW_CFA_def_cfa_offset_sf:
insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
- fs->cfa_offset = offset * fs->data_align;
+ fs->regs.cfa_offset = offset * fs->data_align;
/* cfa_how deliberately not set. */
break;
@@ -932,19 +935,19 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
execute_cfa_program (fde, fde->instructions, fde->end, this_frame, fs);
/* Calculate the CFA. */
- switch (fs->cfa_how)
+ switch (fs->regs.cfa_how)
{
case CFA_REG_OFFSET:
- cache->cfa = read_reg (this_frame, fs->cfa_reg);
+ cache->cfa = read_reg (this_frame, fs->regs.cfa_reg);
if (fs->armcc_cfa_offsets_reversed)
- cache->cfa -= fs->cfa_offset;
+ cache->cfa -= fs->regs.cfa_offset;
else
- cache->cfa += fs->cfa_offset;
+ cache->cfa += fs->regs.cfa_offset;
break;
case CFA_EXP:
cache->cfa =
- execute_stack_op (fs->cfa_exp, fs->cfa_exp_len,
+ execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len,
cache->addr_size, this_frame, 0);
break;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index d08158e10d0..a9436f47e9c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-06-30 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ gdb/10275
+ * gdb.dwarf2/dw2-restore.{S,exp}: New test.
+
2009-06-30 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.opt/inline-locals.exp: Remove XFAIL with duplicated arg1.
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-restore.S b/gdb/testsuite/gdb.dwarf2/dw2-restore.S
new file mode 100644
index 00000000000..c268dac355d
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-restore.S
@@ -0,0 +1,50 @@
+/*
+ Copyright 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Compile with "gcc -nostdlib dw2-restore.S" */
+
+ .text
+ .globl _start
+ .func _start
+_start: call foo
+ mov $0,%rax
+ ret
+ .endfunc
+
+ .func foo
+foo: .cfi_startproc
+ push %rbp
+ .cfi_adjust_cfa_offset 8
+ mov %rsp,%rbp
+ .cfi_def_cfa_register %rbp
+
+ .cfi_remember_state
+ jmp 2f
+
+1: mov %rbp,%rsp
+ .cfi_restore %rbp
+ pop %rbp
+ .cfi_adjust_cfa_offset -8
+ .cfi_def_cfa_register %rsp
+ ret
+
+ .cfi_restore_state
+2: movq $0,%rax
+ movq $0,(%rax) /* crash here */
+ jmp 1b
+ .cfi_endproc
+ .endfunc
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-restore.exp b/gdb/testsuite/gdb.dwarf2/dw2-restore.exp
new file mode 100644
index 00000000000..78994c17645
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-restore.exp
@@ -0,0 +1,37 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test handling of DW_CFA_restore_state.
+
+# This test can only be run on x86_64 targets.
+if {![istarget x86_64-*]} {
+ return 0
+}
+set testfile "dw2-restore"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list {additional_flags=-nostdlib}]] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "run" ""
+gdb_test "where" ".*$hex in foo ().+$hex in _start ().*"