Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* Support Dwarf3 DW_CFA_val_* expressions
@ 2006-03-03 17:54 Alexandre Oliva
  2006-03-04 12:01 ` Mark Kettenis
  0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2006-03-03 17:54 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 586 bytes --]

Jakub has recently implemented some of the Dwarf3 CFA value
expressions: http://sourceware.org/ml/binutils/2006-03/msg00009.html
http://sourceware.org/ml/binutils/2006-03/msg00043.html

Support in the GCC unwinder is in the works (or maybe already
contributed and I couldn't find it :-), but GDB is still missing
support for such encodings.  Without this patch, when it encounters
them, it complains loudly and fails to issue backtraces, as with the
testcases in the patch that follows.

This patch introduces support for the new encodings.  Tested on
amd64-linux-gnu.  Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdb-cfaval.patch --]
[-- Type: text/x-patch, Size: 20528 bytes --]

for gdb/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2-frame.h (enum dwarf2_frame_reg_rule): Add
	DWARF2_FRAME_REG_SAVED_VAL_OFFSET and
	DWARF2_FRAME_REG_SAVED_VAL_EXP.
	* dwarf2-frame.c (execute_cfa_program): Handle val_offset,
	val_offset_sf and val_expression.
	(dwarf2_frame_prev_register): Handle the new reg rules.

for gdb/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gdb.dwarf2/cfa-val-expr.exp: New test.
	* gdb.dwarf2/cfa-val-expr-1.c, gdb.dwarf2/cfa-val-expr-2.c:
	Its sources.

Index: gdb/dwarf2-frame.c
===================================================================
--- gdb/dwarf2-frame.c.orig	2006-01-18 15:44:55.000000000 -0200
+++ gdb/dwarf2-frame.c	2006-03-03 12:09:04.000000000 -0300
@@ -443,6 +443,34 @@ bad CFI data; mismatched DW_CFA_restore_
 	      fs->regs.reg[reg].loc.offset = offset;
 	      break;
 
+	    case DW_CFA_val_offset:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      offset = utmp * fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_offset_sf:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+	      offset *= fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_expression:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	      fs->regs.reg[reg].exp_len = utmp;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
+	      insn_ptr += utmp;
+	      break;
+
 	    case DW_CFA_def_cfa_sf:
 	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
 	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
@@ -891,6 +919,28 @@ dwarf2_frame_prev_register (struct frame
 	}
       break;
 
+    case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				cache->cfa + cache->reg[regnum].loc.offset);
+      break;
+
+    case DWARF2_FRAME_REG_SAVED_VAL_EXP:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				execute_stack_op (cache->reg[regnum].loc.exp,
+						  cache->reg[regnum].exp_len,
+						  next_frame, cache->cfa));
+      break;
+
     case DWARF2_FRAME_REG_UNSPECIFIED:
       /* GCC, in its infinite wisdom decided to not provide unwind
 	 information for registers that are "same value".  Since
Index: gdb/dwarf2-frame.h
===================================================================
--- gdb/dwarf2-frame.h.orig	2005-12-19 15:07:39.000000000 -0200
+++ gdb/dwarf2-frame.h	2006-03-03 07:46:10.000000000 -0300
@@ -51,6 +51,10 @@ enum dwarf2_frame_reg_rule
   DWARF2_FRAME_REG_SAVED_EXP,
   DWARF2_FRAME_REG_SAME_VALUE,
 
+  /* These are defined in Dwarf3.  */
+  DWARF2_FRAME_REG_SAVED_VAL_OFFSET,
+  DWARF2_FRAME_REG_SAVED_VAL_EXP,
+
   /* These aren't defined by the DWARF2 CFI specification, but are
      used internally by GDB.  */
   DWARF2_FRAME_REG_RA,		/* Return Address.  */
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c	2006-03-03 11:59:17.000000000 -0300
@@ -0,0 +1,261 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
+   support in GCC unwinders.  GDB does not need all of it, since all
+   we do is to try to get correct backtraces.  No compiler or binutils
+   support is required.  */
+
+/* Test complex CFA value expressions.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+		   _Unwind_Exception_Class exc_class,
+		   struct _Unwind_Exception *exc_obj,
+		   struct _Unwind_Context *context,
+		   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void
+force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+  abort ();
+}
+
+int count;
+
+static void
+counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void
+handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  _exit (0);
+}
+
+static int __attribute__((noinline))
+fn5 (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+void
+bar (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  fn5 ();
+}
+
+void __attribute__((noinline))
+foo (int x)
+{
+  char buf[256];
+#ifdef __i386__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leal	%1, %%ecx\n"
+"2:\t"	"call	bar\n"
+"3:\t"	"jmp	18f\n"
+"4:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"5:\t"	".long	7f-6f	# Length of Common Information Entry\n"
+"6:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -4	# CIE Data Alignment Factor\n\t"
+	".byte	0x8	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0xc	# DW_CFA_def_cfa\n\t"
+	".uleb128 0x4\n\t"
+	".uleb128 0x0\n\t"
+	".align 4\n"
+"7:\t"	".long	17f-8f	# FDE Length\n"
+"8:\t"	".long	8b-5b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	4b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 10f-9f\n"
+"9:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 3b-1b\n"
+"10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 12f-11f\n"
+"11:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 3b-2b\n"
+"12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 16f-13f\n"
+"13:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 15f-14f\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"14:\t"	".4byte	3b-.\n\t"
+	".byte	0x1c	# DW_OP_minus\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"15:\t"	".4byte	18f-.\n\t"
+	".byte	0x22	# DW_OP_plus\n"
+"16:\t"	".align 4\n"
+"17:\t"	".previous\n"
+"18:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "eax", "edx", "ecx");
+#elif defined __x86_64__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leaq	%1, %%rdi\n"
+"2:\t"	"subq	$128, %%rsp\n"
+"3:\t"	"call	bar\n"
+"4:\t"	"addq	$128, %%rsp\n"
+"5:\t"	"jmp	24f\n"
+"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
+"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -8	# CIE Data Alignment Factor\n\t"
+	".byte	0x10	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0x12	# DW_CFA_def_cfa_sf\n\t"
+	".uleb128 0x7\n\t"
+	".sleb128 16\n\t"
+	".align 8\n"
+"9:\t"	".long	23f-10f	# FDE Length\n"
+"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	6b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 12f-11f\n"
+"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-1b\n"
+"12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 14f-13f\n"
+"13:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-2b\n"
+"14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t"
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 0\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 16f-15f\n"
+"15:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-3b\n"
+"16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t"
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 128\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 20f-17f\n"
+"17:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 19f-18f\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"18:\t"	".4byte	4b-.\n\t"
+	".byte	0x1c	# DW_OP_minus\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"19:\t"	".4byte	24f-.\n\t"
+	".byte	0x22	# DW_OP_plus\n"
+"20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t"
+	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t"
+	".sleb128 16\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 22f-21f\n"
+"21:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-5b\n"
+"22:\t"	".align 8\n"
+"23:\t"	".previous\n"
+"24:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
+	  "r8", "r9", "r10", "r11");
+#else
+# error Unsupported test architecture
+#endif
+}
+
+static int __attribute__((noinline))
+fn2 (void)
+{
+  foo (3);
+  return 0;
+}
+
+static int __attribute__((noinline))
+fn1 (void)
+{
+  fn2 ();
+  return 0;
+}
+
+static void *
+fn0 (void)
+{
+  char dummy __attribute__((cleanup (handler)));
+  fn1 ();
+  return 0;
+}
+
+int
+main (void)
+{
+  fn0 ();
+  return 0;
+}
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c	2006-03-03 11:59:13.000000000 -0300
@@ -0,0 +1,226 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
+   support in GCC unwinders.  GDB does not need all of it, since all
+   we do is to try to get correct backtraces.  No compiler or binutils
+   support is required.  */
+
+/* Test complex CFA value expressions.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+		   _Unwind_Exception_Class exc_class,
+		   struct _Unwind_Exception *exc_obj,
+		   struct _Unwind_Context *context,
+		   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void
+force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+  abort ();
+}
+
+int count;
+
+static void
+counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void
+handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  _exit (0);
+}
+
+static int __attribute__((noinline))
+fn5 (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+void
+bar (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  fn5 ();
+}
+
+void __attribute__((noinline))
+foo (int x)
+{
+  char buf[256];
+#ifdef __x86_64__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leaq	%1, %%rdi\n"
+"2:\t"	"subq	$128, %%rsp\n"
+"3:\t"	"call	bar\n"
+"4:\t"	"addq	$128, %%rsp\n"
+"5:\t"	"jmp	21f\n"
+"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
+"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -8	# CIE Data Alignment Factor\n\t"
+	".byte	0x10	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0xc	# DW_CFA_def_cfa\n\t"
+	".uleb128 0x7\n\t"
+	".uleb128 0x0\n\t"
+	".align 8\n"
+"9:\t"	".long	20f-10f	# FDE Length\n"
+"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	6b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	/* This CFA expression computes the address right
+	   past the jnz instruction above, from %rip somewhere
+	   within the _L_mutex_lock_%= subsection.  */
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 19f-11f\n"
+"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 0\n"
+"12:\t"	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0x48\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	16f-13f\n"
+"13:\t"	".byte	0x13	# DW_OP_drop\n\t"
+	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	1\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0x81\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	15f-14f\n"
+"14:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 3b-2b-1\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-15f\n"
+"15:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 2b-1b-1\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-16f\n"
+"16:\t"	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0xe8\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	18f-17f\n"
+"17:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 4b-3b\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-18f\n"
+"18:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	4\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
+	".byte	0x24	# DW_OP_shl\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
+	".byte	0x26	# DW_OP_shra\n\t"
+	".byte	0x22	# DW_OP_plus\n\t"
+	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 6b-5b-1\n"
+"19:\t"	".byte	0x40 + (3b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 128\n\t"
+	".byte	0x40 + (5b-3b) # DW_CFA_advance_loc\n\t"
+	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 0\n\t"
+	".align 8\n"
+"20:\t"	".previous\n"
+"21:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
+	  "r8", "r9", "r10", "r11");
+#else
+# error Unsupported test architecture
+#endif
+}
+
+static int __attribute__((noinline))
+fn2 (void)
+{
+  foo (3);
+  return 0;
+}
+
+static int __attribute__((noinline))
+fn1 (void)
+{
+  fn2 ();
+  return 0;
+}
+
+static void *
+fn0 (void)
+{
+  char dummy __attribute__((cleanup (handler)));
+  fn1 ();
+  return 0;
+}
+
+int
+main (void)
+{
+  fn0 ();
+  return 0;
+}
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp	2006-03-03 12:07:51.000000000 -0300
@@ -0,0 +1,87 @@
+# Copyright 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Alexandre Oliva <aoliva@redhat.com>
+
+if $tracelevel then {
+	strace $tracelevel
+	}
+
+set prms_id 0
+set bug_id 0
+
+# signal-augm.S needs hand-coded assembly
+if {![istarget i*86-*-linux*]
+    && ![istarget x86_64-*-linux*]} {
+    return -1;
+}
+
+if [get_compiler_info "ignored"] {
+    return -1
+}
+
+if {$gcc_compiled == 0} {
+    return -1
+}
+
+set tnum 1
+set testfile "cfa-val-expr-$tnum"
+
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
+    return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+
+gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
+gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
+gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
+
+set tnum 2
+set testfile "cfa-val-expr-$tnum"
+
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
+    return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+
+gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
+gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
+gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
+
+return 0

[-- Attachment #3: Type: text/plain, Size: 249 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-03 17:54 Support Dwarf3 DW_CFA_val_* expressions Alexandre Oliva
@ 2006-03-04 12:01 ` Mark Kettenis
  2006-03-04 14:43   ` Alexandre Oliva
  0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2006-03-04 12:01 UTC (permalink / raw)
  To: aoliva; +Cc: gdb-patches

> From: Alexandre Oliva <aoliva@redhat.com>
> Date: Fri, 03 Mar 2006 12:30:57 -0300
> 
> Jakub has recently implemented some of the Dwarf3 CFA value
> expressions: http://sourceware.org/ml/binutils/2006-03/msg00009.html
> http://sourceware.org/ml/binutils/2006-03/msg00043.html
> 
> Support in the GCC unwinder is in the works (or maybe already
> contributed and I couldn't find it :-), but GDB is still missing
> support for such encodings.  Without this patch, when it encounters
> them, it complains loudly and fails to issue backtraces, as with the
> testcases in the patch that follows.
> 
> This patch introduces support for the new encodings.  Tested on
> amd64-linux-gnu.  Ok to install?

Thanks, the code looks fine.  It's also good to have a few testcases,
but I don't completely understand the testcases :( You seem to mess
with a lot of GCC internals in them.  Is the force_unwind() stuff
really necessary?  The tests are only enabled on Linux.  Is there a
reason why they won't work on other i386 and amd64 systems that use a
recent enough GCC?  And what would be the minimum version of GCC
needed to run these tests?

Mark

> for gdb/ChangeLog
> from  Alexandre Oliva  <aoliva@redhat.com>
> 
> 	* dwarf2-frame.h (enum dwarf2_frame_reg_rule): Add
> 	DWARF2_FRAME_REG_SAVED_VAL_OFFSET and
> 	DWARF2_FRAME_REG_SAVED_VAL_EXP.
> 	* dwarf2-frame.c (execute_cfa_program): Handle val_offset,
> 	val_offset_sf and val_expression.
> 	(dwarf2_frame_prev_register): Handle the new reg rules.
> 
> for gdb/testsuite/ChangeLog
> from  Alexandre Oliva  <aoliva@redhat.com>
> 
> 	* gdb.dwarf2/cfa-val-expr.exp: New test.
> 	* gdb.dwarf2/cfa-val-expr-1.c, gdb.dwarf2/cfa-val-expr-2.c:
> 	Its sources.
> 
> Index: gdb/dwarf2-frame.c
> ===================================================================
> --- gdb/dwarf2-frame.c.orig	2006-01-18 15:44:55.000000000 -0200
> +++ gdb/dwarf2-frame.c	2006-03-03 12:09:04.000000000 -0300
> @@ -443,6 +443,34 @@ bad CFI data; mismatched DW_CFA_restore_
>  	      fs->regs.reg[reg].loc.offset = offset;
>  	      break;
>  
> +	    case DW_CFA_val_offset:
> +	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
> +	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
> +	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
> +	      offset = utmp * fs->data_align;
> +	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
> +	      fs->regs.reg[reg].loc.offset = offset;
> +	      break;
> +
> +	    case DW_CFA_val_offset_sf:
> +	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
> +	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
> +	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
> +	      offset *= fs->data_align;
> +	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
> +	      fs->regs.reg[reg].loc.offset = offset;
> +	      break;
> +
> +	    case DW_CFA_val_expression:
> +	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
> +	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
> +	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
> +	      fs->regs.reg[reg].loc.exp = insn_ptr;
> +	      fs->regs.reg[reg].exp_len = utmp;
> +	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
> +	      insn_ptr += utmp;
> +	      break;
> +
>  	    case DW_CFA_def_cfa_sf:
>  	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
>  	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
> @@ -891,6 +919,28 @@ dwarf2_frame_prev_register (struct frame
>  	}
>        break;
>  
> +    case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
> +      *optimizedp = 0;
> +      *lvalp = not_lval;
> +      *addrp = 0;
> +      *realnump = -1;
> +      if (valuep)
> +	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
> +				cache->cfa + cache->reg[regnum].loc.offset);
> +      break;
> +
> +    case DWARF2_FRAME_REG_SAVED_VAL_EXP:
> +      *optimizedp = 0;
> +      *lvalp = not_lval;
> +      *addrp = 0;
> +      *realnump = -1;
> +      if (valuep)
> +	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
> +				execute_stack_op (cache->reg[regnum].loc.exp,
> +						  cache->reg[regnum].exp_len,
> +						  next_frame, cache->cfa));
> +      break;
> +
>      case DWARF2_FRAME_REG_UNSPECIFIED:
>        /* GCC, in its infinite wisdom decided to not provide unwind
>  	 information for registers that are "same value".  Since
> Index: gdb/dwarf2-frame.h
> ===================================================================
> --- gdb/dwarf2-frame.h.orig	2005-12-19 15:07:39.000000000 -0200
> +++ gdb/dwarf2-frame.h	2006-03-03 07:46:10.000000000 -0300
> @@ -51,6 +51,10 @@ enum dwarf2_frame_reg_rule
>    DWARF2_FRAME_REG_SAVED_EXP,
>    DWARF2_FRAME_REG_SAME_VALUE,
>  
> +  /* These are defined in Dwarf3.  */
> +  DWARF2_FRAME_REG_SAVED_VAL_OFFSET,
> +  DWARF2_FRAME_REG_SAVED_VAL_EXP,
> +
>    /* These aren't defined by the DWARF2 CFI specification, but are
>       used internally by GDB.  */
>    DWARF2_FRAME_REG_RA,		/* Return Address.  */
> Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c	2006-03-03 11:59:17.000000000 -0300
> @@ -0,0 +1,261 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2006  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 2 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, write to the Free Software
> +   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> +   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
> +   support in GCC unwinders.  GDB does not need all of it, since all
> +   we do is to try to get correct backtraces.  No compiler or binutils
> +   support is required.  */
> +
> +/* Test complex CFA value expressions.  */
> +
> +#include <unwind.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +static _Unwind_Reason_Code
> +force_unwind_stop (int version, _Unwind_Action actions,
> +		   _Unwind_Exception_Class exc_class,
> +		   struct _Unwind_Exception *exc_obj,
> +		   struct _Unwind_Context *context,
> +		   void *stop_parameter)
> +{
> +  if (actions & _UA_END_OF_STACK)
> +    abort ();
> +  return _URC_NO_REASON;
> +}
> +
> +static void
> +force_unwind ()
> +{
> +  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
> +  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
> +  exc->exception_cleanup = 0;
> +
> +  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
> +  abort ();
> +}
> +
> +int count;
> +
> +static void
> +counter (void *p __attribute__((unused)))
> +{
> +  ++count;
> +}
> +
> +static void
> +handler (void *p __attribute__((unused)))
> +{
> +  if (count != 2)
> +    abort ();
> +  _exit (0);
> +}
> +
> +static int __attribute__((noinline))
> +fn5 (void)
> +{
> +  char dummy __attribute__((cleanup (counter)));
> +  force_unwind ();
> +  return 0;
> +}
> +
> +void
> +bar (void)
> +{
> +  char dummy __attribute__((cleanup (counter)));
> +  fn5 ();
> +}
> +
> +void __attribute__((noinline))
> +foo (int x)
> +{
> +  char buf[256];
> +#ifdef __i386__
> +  __asm (
> +	"testl	%0, %0\n\t"
> +	"jnz	1f\n\t"
> +	".subsection 1\n\t"
> +	".type	_L_mutex_lock_%=, @function\n"
> +"_L_mutex_lock_%=:\n"
> +"1:\t"	"leal	%1, %%ecx\n"
> +"2:\t"	"call	bar\n"
> +"3:\t"	"jmp	18f\n"
> +"4:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
> +	".previous\n\t"
> +	".section	.eh_frame,\"a\",@progbits\n"
> +"5:\t"	".long	7f-6f	# Length of Common Information Entry\n"
> +"6:\t"	".long	0x0	# CIE Identifier Tag\n\t"
> +	".byte	0x1	# CIE Version\n\t"
> +	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
> +	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
> +	".sleb128 -4	# CIE Data Alignment Factor\n\t"
> +	".byte	0x8	# CIE RA Column\n\t"
> +	".uleb128 0x1	# Augmentation size\n\t"
> +	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
> +	".byte	0xc	# DW_CFA_def_cfa\n\t"
> +	".uleb128 0x4\n\t"
> +	".uleb128 0x0\n\t"
> +	".align 4\n"
> +"7:\t"	".long	17f-8f	# FDE Length\n"
> +"8:\t"	".long	8b-5b	# FDE CIE offset\n\t"
> +	".long	1b-.	# FDE initial location\n\t"
> +	".long	4b-1b	# FDE address range\n\t"
> +	".uleb128 0x0	# Augmentation size\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x8\n\t"
> +	".uleb128 10f-9f\n"
> +"9:\t"	".byte	0x78	# DW_OP_breg8\n\t"
> +	".sleb128 3b-1b\n"
> +"10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x8\n\t"
> +	".uleb128 12f-11f\n"
> +"11:\t"	".byte	0x78	# DW_OP_breg8\n\t"
> +	".sleb128 3b-2b\n"
> +"12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x8\n\t"
> +	".uleb128 16f-13f\n"
> +"13:\t"	".byte	0x78	# DW_OP_breg8\n\t"
> +	".sleb128 15f-14f\n\t"
> +	".byte	0x0d	# DW_OP_const4s\n"
> +"14:\t"	".4byte	3b-.\n\t"
> +	".byte	0x1c	# DW_OP_minus\n\t"
> +	".byte	0x0d	# DW_OP_const4s\n"
> +"15:\t"	".4byte	18f-.\n\t"
> +	".byte	0x22	# DW_OP_plus\n"
> +"16:\t"	".align 4\n"
> +"17:\t"	".previous\n"
> +"18:"
> +	: : "r" (x), "m" (x), "r" (buf)
> +	: "memory", "eax", "edx", "ecx");
> +#elif defined __x86_64__
> +  __asm (
> +	"testl	%0, %0\n\t"
> +	"jnz	1f\n\t"
> +	".subsection 1\n\t"
> +	".type	_L_mutex_lock_%=, @function\n"
> +"_L_mutex_lock_%=:\n"
> +"1:\t"	"leaq	%1, %%rdi\n"
> +"2:\t"	"subq	$128, %%rsp\n"
> +"3:\t"	"call	bar\n"
> +"4:\t"	"addq	$128, %%rsp\n"
> +"5:\t"	"jmp	24f\n"
> +"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
> +	".previous\n\t"
> +	".section	.eh_frame,\"a\",@progbits\n"
> +"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
> +"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
> +	".byte	0x1	# CIE Version\n\t"
> +	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
> +	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
> +	".sleb128 -8	# CIE Data Alignment Factor\n\t"
> +	".byte	0x10	# CIE RA Column\n\t"
> +	".uleb128 0x1	# Augmentation size\n\t"
> +	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
> +	".byte	0x12	# DW_CFA_def_cfa_sf\n\t"
> +	".uleb128 0x7\n\t"
> +	".sleb128 16\n\t"
> +	".align 8\n"
> +"9:\t"	".long	23f-10f	# FDE Length\n"
> +"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
> +	".long	1b-.	# FDE initial location\n\t"
> +	".long	6b-1b	# FDE address range\n\t"
> +	".uleb128 0x0	# Augmentation size\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 12f-11f\n"
> +"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 4b-1b\n"
> +"12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 14f-13f\n"
> +"13:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 4b-2b\n"
> +"14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t"
> +	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
> +	".uleb128 0\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 16f-15f\n"
> +"15:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 4b-3b\n"
> +"16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t"
> +	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
> +	".uleb128 128\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 20f-17f\n"
> +"17:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 19f-18f\n\t"
> +	".byte	0x0d	# DW_OP_const4s\n"
> +"18:\t"	".4byte	4b-.\n\t"
> +	".byte	0x1c	# DW_OP_minus\n\t"
> +	".byte	0x0d	# DW_OP_const4s\n"
> +"19:\t"	".4byte	24f-.\n\t"
> +	".byte	0x22	# DW_OP_plus\n"
> +"20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t"
> +	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t"
> +	".sleb128 16\n\t"
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 22f-21f\n"
> +"21:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 4b-5b\n"
> +"22:\t"	".align 8\n"
> +"23:\t"	".previous\n"
> +"24:"
> +	: : "r" (x), "m" (x), "r" (buf)
> +	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
> +	  "r8", "r9", "r10", "r11");
> +#else
> +# error Unsupported test architecture
> +#endif
> +}
> +
> +static int __attribute__((noinline))
> +fn2 (void)
> +{
> +  foo (3);
> +  return 0;
> +}
> +
> +static int __attribute__((noinline))
> +fn1 (void)
> +{
> +  fn2 ();
> +  return 0;
> +}
> +
> +static void *
> +fn0 (void)
> +{
> +  char dummy __attribute__((cleanup (handler)));
> +  fn1 ();
> +  return 0;
> +}
> +
> +int
> +main (void)
> +{
> +  fn0 ();
> +  return 0;
> +}
> Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c	2006-03-03 11:59:13.000000000 -0300
> @@ -0,0 +1,226 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2006  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 2 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, write to the Free Software
> +   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> +   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
> +   support in GCC unwinders.  GDB does not need all of it, since all
> +   we do is to try to get correct backtraces.  No compiler or binutils
> +   support is required.  */
> +
> +/* Test complex CFA value expressions.  */
> +
> +#include <unwind.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +static _Unwind_Reason_Code
> +force_unwind_stop (int version, _Unwind_Action actions,
> +		   _Unwind_Exception_Class exc_class,
> +		   struct _Unwind_Exception *exc_obj,
> +		   struct _Unwind_Context *context,
> +		   void *stop_parameter)
> +{
> +  if (actions & _UA_END_OF_STACK)
> +    abort ();
> +  return _URC_NO_REASON;
> +}
> +
> +static void
> +force_unwind ()
> +{
> +  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
> +  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
> +  exc->exception_cleanup = 0;
> +
> +  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
> +  abort ();
> +}
> +
> +int count;
> +
> +static void
> +counter (void *p __attribute__((unused)))
> +{
> +  ++count;
> +}
> +
> +static void
> +handler (void *p __attribute__((unused)))
> +{
> +  if (count != 2)
> +    abort ();
> +  _exit (0);
> +}
> +
> +static int __attribute__((noinline))
> +fn5 (void)
> +{
> +  char dummy __attribute__((cleanup (counter)));
> +  force_unwind ();
> +  return 0;
> +}
> +
> +void
> +bar (void)
> +{
> +  char dummy __attribute__((cleanup (counter)));
> +  fn5 ();
> +}
> +
> +void __attribute__((noinline))
> +foo (int x)
> +{
> +  char buf[256];
> +#ifdef __x86_64__
> +  __asm (
> +	"testl	%0, %0\n\t"
> +	"jnz	1f\n\t"
> +	".subsection 1\n\t"
> +	".type	_L_mutex_lock_%=, @function\n"
> +"_L_mutex_lock_%=:\n"
> +"1:\t"	"leaq	%1, %%rdi\n"
> +"2:\t"	"subq	$128, %%rsp\n"
> +"3:\t"	"call	bar\n"
> +"4:\t"	"addq	$128, %%rsp\n"
> +"5:\t"	"jmp	21f\n"
> +"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
> +	".previous\n\t"
> +	".section	.eh_frame,\"a\",@progbits\n"
> +"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
> +"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
> +	".byte	0x1	# CIE Version\n\t"
> +	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
> +	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
> +	".sleb128 -8	# CIE Data Alignment Factor\n\t"
> +	".byte	0x10	# CIE RA Column\n\t"
> +	".uleb128 0x1	# Augmentation size\n\t"
> +	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
> +	".byte	0xc	# DW_CFA_def_cfa\n\t"
> +	".uleb128 0x7\n\t"
> +	".uleb128 0x0\n\t"
> +	".align 8\n"
> +"9:\t"	".long	20f-10f	# FDE Length\n"
> +"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
> +	".long	1b-.	# FDE initial location\n\t"
> +	".long	6b-1b	# FDE address range\n\t"
> +	".uleb128 0x0	# Augmentation size\n\t"
> +	/* This CFA expression computes the address right
> +	   past the jnz instruction above, from %rip somewhere
> +	   within the _L_mutex_lock_%= subsection.  */
> +	".byte	0x16	# DW_CFA_val_expression\n\t"
> +	".uleb128 0x10\n\t"
> +	".uleb128 19f-11f\n"
> +"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
> +	".sleb128 0\n"
> +"12:\t"	".byte	0x12	# DW_OP_dup\n\t"
> +	".byte	0x94	# DW_OP_deref_size\n\t"
> +	".byte	1\n\t"
> +	".byte	0x12	# DW_OP_dup\n\t"
> +	".byte	0x08	# DW_OP_const1u\n\t"
> +	".byte	0x48\n\t"
> +	".byte	0x2e	# DW_OP_ne\n\t"
> +	".byte	0x28	# DW_OP_bra\n\t"
> +	".2byte	16f-13f\n"
> +"13:\t"	".byte	0x13	# DW_OP_drop\n\t"
> +	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 1\n\t"
> +	".byte	0x12	# DW_OP_dup\n\t"
> +	".byte	0x94	# DW_OP_deref_size\n\t"
> +	".byte	1\n\t"
> +	".byte	0x08	# DW_OP_const1u\n\t"
> +	".byte	0x81\n\t"
> +	".byte	0x2e	# DW_OP_ne\n\t"
> +	".byte	0x28	# DW_OP_bra\n\t"
> +	".2byte	15f-14f\n"
> +"14:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 3b-2b-1\n\t"
> +	".byte	0x2f	# DW_OP_skip\n\t"
> +	".2byte	12b-15f\n"
> +"15:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 2b-1b-1\n\t"
> +	".byte	0x2f	# DW_OP_skip\n\t"
> +	".2byte	12b-16f\n"
> +"16:\t"	".byte	0x08	# DW_OP_const1u\n\t"
> +	".byte	0xe8\n\t"
> +	".byte	0x2e	# DW_OP_ne\n\t"
> +	".byte	0x28	# DW_OP_bra\n\t"
> +	".2byte	18f-17f\n"
> +"17:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 4b-3b\n\t"
> +	".byte	0x2f	# DW_OP_skip\n\t"
> +	".2byte	12b-18f\n"
> +"18:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 1\n\t"
> +	".byte	0x12	# DW_OP_dup\n\t"
> +	".byte	0x94	# DW_OP_deref_size\n\t"
> +	".byte	4\n\t"
> +	".byte	0x08	# DW_OP_const1u\n\t"
> +	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
> +	".byte	0x24	# DW_OP_shl\n\t"
> +	".byte	0x08	# DW_OP_const1u\n\t"
> +	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
> +	".byte	0x26	# DW_OP_shra\n\t"
> +	".byte	0x22	# DW_OP_plus\n\t"
> +	".byte	0x23	# DW_OP_plus_uconst\n\t"
> +	".uleb128 6b-5b-1\n"
> +"19:\t"	".byte	0x40 + (3b-1b) # DW_CFA_advance_loc\n\t"
> +	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
> +	".uleb128 128\n\t"
> +	".byte	0x40 + (5b-3b) # DW_CFA_advance_loc\n\t"
> +	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
> +	".uleb128 0\n\t"
> +	".align 8\n"
> +"20:\t"	".previous\n"
> +"21:"
> +	: : "r" (x), "m" (x), "r" (buf)
> +	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
> +	  "r8", "r9", "r10", "r11");
> +#else
> +# error Unsupported test architecture
> +#endif
> +}
> +
> +static int __attribute__((noinline))
> +fn2 (void)
> +{
> +  foo (3);
> +  return 0;
> +}
> +
> +static int __attribute__((noinline))
> +fn1 (void)
> +{
> +  fn2 ();
> +  return 0;
> +}
> +
> +static void *
> +fn0 (void)
> +{
> +  char dummy __attribute__((cleanup (handler)));
> +  fn1 ();
> +  return 0;
> +}
> +
> +int
> +main (void)
> +{
> +  fn0 ();
> +  return 0;
> +}
> Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp	2006-03-03 12:07:51.000000000 -0300
> @@ -0,0 +1,87 @@
> +# Copyright 2006 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 2 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, write to the Free Software
> +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> +# Please email any bugs, comments, and/or additions to this file to:
> +# bug-gdb@prep.ai.mit.edu
> +
> +# This file was written by Alexandre Oliva <aoliva@redhat.com>
> +
> +if $tracelevel then {
> +	strace $tracelevel
> +	}
> +
> +set prms_id 0
> +set bug_id 0
> +
> +# signal-augm.S needs hand-coded assembly
> +if {![istarget i*86-*-linux*]
> +    && ![istarget x86_64-*-linux*]} {
> +    return -1;
> +}
> +
> +if [get_compiler_info "ignored"] {
> +    return -1
> +}
> +
> +if {$gcc_compiled == 0} {
> +    return -1
> +}
> +
> +set tnum 1
> +set testfile "cfa-val-expr-$tnum"
> +
> +set srcfile ${srcdir}/${subdir}/${testfile}.c
> +set binfile ${objdir}/${subdir}/${testfile}
> +if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
> +    return -1;
> +}
> +
> +gdb_exit
> +gdb_start
> +gdb_reinitialize_dir $srcdir/$subdir
> +gdb_load ${binfile}
> +
> +if [target_info exists gdb_stub] {
> +    gdb_step_for_stub;
> +}
> +
> +gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
> +gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
> +gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
> +
> +set tnum 2
> +set testfile "cfa-val-expr-$tnum"
> +
> +set srcfile ${srcdir}/${subdir}/${testfile}.c
> +set binfile ${objdir}/${subdir}/${testfile}
> +if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
> +    return -1;
> +}
> +
> +gdb_exit
> +gdb_start
> +gdb_reinitialize_dir $srcdir/$subdir
> +gdb_load ${binfile}
> +
> +if [target_info exists gdb_stub] {
> +    gdb_step_for_stub;
> +}
> +
> +gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
> +gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
> +gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
> +
> +return 0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-04 12:01 ` Mark Kettenis
@ 2006-03-04 14:43   ` Alexandre Oliva
  2006-03-04 15:07     ` Daniel Jacobowitz
  0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2006-03-04 14:43 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

On Mar  4, 2006, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:

> Thanks, the code looks fine.

Is this to be read as an ok to install?  (Sorry, I've been just a
lurker here in the past and I'm not entirely familiar with the rules
about who can approve what, so I thought I'd ask instead of ASSuming
:-)

> It's also good to have a few testcases,
> but I don't completely understand the testcases :(

You're not alone in that feeling, I assure you :-)

> You seem to mess
> with a lot of GCC internals in them.  Is the force_unwind() stuff
> really necessary?

Not for GDB, no.  We don't even reach that point.  I thought we'd be
better off keeping the testcase in sync with GCC, so all I did was to
add the initial comment.  The execution within GDB doesn't ever reach
the point of run-time-wise unwinding the stack.  GDB does something
similar by unwinding the stack to get a backtrace at the point from
which the GCC unwinder would be called.

> The tests are only enabled on Linux.  Is there a
> reason why they won't work on other i386 and amd64 systems that use a
> recent enough GCC?

I have no idea, I suppose someone with easy access to them could test
them and let me know :-)

At some point I had only the architectures listed in the .exp file,
but then I thought that some of them might not even use Dwarf2+ debug
info, and decided I'd go with only what I could test myself.

> And what would be the minimum version of GCC
> needed to run these tests?

To actually run them successfully to completion, without the debugger
interaction, you'd need some upcoming version of GCC, perhaps even
with patches yet to be checked in.  To compile it and run it up to the
point we need in the GDB test, I'm pretty sure even GCC 2.95 would do;
perhaps something even older than that.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-04 14:43   ` Alexandre Oliva
@ 2006-03-04 15:07     ` Daniel Jacobowitz
  2006-03-07 14:25       ` Alexandre Oliva
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-03-04 15:07 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Mark Kettenis, gdb-patches

On Sat, Mar 04, 2006 at 09:01:43AM -0300, Alexandre Oliva wrote:
> > It's also good to have a few testcases,
> > but I don't completely understand the testcases :(
> 
> You're not alone in that feeling, I assure you :-)

Like Mark, I am happier with the code than the testcases.  In fact,
I'd rather not have the tests at all than have something quite
so overkill.  And you're not correct that older GCCs could run them
far enough to test; they'll fail to build because of the use of
__attribute__((cleanup)) (and the fact that dejagnu treats warnings
as fatal).

You ought to be able to test this much more simply, if you wire it
up to the bits in gdb.asm.  I'm thinking something like this:

gdbasm_declare foo
gdbasm_enter
gdbasm_call bar
.cfi_startproc
.cfi_return_column 0
.cfi_undefined 0
gdbasm_leave
.cfi_endproc
gdbasm_end foo

You ought to be able to backtrace from the call statement, without
unwind info, and you ought to be unable to backtrace from the epilogue,
where the dwarf2 unwinder will kick in and say you've hit the end of
the stack.  Whether bar has a signal augmentation or not will determine
whether you can backtrace from it to foo's caller or not.

Unfortunately if you want to put the signal augmentation on bar you'll
also need unwind info for it; I guess that would require an addition
to the gdb.asm bits.  Then, just refuse to test if the testcase doesn't
assemble.

I'm sure it won't work for some platforms, and we'll have to add some
skips in the .exp file, but it ought to get enough of the current
ELF/dwarf platforms to be interesting, don't you think?

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-04 15:07     ` Daniel Jacobowitz
@ 2006-03-07 14:25       ` Alexandre Oliva
  2006-03-07 15:01         ` Mark Kettenis
  0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2006-03-07 14:25 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2074 bytes --]

On Mar  4, 2006, Daniel Jacobowitz <drow@false.org> wrote:

> On Sat, Mar 04, 2006 at 09:01:43AM -0300, Alexandre Oliva wrote:
>> > It's also good to have a few testcases,
>> > but I don't completely understand the testcases :(
>> 
>> You're not alone in that feeling, I assure you :-)

> Like Mark, I am happier with the code than the testcases.  In fact,
> I'd rather not have the tests at all than have something quite
> so overkill.

Fair enough...  Those tests uncovered a problem with the way our
dwarf2 code identifies frames, though: it uses the function start
address and the CFA to identify a stack frame, whereas it should use
the PC and the CFA.  In some corner cases, such as the one exercised
by the i386 testcase, if you're on the second instruction of the
region covered by the hand-generated unwind info and ask for a
backtrace, GDB complains that the stack is corrupt, but the only
problem is that the dwarf2 machinery gets confused by the same-CFA,
same-function pair of stack frames.  This is fixed in the revised
patch below.

> And you're not correct that older GCCs could run them
> far enough to test; they'll fail to build because of the use of
> __attribute__((cleanup))

Oops, indeed, sorry about that.  The testcases must definitely be
amended if they're to remain.  Should they?

> You ought to be able to test this much more simply, if you wire it
> up to the bits in gdb.asm.

But that wouldn't have caught errors in processing complex dwarf
expressions, which the current testcases did in an older tree.

> I'm sure it won't work for some platforms, and we'll have to add some
> skips in the .exp file, but it ought to get enough of the current
> ELF/dwarf platforms to be interesting, don't you think?

Not sure...  You talked about signal augmentations, but that's a
different patch in a different thread.  This one is about complex
dwarf2 expressions involving newly-introduced encodings.

I'm not sure how to encode such tests with gdb.asm, but I may look
into it if dropping the tests in the following updated patch is not
good enough.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdb-cfaval.patch --]
[-- Type: text/x-patch, Size: 20928 bytes --]

for gdb/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2-frame.h (enum dwarf2_frame_reg_rule): Add
	DWARF2_FRAME_REG_SAVED_VAL_OFFSET and
	DWARF2_FRAME_REG_SAVED_VAL_EXP.
	* dwarf2-frame.c (execute_cfa_program): Handle val_offset,
	val_offset_sf and val_expression.
	(dwarf2_frame_prev_register): Handle the new reg rules.
	(dwarf2_frame_this_id): Use pc instead of function entry point.

for gdb/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gdb.dwarf2/cfa-val-expr.exp: New test.
	* gdb.dwarf2/cfa-val-expr-1.c, gdb.dwarf2/cfa-val-expr-2.c:
	Its sources.

Index: gdb/dwarf2-frame.c
===================================================================
--- gdb/dwarf2-frame.c.orig	2006-03-07 02:06:03.000000000 -0300
+++ gdb/dwarf2-frame.c	2006-03-07 02:06:07.000000000 -0300
@@ -446,6 +446,34 @@ bad CFI data; mismatched DW_CFA_restore_
 	      fs->regs.reg[reg].loc.offset = offset;
 	      break;
 
+	    case DW_CFA_val_offset:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      offset = utmp * fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_offset_sf:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+	      offset *= fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_expression:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	      fs->regs.reg[reg].exp_len = utmp;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
+	      insn_ptr += utmp;
+	      break;
+
 	    case DW_CFA_def_cfa_sf:
 	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
 	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
@@ -828,7 +856,7 @@ dwarf2_frame_this_id (struct frame_info 
   if (cache->undefined_retaddr)
     return;
 
-  (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame));
+  (*this_id) = frame_id_build (cache->cfa, frame_pc_unwind (next_frame));
 }
 
 static void
@@ -894,6 +922,28 @@ dwarf2_frame_prev_register (struct frame
 	}
       break;
 
+    case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				cache->cfa + cache->reg[regnum].loc.offset);
+      break;
+
+    case DWARF2_FRAME_REG_SAVED_VAL_EXP:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				execute_stack_op (cache->reg[regnum].loc.exp,
+						  cache->reg[regnum].exp_len,
+						  next_frame, cache->cfa));
+      break;
+
     case DWARF2_FRAME_REG_UNSPECIFIED:
       /* GCC, in its infinite wisdom decided to not provide unwind
 	 information for registers that are "same value".  Since
Index: gdb/dwarf2-frame.h
===================================================================
--- gdb/dwarf2-frame.h.orig	2006-03-07 02:06:03.000000000 -0300
+++ gdb/dwarf2-frame.h	2006-03-07 02:06:07.000000000 -0300
@@ -51,6 +51,10 @@ enum dwarf2_frame_reg_rule
   DWARF2_FRAME_REG_SAVED_EXP,
   DWARF2_FRAME_REG_SAME_VALUE,
 
+  /* These are defined in Dwarf3.  */
+  DWARF2_FRAME_REG_SAVED_VAL_OFFSET,
+  DWARF2_FRAME_REG_SAVED_VAL_EXP,
+
   /* These aren't defined by the DWARF2 CFI specification, but are
      used internally by GDB.  */
   DWARF2_FRAME_REG_RA,		/* Return Address.  */
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c	2006-03-07 02:06:07.000000000 -0300
@@ -0,0 +1,261 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
+   support in GCC unwinders.  GDB does not need all of it, since all
+   we do is to try to get correct backtraces.  No compiler or binutils
+   support is required.  */
+
+/* Test complex CFA value expressions.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+		   _Unwind_Exception_Class exc_class,
+		   struct _Unwind_Exception *exc_obj,
+		   struct _Unwind_Context *context,
+		   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void
+force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+  abort ();
+}
+
+int count;
+
+static void
+counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void
+handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  _exit (0);
+}
+
+static int __attribute__((noinline))
+fn5 (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+void
+bar (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  fn5 ();
+}
+
+void __attribute__((noinline))
+foo (int x)
+{
+  char buf[256];
+#ifdef __i386__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leal	%1, %%ecx\n"
+"2:\t"	"call	bar\n"
+"3:\t"	"jmp	18f\n"
+"4:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"5:\t"	".long	7f-6f	# Length of Common Information Entry\n"
+"6:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -4	# CIE Data Alignment Factor\n\t"
+	".byte	0x8	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0xc	# DW_CFA_def_cfa\n\t"
+	".uleb128 0x4\n\t"
+	".uleb128 0x0\n\t"
+	".align 4\n"
+"7:\t"	".long	17f-8f	# FDE Length\n"
+"8:\t"	".long	8b-5b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	4b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 10f-9f\n"
+"9:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 3b-1b\n"
+"10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 12f-11f\n"
+"11:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 3b-2b\n"
+"12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x8\n\t"
+	".uleb128 16f-13f\n"
+"13:\t"	".byte	0x78	# DW_OP_breg8\n\t"
+	".sleb128 15f-14f\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"14:\t"	".4byte	3b-.\n\t"
+	".byte	0x1c	# DW_OP_minus\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"15:\t"	".4byte	18f-.\n\t"
+	".byte	0x22	# DW_OP_plus\n"
+"16:\t"	".align 4\n"
+"17:\t"	".previous\n"
+"18:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "eax", "edx", "ecx");
+#elif defined __x86_64__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leaq	%1, %%rdi\n"
+"2:\t"	"subq	$128, %%rsp\n"
+"3:\t"	"call	bar\n"
+"4:\t"	"addq	$128, %%rsp\n"
+"5:\t"	"jmp	24f\n"
+"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
+"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -8	# CIE Data Alignment Factor\n\t"
+	".byte	0x10	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0x12	# DW_CFA_def_cfa_sf\n\t"
+	".uleb128 0x7\n\t"
+	".sleb128 16\n\t"
+	".align 8\n"
+"9:\t"	".long	23f-10f	# FDE Length\n"
+"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	6b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 12f-11f\n"
+"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-1b\n"
+"12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 14f-13f\n"
+"13:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-2b\n"
+"14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t"
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 0\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 16f-15f\n"
+"15:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-3b\n"
+"16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t"
+	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 128\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 20f-17f\n"
+"17:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 19f-18f\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"18:\t"	".4byte	4b-.\n\t"
+	".byte	0x1c	# DW_OP_minus\n\t"
+	".byte	0x0d	# DW_OP_const4s\n"
+"19:\t"	".4byte	24f-.\n\t"
+	".byte	0x22	# DW_OP_plus\n"
+"20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t"
+	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t"
+	".sleb128 16\n\t"
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 22f-21f\n"
+"21:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 4b-5b\n"
+"22:\t"	".align 8\n"
+"23:\t"	".previous\n"
+"24:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
+	  "r8", "r9", "r10", "r11");
+#else
+# error Unsupported test architecture
+#endif
+}
+
+static int __attribute__((noinline))
+fn2 (void)
+{
+  foo (3);
+  return 0;
+}
+
+static int __attribute__((noinline))
+fn1 (void)
+{
+  fn2 ();
+  return 0;
+}
+
+static void *
+fn0 (void)
+{
+  char dummy __attribute__((cleanup (handler)));
+  fn1 ();
+  return 0;
+}
+
+int
+main (void)
+{
+  fn0 ();
+  return 0;
+}
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr-2.c	2006-03-07 02:06:07.000000000 -0300
@@ -0,0 +1,226 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for Dwarf3 value expression
+   support in GCC unwinders.  GDB does not need all of it, since all
+   we do is to try to get correct backtraces.  No compiler or binutils
+   support is required.  */
+
+/* Test complex CFA value expressions.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+		   _Unwind_Exception_Class exc_class,
+		   struct _Unwind_Exception *exc_obj,
+		   struct _Unwind_Context *context,
+		   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void
+force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+  abort ();
+}
+
+int count;
+
+static void
+counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void
+handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  _exit (0);
+}
+
+static int __attribute__((noinline))
+fn5 (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+void
+bar (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  fn5 ();
+}
+
+void __attribute__((noinline))
+foo (int x)
+{
+  char buf[256];
+#ifdef __x86_64__
+  __asm (
+	"testl	%0, %0\n\t"
+	"jnz	1f\n\t"
+	".subsection 1\n\t"
+	".type	_L_mutex_lock_%=, @function\n"
+"_L_mutex_lock_%=:\n"
+"1:\t"	"leaq	%1, %%rdi\n"
+"2:\t"	"subq	$128, %%rsp\n"
+"3:\t"	"call	bar\n"
+"4:\t"	"addq	$128, %%rsp\n"
+"5:\t"	"jmp	21f\n"
+"6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
+	".previous\n\t"
+	".section	.eh_frame,\"a\",@progbits\n"
+"7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
+"8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
+	".byte	0x1	# CIE Version\n\t"
+	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
+	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
+	".sleb128 -8	# CIE Data Alignment Factor\n\t"
+	".byte	0x10	# CIE RA Column\n\t"
+	".uleb128 0x1	# Augmentation size\n\t"
+	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
+	".byte	0xc	# DW_CFA_def_cfa\n\t"
+	".uleb128 0x7\n\t"
+	".uleb128 0x0\n\t"
+	".align 8\n"
+"9:\t"	".long	20f-10f	# FDE Length\n"
+"10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
+	".long	1b-.	# FDE initial location\n\t"
+	".long	6b-1b	# FDE address range\n\t"
+	".uleb128 0x0	# Augmentation size\n\t"
+	/* This CFA expression computes the address right
+	   past the jnz instruction above, from %rip somewhere
+	   within the _L_mutex_lock_%= subsection.  */
+	".byte	0x16	# DW_CFA_val_expression\n\t"
+	".uleb128 0x10\n\t"
+	".uleb128 19f-11f\n"
+"11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
+	".sleb128 0\n"
+"12:\t"	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0x48\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	16f-13f\n"
+"13:\t"	".byte	0x13	# DW_OP_drop\n\t"
+	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	1\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0x81\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	15f-14f\n"
+"14:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 3b-2b-1\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-15f\n"
+"15:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 2b-1b-1\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-16f\n"
+"16:\t"	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	0xe8\n\t"
+	".byte	0x2e	# DW_OP_ne\n\t"
+	".byte	0x28	# DW_OP_bra\n\t"
+	".2byte	18f-17f\n"
+"17:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 4b-3b\n\t"
+	".byte	0x2f	# DW_OP_skip\n\t"
+	".2byte	12b-18f\n"
+"18:\t"	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 1\n\t"
+	".byte	0x12	# DW_OP_dup\n\t"
+	".byte	0x94	# DW_OP_deref_size\n\t"
+	".byte	4\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
+	".byte	0x24	# DW_OP_shl\n\t"
+	".byte	0x08	# DW_OP_const1u\n\t"
+	".byte	72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
+	".byte	0x26	# DW_OP_shra\n\t"
+	".byte	0x22	# DW_OP_plus\n\t"
+	".byte	0x23	# DW_OP_plus_uconst\n\t"
+	".uleb128 6b-5b-1\n"
+"19:\t"	".byte	0x40 + (3b-1b) # DW_CFA_advance_loc\n\t"
+	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 128\n\t"
+	".byte	0x40 + (5b-3b) # DW_CFA_advance_loc\n\t"
+	".byte	0xe	# DW_CFA_def_cfa_offset\n\t"
+	".uleb128 0\n\t"
+	".align 8\n"
+"20:\t"	".previous\n"
+"21:"
+	: : "r" (x), "m" (x), "r" (buf)
+	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
+	  "r8", "r9", "r10", "r11");
+#else
+# error Unsupported test architecture
+#endif
+}
+
+static int __attribute__((noinline))
+fn2 (void)
+{
+  foo (3);
+  return 0;
+}
+
+static int __attribute__((noinline))
+fn1 (void)
+{
+  fn2 ();
+  return 0;
+}
+
+static void *
+fn0 (void)
+{
+  char dummy __attribute__((cleanup (handler)));
+  fn1 ();
+  return 0;
+}
+
+int
+main (void)
+{
+  fn0 ();
+  return 0;
+}
Index: gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/cfa-val-expr.exp	2006-03-07 02:06:07.000000000 -0300
@@ -0,0 +1,91 @@
+# Copyright 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Alexandre Oliva <aoliva@redhat.com>
+
+if $tracelevel then {
+	strace $tracelevel
+	}
+
+set prms_id 0
+set bug_id 0
+
+# signal-augm.S needs hand-coded assembly
+if {![istarget i*86-*-linux*]
+    && ![istarget x86_64-*-linux*]} {
+    return -1;
+}
+
+if [get_compiler_info "ignored"] {
+    return -1
+}
+
+if {$gcc_compiled == 0} {
+    return -1
+}
+
+set tnum 1
+set testfile "cfa-val-expr-$tnum"
+
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
+    return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+
+gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
+gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
+gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
+
+if {![istarget x86_64-*-linux*]} {
+    return 0;
+}
+
+set tnum 2
+set testfile "cfa-val-expr-$tnum"
+
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug "additional_flags=-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
+    return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+
+gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5 ($tnum)"
+gdb_test "run" ".*Breakpoint 1.*" "stopped at fn5 ($tnum)"
+gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* bar .*\#2 .* _L_mutex.* .*\#3 .* foo .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* main.*" "backtrace ($tnum)"
+
+return 0

[-- Attachment #3: Type: text/plain, Size: 249 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-07 14:25       ` Alexandre Oliva
@ 2006-03-07 15:01         ` Mark Kettenis
  2006-03-07 19:55           ` Alexandre Oliva
  0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2006-03-07 15:01 UTC (permalink / raw)
  To: aoliva; +Cc: gdb-patches

> From: Alexandre Oliva <aoliva@redhat.com>
> Date: Tue, 07 Mar 2006 02:31:27 -0300
> 
> On Mar  4, 2006, Daniel Jacobowitz <drow@false.org> wrote:
> 
> > On Sat, Mar 04, 2006 at 09:01:43AM -0300, Alexandre Oliva wrote:
> >> > It's also good to have a few testcases,
> >> > but I don't completely understand the testcases :(
> >> 
> >> You're not alone in that feeling, I assure you :-)
> 
> > Like Mark, I am happier with the code than the testcases.  In fact,
> > I'd rather not have the tests at all than have something quite
> > so overkill.
> 
> Fair enough...  Those tests uncovered a problem with the way our
> dwarf2 code identifies frames, though: it uses the function start
> address and the CFA to identify a stack frame, whereas it should use
> the PC and the CFA.

Nope, using the function address is the correct thing to do.
Otherwise you'll end up with a different frame ID if you single-step
to the next instruction for example.

> In some corner cases, such as the one exercised by the i386
> testcase, if you're on the second instruction of the region covered
> by the hand-generated unwind info and ask for a backtrace, GDB
> complains that the stack is corrupt, but the only problem is that
> the dwarf2 machinery gets confused by the same-CFA, same-function
> pair of stack frames.  This is fixed in the revised patch below.

That fix is wrong!  Either your hand-generated unwind info is wrong
(or incomplete) or GDB needs to do something more clever (like perhaps
using the address of the first instruction in the region covered by
the unwind info).  In any case, the frame ID should only change when
we really enter a different frame.

Perhaps you can explain in more detail what the problem is?

> > And you're not correct that older GCCs could run them
> > far enough to test; they'll fail to build because of the use of
> > __attribute__((cleanup))
> 
> Oops, indeed, sorry about that.  The testcases must definitely be
> amended if they're to remain.  Should they?

I think the tests need to be simplified.

Mark


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-07 15:01         ` Mark Kettenis
@ 2006-03-07 19:55           ` Alexandre Oliva
  2006-03-12 18:15             ` Mark Kettenis
  2006-03-13  2:25             ` Daniel Jacobowitz
  0 siblings, 2 replies; 12+ messages in thread
From: Alexandre Oliva @ 2006-03-07 19:55 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches, roland

On Mar  7, 2006, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:

>> From: Alexandre Oliva <aoliva@redhat.com>
>> Date: Tue, 07 Mar 2006 02:31:27 -0300
>> 
>> On Mar  4, 2006, Daniel Jacobowitz <drow@false.org> wrote:
>> 
>> > On Sat, Mar 04, 2006 at 09:01:43AM -0300, Alexandre Oliva wrote:
>> >> > It's also good to have a few testcases,
>> >> > but I don't completely understand the testcases :(
>> >> 
>> >> You're not alone in that feeling, I assure you :-)
>> 
>> > Like Mark, I am happier with the code than the testcases.  In fact,
>> > I'd rather not have the tests at all than have something quite
>> > so overkill.

>> Fair enough...  Those tests uncovered a problem with the way our
>> dwarf2 code identifies frames, though: it uses the function start
>> address and the CFA to identify a stack frame, whereas it should use
>> the PC and the CFA.

> Nope, using the function address is the correct thing to do.
> Otherwise you'll end up with a different frame ID if you single-step
> to the next instruction for example.

So I see :-(  Sorry for posting the patch before testing was even
started.

>> In some corner cases, such as the one exercised by the i386
>> testcase, if you're on the second instruction of the region covered
>> by the hand-generated unwind info and ask for a backtrace, GDB
>> complains that the stack is corrupt, but the only problem is that
>> the dwarf2 machinery gets confused by the same-CFA, same-function
>> pair of stack frames.  This is fixed in the revised patch below.

> That fix is wrong!  Either your hand-generated unwind info is wrong
> (or incomplete) or GDB needs to do something more clever (like perhaps
> using the address of the first instruction in the region covered by
> the unwind info).

Using the address of the first instruction in the region wouldn't work
either.  The hand-generated unwind info arranges for _L_mutex_lock_31
on i386 to seem like it calls itself, for some reason I don't quite
understand.  Jakub says the backtrace we get after my change is
correct, whereas *without* the patch we get this:

0x080486bc in _L_mutex_lock_31 ()
1: x/i $pc  0x80486bc <_L_mutex_lock_31>:       lea    0x8(%ebp),%ecx
(gdb) where
#0  0x080486bc in _L_mutex_lock_31 ()
#1  0x080486c4 in _L_mutex_lock_31 ()
Previous frame identical to this frame (corrupt stack?)
(gdb) disass foo
Dump of assembler code for function foo:
0x08048540 <foo+0>:     push   %ebp
0x08048541 <foo+1>:     mov    %esp,%ebp
0x08048543 <foo+3>:     sub    $0x108,%esp
0x08048549 <foo+9>:     mov    %ebx,0xfffffff8(%ebp)
0x0804854c <foo+12>:    lea    0xfffffef8(%ebp),%ebx
0x08048552 <foo+18>:    mov    %esi,0xfffffffc(%ebp)
0x08048555 <foo+21>:    mov    0x8(%ebp),%esi
0x08048558 <foo+24>:    test   %esi,%esi
0x0804855a <foo+26>:    jne    0x80486bc <_L_mutex_lock_31>
0x08048560 <foo+32>:    mov    0xfffffff8(%ebp),%ebx
0x08048563 <foo+35>:    mov    0xfffffffc(%ebp),%esi
0x08048566 <foo+38>:    mov    %ebp,%esp
0x08048568 <foo+40>:    pop    %ebp
0x08048569 <foo+41>:    ret
End of assembler dump.
(gdb) disass
Dump of assembler code for function _L_mutex_lock_31:
0x080486bc <_L_mutex_lock_31+0>:        lea    0x8(%ebp),%ecx
0x080486bf <_L_mutex_lock_31+3>:        call   0x8048690 <bar>
0x080486c4 <_L_mutex_lock_31+8>:        jmp    0x8048560 <foo+32>
0x080486c9 <_L_mutex_lock_31+13>:       nop
0x080486ca <_L_mutex_lock_31+14>:       nop
0x080486cb <_L_mutex_lock_31+15>:       nop
End of assembler dump.

> In any case, the frame ID should only change when
> we really enter a different frame.

My understanding is that the intention *is* to represent debug info as
an entry into a new frame, but I don't quite understand why it would
be correct to have two entries for the same function, as in the stack
trace below (generated by the incorrectly-patched GDB).

(gdb) si
0x080486bc in _L_mutex_lock_31 ()
1: x/i $pc  0x80486bc <_L_mutex_lock_31>:       lea    0x8(%ebp),%ecx
(gdb) where
#0  0x080486bc in _L_mutex_lock_31 ()
#1  0x080486c4 in _L_mutex_lock_31 ()
#2  0x08048560 in foo (x=3)
    at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:91
#3  0x08048582 in fn2 ()
    at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:237
#4  0x08048598 in fn1 ()
    at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:244
#5  0x080485fb in main ()
    at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:252


Roland, do you happen to know what the point is of the two stack
frames for _L_mutex_lock_31?  Could we perhaps do away with them, so
as to avoid the problem entirely, given that GDB is apparently doing
the right thing?


As an aside, I don't quite see that GDB's approach to identifying
stack frames by using the stack pointer and the function entry point
is entirely correct for architectures in which recursive functions
don't necessarily change the stack pointer: consider an architecture
with register windows that use a separate stack, like IA64, with the
further assumption that one wouldn't need to save the return address
on the regular stack because the register window machinery would take
care of saving it.

> Perhaps you can explain in more detail what the problem is?

Is the above enough?

>> > And you're not correct that older GCCs could run them
>> > far enough to test; they'll fail to build because of the use of
>> > __attribute__((cleanup))
>> 
>> Oops, indeed, sorry about that.  The testcases must definitely be
>> amended if they're to remain.  Should they?

> I think the tests need to be simplified.

Tricky.  The very point of the tests is to test the complex CFA
expressions.  I could easily remove all of the cleanup and run-time
unwinding stuff (is this what you meant?), but taking out the hairy
bits would render the test pointless.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-07 19:55           ` Alexandre Oliva
@ 2006-03-12 18:15             ` Mark Kettenis
  2006-05-28 22:22               ` Alexandre Oliva
  2006-03-13  2:25             ` Daniel Jacobowitz
  1 sibling, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2006-03-12 18:15 UTC (permalink / raw)
  To: aoliva; +Cc: gdb-patches, roland

> From: Alexandre Oliva <aoliva@redhat.com>
> Date: Tue, 07 Mar 2006 14:46:00 -0300
> 
> On Mar  7, 2006, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> 
> >> From: Alexandre Oliva <aoliva@redhat.com>
> >> Date: Tue, 07 Mar 2006 02:31:27 -0300
> >> 
> >> On Mar  4, 2006, Daniel Jacobowitz <drow@false.org> wrote:
> >> 
> >> > On Sat, Mar 04, 2006 at 09:01:43AM -0300, Alexandre Oliva wrote:
> >> >> > It's also good to have a few testcases,
> >> >> > but I don't completely understand the testcases :(
> >> >> 
> >> >> You're not alone in that feeling, I assure you :-)
> >> 
> >> > Like Mark, I am happier with the code than the testcases.  In fact,
> >> > I'd rather not have the tests at all than have something quite
> >> > so overkill.
> 
> >> Fair enough...  Those tests uncovered a problem with the way our
> >> dwarf2 code identifies frames, though: it uses the function start
> >> address and the CFA to identify a stack frame, whereas it should use
> >> the PC and the CFA.
> 
> > Nope, using the function address is the correct thing to do.
> > Otherwise you'll end up with a different frame ID if you single-step
> > to the next instruction for example.
> 
> So I see :-(  Sorry for posting the patch before testing was even
> started.

No problem.

> >> In some corner cases, such as the one exercised by the i386
> >> testcase, if you're on the second instruction of the region covered
> >> by the hand-generated unwind info and ask for a backtrace, GDB
> >> complains that the stack is corrupt, but the only problem is that
> >> the dwarf2 machinery gets confused by the same-CFA, same-function
> >> pair of stack frames.  This is fixed in the revised patch below.
> 
> > That fix is wrong!  Either your hand-generated unwind info is wrong
> > (or incomplete) or GDB needs to do something more clever (like perhaps
> > using the address of the first instruction in the region covered by
> > the unwind info).
> 
> Using the address of the first instruction in the region wouldn't work
> either.  The hand-generated unwind info arranges for _L_mutex_lock_31
> on i386 to seem like it calls itself, for some reason I don't quite
> understand.  Jakub says the backtrace we get after my change is
> correct, whereas *without* the patch we get this:
> 
> 0x080486bc in _L_mutex_lock_31 ()
> 1: x/i $pc  0x80486bc <_L_mutex_lock_31>:       lea    0x8(%ebp),%ecx
> (gdb) where
> #0  0x080486bc in _L_mutex_lock_31 ()
> #1  0x080486c4 in _L_mutex_lock_31 ()
> Previous frame identical to this frame (corrupt stack?)
> (gdb) disass foo
> Dump of assembler code for function foo:
> 0x08048540 <foo+0>:     push   %ebp
> 0x08048541 <foo+1>:     mov    %esp,%ebp
> 0x08048543 <foo+3>:     sub    $0x108,%esp
> 0x08048549 <foo+9>:     mov    %ebx,0xfffffff8(%ebp)
> 0x0804854c <foo+12>:    lea    0xfffffef8(%ebp),%ebx
> 0x08048552 <foo+18>:    mov    %esi,0xfffffffc(%ebp)
> 0x08048555 <foo+21>:    mov    0x8(%ebp),%esi
> 0x08048558 <foo+24>:    test   %esi,%esi
> 0x0804855a <foo+26>:    jne    0x80486bc <_L_mutex_lock_31>
> 0x08048560 <foo+32>:    mov    0xfffffff8(%ebp),%ebx
> 0x08048563 <foo+35>:    mov    0xfffffffc(%ebp),%esi
> 0x08048566 <foo+38>:    mov    %ebp,%esp
> 0x08048568 <foo+40>:    pop    %ebp
> 0x08048569 <foo+41>:    ret
> End of assembler dump.
> (gdb) disass
> Dump of assembler code for function _L_mutex_lock_31:
> 0x080486bc <_L_mutex_lock_31+0>:        lea    0x8(%ebp),%ecx
> 0x080486bf <_L_mutex_lock_31+3>:        call   0x8048690 <bar>
> 0x080486c4 <_L_mutex_lock_31+8>:        jmp    0x8048560 <foo+32>
> 0x080486c9 <_L_mutex_lock_31+13>:       nop
> 0x080486ca <_L_mutex_lock_31+14>:       nop
> 0x080486cb <_L_mutex_lock_31+15>:       nop
> End of assembler dump.
> 
> > In any case, the frame ID should only change when
> > we really enter a different frame.
> 
> My understanding is that the intention *is* to represent debug info as
> an entry into a new frame, but I don't quite understand why it would
> be correct to have two entries for the same function, as in the stack
> trace below (generated by the incorrectly-patched GDB).

Hmm, that unwind info is a lie then, but I can see that it doesn't
really make a difference for handling exceptions.  You'll only notice
the problems if you actually start interpreting the frames.

Unwinding with the porgram counter annywhere in _L_mutex_lock_31
should just land us directly at foo+32.  

Roland, any reason why that wouldn't work?

> (gdb) si
> 0x080486bc in _L_mutex_lock_31 ()
> 1: x/i $pc  0x80486bc <_L_mutex_lock_31>:       lea    0x8(%ebp),%ecx
> (gdb) where
> #0  0x080486bc in _L_mutex_lock_31 ()
> #1  0x080486c4 in _L_mutex_lock_31 ()
> #2  0x08048560 in foo (x=3)
>     at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:91
> #3  0x08048582 in fn2 ()
>     at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:237
> #4  0x08048598 in fn1 ()
>     at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:244
> #5  0x080485fb in main ()
>     at ../../../gdb/testsuite/gdb.dwarf2/cfa-val-expr-1.c:252
> 
> 
> Roland, do you happen to know what the point is of the two stack
> frames for _L_mutex_lock_31?  Could we perhaps do away with them, so
> as to avoid the problem entirely, given that GDB is apparently doing
> the right thing?
> 
> 
> As an aside, I don't quite see that GDB's approach to identifying
> stack frames by using the stack pointer and the function entry point
> is entirely correct for architectures in which recursive functions
> don't necessarily change the stack pointer: consider an architecture
> with register windows that use a separate stack, like IA64, with the
> further assumption that one wouldn't need to save the return address
> on the regular stack because the register window machinery would take
> care of saving it.

Well, I simplified things a bit; actually a frame ID can have a third
"special" address in addition to the code and stack addresses.
Unsurprisingly on ia64, this third address is used to store the
backing store pointer.

> > Perhaps you can explain in more detail what the problem is?
> 
> Is the above enough?
> 
> >> > And you're not correct that older GCCs could run them
> >> > far enough to test; they'll fail to build because of the use of
> >> > __attribute__((cleanup))
> >> 
> >> Oops, indeed, sorry about that.  The testcases must definitely be
> >> amended if they're to remain.  Should they?
> 
> > I think the tests need to be simplified.
> 
> Tricky.  The very point of the tests is to test the complex CFA
> expressions.  I could easily remove all of the cleanup and run-time
> unwinding stuff (is this what you meant?), but taking out the hairy
> bits would render the test pointless.

Sorry yes, I meant removing the cleanup and run-time unwinding stuff.
You indicated those were not necessary for the GDB tests, they would
just confuse people trying to understand what is happening, and make
the test dependend on particular GCC versions.

However, since the test doesn't seem to be helpful for GDB at all
(except perhaps for testing how GDB reacts to somewhat bogus debug
info), it's probably be a good idea to have a test that actually tests
these new DWARF3 expressions.  Since I don't think it would be
possible to write a test that runs on all ISA's an i386-specific test
in testsuite/gdb.arch would probably be best.

Anyway, feel free to commit the code that adds support for the new
DWARF3 expressions (the origional one, not the "corrected" one ;).

Mark


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-07 19:55           ` Alexandre Oliva
  2006-03-12 18:15             ` Mark Kettenis
@ 2006-03-13  2:25             ` Daniel Jacobowitz
  2006-03-13  6:23               ` Alexandre Oliva
  1 sibling, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-03-13  2:25 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Mark Kettenis, gdb-patches, roland

On Tue, Mar 07, 2006 at 02:46:00PM -0300, Alexandre Oliva wrote:
> Using the address of the first instruction in the region wouldn't work
> either.  The hand-generated unwind info arranges for _L_mutex_lock_31
> on i386 to seem like it calls itself, for some reason I don't quite
> understand.  Jakub says the backtrace we get after my change is
> correct, whereas *without* the patch we get this:

Where does this hand generated unwind info come from?  The NPTL I'm
looking at doesn't have any for that function, either an older build I
had around or a current CVS checkout.  I'm very suspicious of your
description of it.

> > In any case, the frame ID should only change when
> > we really enter a different frame.
> 
> My understanding is that the intention *is* to represent debug info as
> an entry into a new frame, but I don't quite understand why it would
> be correct to have two entries for the same function, as in the stack
> trace below (generated by the incorrectly-patched GDB).

If the intention is to represent an entry into a new frame, then the
debugger should be displaying two frames.

> Tricky.  The very point of the tests is to test the complex CFA
> expressions.  I could easily remove all of the cleanup and run-time
> unwinding stuff (is this what you meant?), but taking out the hairy
> bits would render the test pointless.

Testing hand-written dwarf2/dwarf3 is entirely fine, even if we have to
arch-restrict the tests.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-13  2:25             ` Daniel Jacobowitz
@ 2006-03-13  6:23               ` Alexandre Oliva
  2006-03-24 23:08                 ` Daniel Jacobowitz
  0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2006-03-13  6:23 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches, roland

On Mar 11, 2006, Daniel Jacobowitz <drow@false.org> wrote:

> On Tue, Mar 07, 2006 at 02:46:00PM -0300, Alexandre Oliva wrote:
>> Using the address of the first instruction in the region wouldn't work
>> either.  The hand-generated unwind info arranges for _L_mutex_lock_31
>> on i386 to seem like it calls itself, for some reason I don't quite
>> understand.  Jakub says the backtrace we get after my change is
>> correct, whereas *without* the patch we get this:

> Where does this hand generated unwind info come from?

Jakub's testcase submitted as part of the patch.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-13  6:23               ` Alexandre Oliva
@ 2006-03-24 23:08                 ` Daniel Jacobowitz
  0 siblings, 0 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-03-24 23:08 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Mark Kettenis, gdb-patches, roland

On Sun, Mar 12, 2006 at 11:25:41PM -0300, Alexandre Oliva wrote:
> On Mar 11, 2006, Daniel Jacobowitz <drow@false.org> wrote:
> 
> > On Tue, Mar 07, 2006 at 02:46:00PM -0300, Alexandre Oliva wrote:
> >> Using the address of the first instruction in the region wouldn't work
> >> either.  The hand-generated unwind info arranges for _L_mutex_lock_31
> >> on i386 to seem like it calls itself, for some reason I don't quite
> >> understand.  Jakub says the backtrace we get after my change is
> >> correct, whereas *without* the patch we get this:
> 
> > Where does this hand generated unwind info come from?
> 
> Jakub's testcase submitted as part of the patch.

OK, you and I were using "entry into a new frame" differently.

Here's the function:

 8048584:       8b 75 08                mov    0x8(%ebp),%esi
 8048587:       8d 9d f8 fe ff ff       lea    0xfffffef8(%ebp),%ebx
 804858d:       85 f6                   test   %esi,%esi
 804858f:       75 7c                   jne    804860d <_L_mutex_lock_156>
 8048591:       81 c4 00 01 00 00       add    $0x100,%esp

...

0804860d <_L_mutex_lock_156>:
 804860d:       8d 4d 08                lea    0x8(%ebp),%ecx
 8048610:       e8 4b ff ff ff          call   8048560 <bar>
 8048615:       e9 77 ff ff ff          jmp    8048591 <foo+0x18>

Here's the frame info:

00000014 0000002c 00000018 FDE cie=00000000 pc=0804860d..0804861a
  DW_CFA_val_expression: r8 (DW_OP_breg8: 8)
  DW_CFA_advance_loc: 3 to 08048610
  DW_CFA_val_expression: r8 (DW_OP_breg8: 5)
  DW_CFA_advance_loc: 4 to 08048614
  DW_CFA_val_expression: r8 (DW_OP_breg8: 6; DW_OP_const4s: -382; DW_OP_minus; DW_OP_const4s: -520; DW_OP_plus)
  DW_CFA_nop
  DW_CFA_nop

r8 is the return address column.  That's %eip.  So for the first two
instructions of this "function", we claim that we return to the jump
instruction.  If you're going to put that in the unwind information,
why shouldn't you expect GDB to show the jump as the next address in
the backtrace?

[Why the second one advances loc by 4 bytes instead of 5 I don't know.
It looks like it might be a bug in the version of gas I used; the test
looks OK.]

Then, at the jump, the PC is unwound to PC + 6 - (-382) + (-520) [for
reasons involving the difference of labels in different sections,
AFAICT].  That puts us back where we came from.

I assume these hoops are jumped through to reduce the size of the debug
info, while maintaining its PIC-ness.  Gotta be a better way... but I
don't see any reason why, given this unwind info, GDB should not
display the frame twice.

Which I think means some version of your patch already posted is
correct, minus any arguments about the test cases, but I'm no longer
quite sure which version.


-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Support Dwarf3 DW_CFA_val_* expressions
  2006-03-12 18:15             ` Mark Kettenis
@ 2006-05-28 22:22               ` Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2006-05-28 22:22 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches, roland

[-- Attachment #1: Type: text/plain, Size: 271 bytes --]

On Mar 11, 2006, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:

> Anyway, feel free to commit the code that adds support for the new
> DWARF3 expressions (the origional one, not the "corrected" one ;).

Thanks, and sorry about the delay.  I'm finally checking this in.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdb-cfaval-3.patch --]
[-- Type: text/x-patch, Size: 3531 bytes --]

for gdb/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2-frame.h (enum dwarf2_frame_reg_rule): Add
	DWARF2_FRAME_REG_SAVED_VAL_OFFSET and
	DWARF2_FRAME_REG_SAVED_VAL_EXP.
	* dwarf2-frame.c (execute_cfa_program): Handle val_offset,
	val_offset_sf and val_expression.
	(dwarf2_frame_prev_register): Handle the new reg rules.
	(dwarf2_frame_this_id): Use pc instead of function entry point.

Index: gdb/dwarf2-frame.c
===================================================================
--- gdb/dwarf2-frame.c.orig	2006-05-28 02:44:41.000000000 -0300
+++ gdb/dwarf2-frame.c	2006-05-28 02:44:47.000000000 -0300
@@ -481,6 +481,34 @@ bad CFI data; mismatched DW_CFA_restore_
 	      fs->regs.reg[reg].loc.offset = offset;
 	      break;
 
+	    case DW_CFA_val_offset:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      offset = utmp * fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_offset_sf:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+	      offset *= fs->data_align;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	      break;
+
+	    case DW_CFA_val_expression:
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	      dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	      fs->regs.reg[reg].exp_len = utmp;
+	      fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
+	      insn_ptr += utmp;
+	      break;
+
 	    case DW_CFA_def_cfa_sf:
 	      insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
 	      if (eh_frame_p)
@@ -965,6 +993,28 @@ dwarf2_frame_prev_register (struct frame
 	}
       break;
 
+    case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				cache->cfa + cache->reg[regnum].loc.offset);
+      break;
+
+    case DWARF2_FRAME_REG_SAVED_VAL_EXP:
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+	store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+				execute_stack_op (cache->reg[regnum].loc.exp,
+						  cache->reg[regnum].exp_len,
+						  next_frame, cache->cfa));
+      break;
+
     case DWARF2_FRAME_REG_UNSPECIFIED:
       /* GCC, in its infinite wisdom decided to not provide unwind
 	 information for registers that are "same value".  Since
Index: gdb/dwarf2-frame.h
===================================================================
--- gdb/dwarf2-frame.h.orig	2006-05-28 02:00:31.000000000 -0300
+++ gdb/dwarf2-frame.h	2006-05-28 02:44:47.000000000 -0300
@@ -51,6 +51,10 @@ enum dwarf2_frame_reg_rule
   DWARF2_FRAME_REG_SAVED_EXP,
   DWARF2_FRAME_REG_SAME_VALUE,
 
+  /* These are defined in Dwarf3.  */
+  DWARF2_FRAME_REG_SAVED_VAL_OFFSET,
+  DWARF2_FRAME_REG_SAVED_VAL_EXP,
+
   /* These aren't defined by the DWARF2 CFI specification, but are
      used internally by GDB.  */
   DWARF2_FRAME_REG_RA,		/* Return Address.  */

[-- Attachment #3: Type: text/plain, Size: 249 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2006-05-28  6:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-03-03 17:54 Support Dwarf3 DW_CFA_val_* expressions Alexandre Oliva
2006-03-04 12:01 ` Mark Kettenis
2006-03-04 14:43   ` Alexandre Oliva
2006-03-04 15:07     ` Daniel Jacobowitz
2006-03-07 14:25       ` Alexandre Oliva
2006-03-07 15:01         ` Mark Kettenis
2006-03-07 19:55           ` Alexandre Oliva
2006-03-12 18:15             ` Mark Kettenis
2006-05-28 22:22               ` Alexandre Oliva
2006-03-13  2:25             ` Daniel Jacobowitz
2006-03-13  6:23               ` Alexandre Oliva
2006-03-24 23:08                 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox