This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Support Dwarf3 DW_CFA_val_* expressions
- From: Mark Kettenis <mark dot kettenis at xs4all dot nl>
- To: aoliva at redhat dot com
- Cc: gdb-patches at sources dot redhat dot com
- Date: Sat, 4 Mar 2006 11:17:45 +0100 (CET)
- Subject: Re: Support Dwarf3 DW_CFA_val_* expressions
- References: <or7j7bpmtq.fsf@free.oliva.athome.lsd.ic.unicamp.br>
> 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, ®);
> + 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, ®);
> + 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, ®);
> + 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