public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* PATCH: error reading variable: value has been optimized out
@ 2012-08-24 12:11 Andrew Burgess
  2012-08-26 18:22 ` Jan Kratochvil
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Burgess @ 2012-08-24 12:11 UTC (permalink / raw)
  To: gdb-patches

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

I found some behaviour that has changed, I believe, for the worse.  I have found an example where, in the backtrace, gdb used to say this:

   #0  0x0000000000400504 in function ()
   #1  0x00000000004004fc in broken (operand0=<optimized out>, operand1=<optimized out>) at bad.c:10
   #2  0x00000000004004e5 in main () at main.c:4

But now gdb says this:

   #0  0x0000000000400504 in function ()
   #1  0x00000000004004fc in broken (operand0=<error reading variable: value has been optimized out>, operand1=<error reading variable: value has been optimized out>) at bad.c:10
   #2  0x00000000004004e5 in main () at main.c:4

We now get an error about the value being optimised out.  I believe this should not be marked as an error as the value is quite legitimately no longer available.

At the end of this email is a patch to restore the old behaviour.  What follows here is a description of what causes the new behaviour.

[ Using git clone from git://sourceware.org/git/gdb.git ]

Things first changed with commit 25993ce40950a8b34b31efd49790a16be3d5c519 (http://sourceware.org/ml/gdb-cvs/2011-07/msg00184.html), after this the backtrace looked like this:

#0  0x0000000000400504 in function ()
#1  0x00000000004004fc in broken (operand0=value has been optimized out
) at bad.c:10
#2  0x00000000004004e5 in main () at main.c:4

Clearly things went a little off the rails at this point, I think the old "<optimized out>" is better than the new "value has been optimized out" text, but it doesn't really matter, as things changed again with commit 3d0a5ee6551a1f2036a574f7802c1abc47eada41 (http://sourceware.org/ml/gdb-cvs/2011-09/msg00043.html), the behaviour is now:

#0  0x0000000000400504 in function ()
#1  0x00000000004004fc in broken (operand0=<error reading variable: value has been optimized out>, operand1=<error reading variable: value has been optimized out>) at bad.c:10
#2  0x00000000004004e5 in main () at main.c:4

We get operand1 back again, along with the error message text.

The example given by Jan when proposing the patch (http://sourceware.org/ml/gdb-patches/2011-08/msg00575.html) was this, "<error reading variable: Asked for position 0 of stack, stack only has 0 elements on it.>", in this case the format seems fine, there really was an error while reading the variable, however, in the example I have, there was no _error_, it's just the variable really has gone.  I suggest then that the behaviour we have arrived at is a regression, and we should try to get back to a situation where, for my optimised out variables we see the original behaviour, but in the example Jan gave, we see the new error message style behaviour.

The test attached (bad-bt.tar.bz2) is fairly contrived, and is x86 specific, but hopefully it's good enough to allow people to reproduce the error if they want to.  I'm happy to discus the test if anyone things it's not valid.  To run the test,

  tar -xjvf bad-bt.tar.bz2
  cd bad-bt
  make check GDB=<path-to-gdb>
  # This will run gdb and show the backtrace... 

When gdb tries to figure out where the variable is we eventually end up in dwarf2loc.c:dwarf2_evaluate_loc_desc_full, this tells us that at the address in question the variable is in a register, we then call findvar.c:value_from_register, which calls findvar.c:read_frame_register_value, this then calls get_frame_register_value followed by value_contents_copy.

The problem is that value_contents_copy throws an error if the value returned by get_frame_register_value is optimised out, as it can quite legitimately be if a younger frame has marked the register in question as undefined.

There is currently only one user of read_frame_register_value, which is the path I just described, I suggest then that we change the behaviour of this function to mark the whole result value as optimised out if any of the registers read to acquire the value are optimised out.  I've included the patch do do this below.

Looking through, value.c is seems there might also support for having values partially optimised out, this would seem like a better solution, but I'm not sure the right way to hook this in, if anyone would like to offer suggestions I'm happy to create a new patch, alternatively, this could be improved on later...



Ok to commit? Or is more work required?

Cheers,
Andrew

gdb/ChangeLog

2012-08-24  Andrew Burgess  <aburgess@broadcom.com>

	* findvar.c (read_frame_register_value): Mark the result value as
	optimized out if any of the input registers have been optimized out.

diff --git a/gdb/findvar.c b/gdb/findvar.c
index 66bcebe..ec9dde7 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -677,7 +677,10 @@ default_value_from_register (struct type *type, int regnum,
 /* VALUE must be an lval_register value.  If regnum is the value's
    associated register number, and len the length of the values type,
    read one or more registers in FRAME, starting with register REGNUM,
-   until we've read LEN bytes.  */
+   until we've read LEN bytes.
+
+   If any of the registers we try to read are optimized out, then mark the
+   complete resulting value as optimized out.  */
 
 void
 read_frame_register_value (struct value *value, struct frame_info *frame)
@@ -703,6 +706,12 @@ read_frame_register_value (struct value *value, struct fram
       struct value *regval = get_frame_register_value (frame, regnum);
       int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
 
+      if (value_optimized_out (regval))
+       {
+         set_value_optimized_out (value, 1);
+         break;
+       }
+
       /* If the register length is larger than the number of bytes
          remaining to copy, then only copy the appropriate bytes.  */
       if (reg_len > len)
(




[-- Attachment #2: bad-bt.tar.bz2 --]
[-- Type: application/octet-stream, Size: 2546 bytes --]

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-24 12:11 PATCH: error reading variable: value has been optimized out Andrew Burgess
@ 2012-08-26 18:22 ` Jan Kratochvil
  2012-08-27 15:46   ` Tom Tromey
  2012-08-31 10:33   ` Andrew Burgess
  0 siblings, 2 replies; 21+ messages in thread
From: Jan Kratochvil @ 2012-08-26 18:22 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On Fri, 24 Aug 2012 14:10:35 +0200, Andrew Burgess wrote:
> Looking through, value.c is seems there might also support for having values
> partially optimised out, this would seem like a better solution, but I'm not
> sure the right way to hook this in, if anyone would like to offer
> suggestions I'm happy to create a new patch, alternatively, this could be
> improved on later...

GDB supports partially unavailable values from partially stored traces.
This is AFAIK not applicable for partially optimized out values.

#0  0x0000000000400524 in function ()
#1  0x000000000040051c in broken (operand0=<error reading variable: value has been optimized out>, operand0@entry=1, [...]) at bad.c:10
#2  0x0000000000400415 in main () at main.c:4

The problem is not normally visible because this reproducer comes from old GCC:
        .ident  "GCC: (GNU) 4.2.1"

(gdb) info addr operand0
Symbol "operand0" is multi-location:
  Range 0x400510-0x40051c: a variable in $rdi
(gdb) disass
[...]
   0x0000000000400517 <+7>:     callq  0x400524 <function>
=> 0x000000000040051c <+12>:    nop

That is here it says 'operand0' is valid in all caller instructions till and
including 0x40051b (but not including 0x40051c).  This means that 'operand0'
would be valid in $rdi even when the CPU already executes arbitrary 'function'
instructions which have right to clobber callee-clobbered registers.  This is
incorrect from GCC.

Callee here undefines the value of %rdi for unwind, unaware why, this is
normally assumed as %rdi is callee-clobbered register.
00000038 00000014 ffffffff CIE
  DW_CFA_def_cfa: r7 (rsp) ofs 8
  DW_CFA_offset: r16 (rip) at cfa-8
  DW_CFA_undefined: r4 (rsi)
  DW_CFA_undefined: r5 (rdi)
00000050 0000001c 00000038 FDE cie=00000038 pc=00400524..00400531
                                               ^^^^^^^^

Newer GCCs do not say anything is in callee-clobberred register when inside the
call, being more correct and making it easier for GDB:

GNU C 4.7.1 20120720 (Red Hat 4.7.1-5) -mtune=generic -march=x86-64 -g -O2 -fno-var-tracking-assignments 
#0  f () at 67.c:4
#1  0x0000000000400515 in g (x=<optimized out>) at 67.c:10
at frame #1:
(gdb) info addr x
Symbol "x" is multi-location:
  Range 0x400510-0x400514: a variable in $rdi
Dump of assembler code for function g:
   0x0000000000400510 <+0>:	callq  0x400500 <f>
=> 0x0000000000400515 <+5>:	xor    %eax,%eax

Here you can see 'x' is valid till and including 0x400513 (that is before
'callq' is executed) but when 'callq' is executing (0x400514) then 'x' is
already <optimized out>.  So GDB does not try to unwind such value.


I agree with the fix but it should have GDB-testsuite compatible testcase.
Also FYI it is only for backward compatibility with old GCCs.



Thanks,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-26 18:22 ` Jan Kratochvil
@ 2012-08-27 15:46   ` Tom Tromey
  2012-08-31  9:59     ` Eli Zaretskii
  2012-09-03 15:07     ` Jan Kratochvil
  2012-08-31 10:33   ` Andrew Burgess
  1 sibling, 2 replies; 21+ messages in thread
From: Tom Tromey @ 2012-08-27 15:46 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Andrew Burgess, gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Andrew> Looking through, value.c is seems there might also support for
Andrew> having values partially optimised out, this would seem like a
Andrew> better solution, but I'm not sure the right way to hook this in,
Andrew> if anyone would like to offer suggestions I'm happy to create a
Andrew> new patch, alternatively, this could be improved on later...

Jan> GDB supports partially unavailable values from partially stored traces.
Jan> This is AFAIK not applicable for partially optimized out values.

I'm not sure whether I'm understanding your comment correctly, but gdb
does support partially optimized out values.  However, these are only
supported for lval_computed values.  See lval_funcs::check_validity and
check_any_valid.

Offhand it seems as though read_frame_register_value could create an
lval_computed value if any register it needs is optimized out.  I don't
know whether this is worth the effort.

Tom

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-27 15:46   ` Tom Tromey
@ 2012-08-31  9:59     ` Eli Zaretskii
  2012-09-03 15:07     ` Jan Kratochvil
  1 sibling, 0 replies; 21+ messages in thread
From: Eli Zaretskii @ 2012-08-31  9:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: jan.kratochvil, aburgess, gdb-patches

> From: Tom Tromey <tromey@redhat.com>
> Cc: Andrew Burgess <aburgess@broadcom.com>,        "gdb-patches\@sourceware.org" <gdb-patches@sourceware.org>
> Date: Mon, 27 Aug 2012 09:46:12 -0600
> 
> Offhand it seems as though read_frame_register_value could create an
> lval_computed value if any register it needs is optimized out.  I don't
> know whether this is worth the effort.

IMO, any enhancements that allow better support for optimized-out
variables are important.  Having GDB refuse to show a value of a
variable, letting you go hunt for it via disassembly and register
sniffing, is among the worst user-experiences I have debugging
optimized programs.

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-26 18:22 ` Jan Kratochvil
  2012-08-27 15:46   ` Tom Tromey
@ 2012-08-31 10:33   ` Andrew Burgess
  2012-09-01  8:17     ` Eli Zaretskii
                       ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: Andrew Burgess @ 2012-08-31 10:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

On 26/08/2012 6:18 PM, Jan Kratochvil wrote:
> I agree with the fix but it should have GDB-testsuite compatible testcase.
> Also FYI it is only for backward compatibility with old GCCs.

Included a test case (below) that covers 4 different cases, all of which are currently broken in different ways. These are,

(1) Values held in a single register.

(2) Structure the size of two registers, the dwarf location is a single register, and the structure is assumed to continue into the next sequential register.

(3) Structures the size of two registers split over two registers using dwarf piece information.

(4) Values the size of a single register split over two registers using dwarf piece information to describe the location.

My original patch fixes (1) and (2), though as Tom suggested we could do better in case (2) if we used computed values to describe partially optimized out values, but as gcc is no longer creating examples like this I think we can accept the more limited solution I originally suggessted, if that's ok.

Cases (3) and (4) are not fixed by my original patch, and fail for a different reason.  I could remove these from the test, but I believe the tests are reasonable, or at least not totally crazy, so I'm reluctant to just delete them.  I could just commit the test with these two examples marked as known failing .... or I could fix them :)

The problem is this,

  - In dwarf2loc.c:dwarf_evaluate_loc_desc_full we create the computed value from the pieced location information.

  - In dwarf2loc.c:read_pieced_value we spot that some of the registers are missing and mark the computed value as optimized out.

  - In value.c:value_bits_valid we see the value is both computed, and is marked as optimized out, so we call the check_validity handler on the value.

  - This arrives in dwarf2loc.c:check_pieced_value_bits, the problem is that in here there's no case to handle pieces in registers, and so we just return the default answer that the bits are valid.

Possible fixes,

(a) Could add a case to check_pieced_value_bits to handle the register case, this would need to read the register though, which requires a frame, this would mean either adding a frame parameter back up the call stack, or using VALUE_FRAME_ID, which seems to call a deprecated function, so I'm guessing would be frowned upon.

(b) As the pieces walked in check_pieced_value_bits are private to the value we could, when reading the value in read_pieced_value change the location from DWARF_VALUE_REGISTER to DWARF_VALUE_OPTIMIZED_OUT, this would give us exactly the right result, but I don't really like it, it feels like we'd be throwing away some good information.

(c) We could have some extra state stored within the piece_closure that indicates if each piece is optimized out or not.  This would get set as part of read_pieced_value, and could then be used within check_pieced_value.

(d) Could add a VEC of optimized_out bits/bytes to struct value, similar to the unavailable member, then when we read the pieced value we would setup this VEC correctly and this would be used within value.c:value_bits_valid rather than having to call a special check_validity handler...

(e) I'm open to other ideas...


Thanks,



Andrew

gdb/testsuite/ChangeLog

2012-08-31  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.dwarf2/dw2-op-out-param.S: New file.
	* gdb.dwarf2/dw2-op-out-param.exp: New file.
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
new file mode 100644
index 0000000..d9bb1b3
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
@@ -0,0 +1,602 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Test the behaviour of gdb when the location information describes a
+   function parameter as being in a particular register, but a newer frame
+   on the call stack has clobbered the register (we mark it undefined in
+   the dwarf).
+
+   It can, reasonably, be argued that should dwarf like this be seen in the
+   wild, then this is an issue with the dwarf producer as having the
+   location of an item be in a callee clobbered register does not make much
+   sense.  However, older versions of gcc used to do this, and it is not a
+   bad thing to ensure that gdb does a sane thing when presented with such
+   dwarf.
+
+   This test covers 4 cases.
+   (1) 8-byte basic types in 8-byte registers.
+   (2) 16-byte structures being passed using a single reference register,
+       the structure is assumed to flow into the adjacent register.
+   (3) 16-byte structures split over two registers using dwarf pieces.
+   (4) 8-byte basic types being passed in two 4-byte chunks using two
+       registers and dwarf piece information to describe the placement.  */
+
+        .text
+
+.Ltext0:
+        
+        /* main */
+.globl main
+        .type   main, @function
+main:
+.Ltext1:
+        sub    $0x8,%rsp
+.Ltext2:
+        movq    $0xdeadbeefdeadbeef, %rbx
+        movq    $0xdeadbeefdeadbeef, %rcx
+        movq    $0xdeadbeefdeadbeef, %rdx
+        movq    $0xdeadbeefdeadbeef, %rsi
+        movq    $0xdeadbeefdeadbeef, %rdi
+        
+        callq    test1
+        nop
+
+        callq    test2
+        nop
+
+        callq    test3
+        nop
+
+        callq    test4
+        nop
+        
+        add    $0x8,%rsp
+        retq
+.Ltext3:
+        .size   main, .-main
+
+        /* breakpt */
+.globl breakpt
+        .type   breakpt, @function
+breakpt:
+.Ltext4:
+        sub    $0x8,%rsp
+        add    $0x8, %rsp
+        retq
+.Ltext5:
+        .size   breakpt, .-breakpt
+        
+        /* test1 */
+.globl test1
+        .type   test1, @function
+test1:
+.Ltext5:
+        sub    $0x8,%rsp
+.Ltext6:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext7:
+        .size   test1, .-test1
+
+        /* test2 */
+.globl test2
+        .type   test2, @function
+test2:
+.Ltext8:
+        sub    $0x8,%rsp
+.Ltext9:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext10:
+        .size   test2, .-test2
+
+        /* test3 */
+.globl test3
+        .type   test3, @function
+test3:
+.Ltext11:
+        sub    $0x8,%rsp
+.Ltext12:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext13:
+        .size   test3, .-test3
+
+        /* test4 */
+.globl test4
+        .type   test4, @function
+test4:
+.Ltext14:
+        sub    $0x8,%rsp
+.Ltext15:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext16:
+        .size   test4, .-test4
+        
+
+.Letext0:
+
+        /*******************************************************/
+
+        .section	.debug_frame,"",@progbits
+        
+        /* CIE */
+.Lframe0:
+	.long	.LECIE0-.LSCIE0 /* length */
+.LSCIE0:
+	.long	0xffffffff      /* CIE_id */
+	.byte	0x1             /* version */
+	.string	""              /* augmentation */
+	.uleb128 0x1            /* code alignment */
+	.sleb128 -8             /* data alignment */
+	.byte	0x10            /* R/A column */
+        /* Initial instructions */
+	.byte	0xc             /* DW_CFA_def_cfa */
+	.uleb128 0x7            /* reg# */
+	.uleb128 0x8            /* offset */
+	.byte	0x90            /* DW_CFA_offset (r16) */
+	.uleb128 0x1            /* offset */
+	.align 8
+.LECIE0:
+
+        /* FDE : breakpt */
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0        /* length */
+.LASFDE0:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext4                 /* start */
+	.quad	.Ltext5-.Ltext4         /* length */
+        /* Instructions */
+        .byte   0x7             /* DW_CFA_undefined */
+        .uleb128 0x2            /* reg# */
+        .byte   0x7             /* DW_CFA_undefined */
+        .uleb128 0x4            /* reg# */
+        .byte   0x7             /* DW_CFA_undefined */
+        .uleb128 0x5            /* reg# */        
+	.align 8
+.LEFDE0:
+
+        /* FDE : test1 */
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2        /* length */
+.LASFDE2:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext5                 /* start */
+	.quad	.Ltext7-.Ltext5         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext6-.Ltext5
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE2:
+
+        /* FDE : test2 */
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3        /* length */
+.LASFDE3:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext8                 /* start */
+	.quad	.Ltext10-.Ltext8        /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext9-.Ltext8
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE3:
+
+        /* FDE : test3 */
+.LSFDE4:
+	.long	.LEFDE4-.LASFDE4        /* length */
+.LASFDE4:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext11                /* start */
+	.quad	.Ltext13-.Ltext11       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext12-.Ltext11
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE4:
+
+        /* FDE : test4 */
+.LSFDE5:
+	.long	.LEFDE5-.LASFDE5        /* length */
+.LASFDE5:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext14                /* start */
+	.quad	.Ltext16-.Ltext14       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext15-.Ltext14
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE5:
+
+        /* FDE : main */
+.LSFDE9:
+	.long	.LEFDE9-.LASFDE9        /* length */
+.LASFDE9:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext1                 /* start */
+	.quad	.Ltext3-.Ltext1         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext2-.Ltext1
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE9:
+
+        /*******************************************************/        
+        
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+        .long  .Ldebug_info_end - .Ldebug_info_start   /* Length */
+.Ldebug_info_start:
+	.value	0x2                     /* DWARF version number. */
+	.long	.Ldebug_abbrev0         /* Offset into .debug_abbrev */
+	.byte	0x8                     /* Pointer size */
+
+.LDI0:        
+	.uleb128 0x1                    /* DW_TAG_compile_unit */
+	.string	"GNU C 4.2.1"           /* DW_AT_producer */
+	.byte	0x1                     /* DW_AT_language */
+	.quad	.Ltext0                 /* DW_AT_low_pc */
+	.quad	.Letext0                /* DW_AT_high_pc */
+
+.LDI1:
+	.uleb128 0x2                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"breakpt"               /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext4                 /* DW_AT_low_pc */
+	.quad	.Ltext5                 /* DW_AT_high_pc */        
+
+.LDI2:
+	.uleb128 0x5                    /* DW_TAG_base_type */
+	.byte	0x8                     /* DW_AT_byte_size */
+	.byte	0x5                     /* DW_AT_encoding (DW_ATE_signed) */
+	.string	"long int"              /* DW_AT_name */
+
+.LDI3:
+        .uleb128 0x7                    /* DW_TAG_structure_type */
+        .string "big"                   /* DW_AT_name */
+        .byte   0x10                    /* DW_AT_byte_size */
+        .long   .LDI6                   /* DW_AT_sibling */
+        
+.LDI4:
+        .uleb128 0x8                    /* DW_TAG_member */
+        .string "a"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x0                    /*   + 0 */
+        
+.LDI5:
+        .uleb128 0x8                    /* DW_TAG_structure_type */
+        .string "b"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x8                    /*   + 8 */
+        .byte   0x0
+
+.LDI6:
+	.uleb128 0x6                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"main"                  /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.quad	.Ltext1                 /* DW_AT_low_pc */
+	.quad	.Ltext3                 /* DW_AT_high_pc */
+
+.LDI7:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"test1"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext5                 /* DW_AT_low_pc */
+	.quad	.Ltext7                 /* DW_AT_high_pc */
+	.long	.LDI11                  /* DW_AT_sibling */        
+        
+.LDI8:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+
+.LDI9:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */        
+        
+.LDI10:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0        
+
+.LDI11:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"test2"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext8                 /* DW_AT_low_pc */
+	.quad	.Ltext10                /* DW_AT_high_pc */
+	.long	.LDI15                   /* DW_AT_sibling */        
+        
+.LDI12:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+
+.LDI13:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */        
+        
+.LDI14:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0
+
+.LDI15:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"test3"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext11                /* DW_AT_low_pc */
+	.quad	.Ltext13                /* DW_AT_high_pc */
+	.long	.LDI19                  /* DW_AT_sibling */        
+        
+.LDI16:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+
+.LDI17:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+.LDI18:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+	.byte	0x0
+
+.LDI19:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"test4"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext14                /* DW_AT_low_pc */
+	.quad	.Ltext16                /* DW_AT_high_pc */
+	.long	.LDIE0                  /* DW_AT_sibling */        
+        
+.LDI20:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+
+.LDI21:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+.LDI22:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+	.byte	0x0
+        
+.LDIE0:
+	.byte	0x0
+.Ldebug_info_end:
+
+        /*******************************************************/        
+        
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1    /* abbrev code */
+	.uleb128 0x11   /* TAG: DW_TAG_compile_unit */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x25   /* DW_AT_producer */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x13   /* DW_AT_language */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+        .uleb128 0x11   /* DW_AT_low_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+        .uleb128 0x12   /* DW_AT_high_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x2    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x3    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x1    /* DW_AT_sibling */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x4    /* abbrev code */
+	.uleb128 0x5    /* TAG: DW_TAG_formal_parameter */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x2    /* DW_AT_location */
+	.uleb128 0xa    /*   DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x5    /* abbrev code */
+	.uleb128 0x24   /* TAG: DW_TAG_base_type */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0xb    /* DW_AT_byte_size */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3e   /* DW_AT_encoding */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x6    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+
+        .uleb128 0x7    /* abbrev code */
+        .uleb128 0x13   /* DW_TAG_structure_type */
+        .byte   0x1     /* DW_CHILDREN_yes */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0xb    /* DW_AT_byte_size */
+        .uleb128 0xb    /*    DW_FORM_data1 */
+        .uleb128 0x1    /* DW_AT_sibling */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .byte   0x0
+        .byte   0x0
+        
+        .uleb128 0x8    /* abbrev code */
+        .uleb128 0xd    /* DW_TAG_member */
+        .byte   0x0     /* DW_children_no */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0x49   /* DW_AT_type */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .uleb128 0x38   /* DW_AT_data_member_location */
+        .uleb128 0xa    /*   DW_FORM_block1 */
+        .byte   0x0
+        .byte   0x0
+        
+	.byte	0x0
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
new file mode 100644
index 0000000..c367935
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -0,0 +1,62 @@
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+set test "dw2-op-out-param"
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if ![dwarf2_support] {
+    return 0  
+}
+
+# This test can only be run on x86-64 targets.
+if {![istarget x86_64-*] || ![is_lp64_target]} {
+    return 0
+}
+
+if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "break breakpt" "Breakpoint.*at.*"
+
+# Change the radix, making it easier to spot 0xdeadbeef in output.
+gdb_test "set output-radix 16" \
+    "Output radix now set to decimal 16, hex 10, octal 20."
+
+# So we get to see the structure arguments.
+gdb_test "set print frame-arguments all" ""
+
+gdb_continue_to_breakpoint "Stop in breakpt for test1"
+
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?test1 \\(operand0=<optimized out>, operand1=0xdeadbeefdeadbeef, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test1"
+
+gdb_continue_to_breakpoint "Stop in breakpt for test2"
+
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?test2 \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test2"
+
+gdb_continue_to_breakpoint "Stop in breakpt for test3"
+
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?test3 \\(operand0={a = 0xdeadbeefdeadbeef, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbeefdeadbeef}, operand2={a = <optimized out>, b = <optimized out>}\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test3"
+
+gdb_continue_to_breakpoint "Stop in breakpt for test4"
+
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?test4 \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test4"
+


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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-31 10:33   ` Andrew Burgess
@ 2012-09-01  8:17     ` Eli Zaretskii
  2012-09-03  8:32       ` Andrew Burgess
  2012-09-03 11:24       ` Jan Kratochvil
  2012-09-03 15:17     ` Jan Kratochvil
  2012-09-12 17:30     ` Tom Tromey
  2 siblings, 2 replies; 21+ messages in thread
From: Eli Zaretskii @ 2012-09-01  8:17 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, jan.kratochvil

> Date: Fri, 31 Aug 2012 11:32:32 +0100
> From: "Andrew Burgess" <aburgess@broadcom.com>
> cc: "Jan Kratochvil" <jan.kratochvil@redhat.com>
> 
> On 26/08/2012 6:18 PM, Jan Kratochvil wrote:
> > I agree with the fix but it should have GDB-testsuite compatible testcase.
> > Also FYI it is only for backward compatibility with old GCCs.
> 
> Included a test case (below) that covers 4 different cases, all of
> which are currently broken in different ways.

Thank you for doing this.

> [...] but as gcc is no longer creating examples like this I think we can accept the more limited solution I originally suggessted, if that's ok.

"No longer creating" since what version of GCC?

I don't think we should drop use cases just because they are only
possible on past (old) versions of GCC.  GDB is not limited to debug
programs created only by latest GCC versions.  I happen to still use a
very old version of GCC (because it is stable and fast, and because I
rarely need C++), and would very much like to have better debugging
abilities for optimized code than what I have now.

TIA

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-01  8:17     ` Eli Zaretskii
@ 2012-09-03  8:32       ` Andrew Burgess
  2012-09-03 11:24       ` Jan Kratochvil
  1 sibling, 0 replies; 21+ messages in thread
From: Andrew Burgess @ 2012-09-03  8:32 UTC (permalink / raw)
  To: gdb-patches; +Cc: Eli Zaretskii, jan.kratochvil

On 01/09/2012 9:16 AM, Eli Zaretskii wrote:
>> Date: Fri, 31 Aug 2012 11:32:32 +0100
>> From: "Andrew Burgess" <aburgess@broadcom.com>
>> cc: "Jan Kratochvil" <jan.kratochvil@redhat.com>
>>
>> On 26/08/2012 6:18 PM, Jan Kratochvil wrote:
>>> I agree with the fix but it should have GDB-testsuite compatible testcase.
>>> Also FYI it is only for backward compatibility with old GCCs.
>>
>> Included a test case (below) that covers 4 different cases, all of
>> which are currently broken in different ways.
> 
> Thank you for doing this.
> 
>> [...] but as gcc is no longer creating examples like this I think we can accept the more limited solution I originally suggessted, if that's ok.
> 
> "No longer creating" since what version of GCC?

I have to confess this statement is based on something Jan said in his first reply:

On 26/08/2012 6:18 PM, Jan Kratochvil wrote:
> Newer GCCs do not say anything is in callee-clobberred register when inside the
> call, being more correct and making it easier for GDB:

I haven't confirmed this, but don't doubt it :)

Cheers,
Andrew

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-01  8:17     ` Eli Zaretskii
  2012-09-03  8:32       ` Andrew Burgess
@ 2012-09-03 11:24       ` Jan Kratochvil
  2012-09-03 15:38         ` Eli Zaretskii
  1 sibling, 1 reply; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-03 11:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Andrew Burgess, gdb-patches

On Sat, 01 Sep 2012 10:16:41 +0200, Eli Zaretskii wrote:
> > [...] but as gcc is no longer creating examples like this I think we can
> > accept the more limited solution I originally suggessted, if that's ok.
> 
> "No longer creating" since what version of GCC?

I did not check this specific case but these kinds of registers validity in
general are fixed since FSF GCC 4.5 with the introduction of VTA
(-fvar-tracking-assignments).


Regards,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-27 15:46   ` Tom Tromey
  2012-08-31  9:59     ` Eli Zaretskii
@ 2012-09-03 15:07     ` Jan Kratochvil
  1 sibling, 0 replies; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-03 15:07 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Andrew Burgess, gdb-patches

On Mon, 27 Aug 2012 17:46:12 +0200, Tom Tromey wrote:
> I'm not sure whether I'm understanding your comment correctly, but gdb
> does support partially optimized out values.  However, these are only
> supported for lval_computed values.  See lval_funcs::check_validity and
> check_any_valid.

value_bits_valid leads to val_print_optimized_out - <optimized out>
vs.
value_bytes_available leads to val_print_unavailable - <unavailable>


> Offhand it seems as though read_frame_register_value could create an
> lval_computed value if any register it needs is optimized out.  I don't
> know whether this is worth the effort.

dwarf2_evaluate_loc_desc_full 'ctx->num_pieces > 0' block looka as a nice
guide to it.


Thanks,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-31 10:33   ` Andrew Burgess
  2012-09-01  8:17     ` Eli Zaretskii
@ 2012-09-03 15:17     ` Jan Kratochvil
  2012-09-04 16:58       ` Andrew Burgess
  2012-09-12 17:30     ` Tom Tromey
  2 siblings, 1 reply; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-03 15:17 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On Fri, 31 Aug 2012 12:32:32 +0200, Andrew Burgess wrote:
> Included a test case (below) that covers 4 different cases, all of which are
> currently broken in different ways. These are,

I would prefer to give arbitrary names suggesting what each test does, instead
of 1, 2, 3 and 4.  The same applies to the name of tests in resulting gdb.sum.

Also I had to create same map of the test for myself, it could be given there:

ABI registers order: rdi rsi rdx rcx r8 r9
==amd64_dummy_call_integer_regs

pre-set:   rdi rsi rdx rcx    rbx
undefined: rdi rsi     rcx
used:      rdi rsi rdx rcx r8 rbx

       operand0    operand1    operand2
test1: rcx         rbx         rsi
test2: rdx (+rcx)  rcx (+r8)   rsi (+rdx)
test3: rdx  +rcx   rcx  +rbx   rsi  +rdi
test4: rdx/4+rcx/4 rcx/4+rbx/4 rsi/4+rdi/4

This shows it tries to print also r8 but r8 is not initialized.

Also I would prefer to initialize each 32-bit part of each register by
a unique value, $0xdeadbeefdeadbeef everywhere may needlessly hide possible
ordering errors.  That means some 0xdeadbe00deadbe01, 0xdeadbe02deadbe03 or
anything like that.


> My original patch fixes (1) and (2),

In such case (3) and (4) should be KFAILed with PR number(s) filed and stated
there.


> though as Tom suggested we could do better in case (2) if we used computed
> values to describe partially optimized out values, but as gcc is no longer
> creating examples like this I think we can accept the more limited solution
> I originally suggessted, if that's ok.

Although formally there should be also filed PR and to KFAIL the case 2.

(Unfixed GDB would FAIL and not KFAIL.)



gdb_test "set print frame-arguments all" ""
->
gdb_test_no_output "set print frame-arguments all"

gdb_test "break breakpt" "Breakpoint.*at.*"
->
gdb_breakpoint "breakpt"


Thanks,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-03 11:24       ` Jan Kratochvil
@ 2012-09-03 15:38         ` Eli Zaretskii
  0 siblings, 0 replies; 21+ messages in thread
From: Eli Zaretskii @ 2012-09-03 15:38 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: aburgess, gdb-patches

> Date: Mon, 3 Sep 2012 13:24:25 +0200
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Cc: Andrew Burgess <aburgess@broadcom.com>, gdb-patches@sourceware.org
> 
> On Sat, 01 Sep 2012 10:16:41 +0200, Eli Zaretskii wrote:
> > > [...] but as gcc is no longer creating examples like this I think we can
> > > accept the more limited solution I originally suggessted, if that's ok.
> > 
> > "No longer creating" since what version of GCC?
> 
> I did not check this specific case but these kinds of registers validity in
> general are fixed since FSF GCC 4.5 with the introduction of VTA
> (-fvar-tracking-assignments).

OK, thanks.  I hope it will be possible to support older versions as
well.  E.g., fencepost.gnu.org has this installed:

  eliz@fencepost:~$ gcc --version
  gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
  Copyright (C) 2009 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-03 15:17     ` Jan Kratochvil
@ 2012-09-04 16:58       ` Andrew Burgess
  2012-09-05 18:54         ` Jan Kratochvil
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Burgess @ 2012-09-04 16:58 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

On 03/09/2012 4:16 PM, Jan Kratochvil wrote:
> On Fri, 31 Aug 2012 12:32:32 +0200, Andrew Burgess wrote:
>> Included a test case (below) that covers 4 different cases, all of which are
>> currently broken in different ways. These are,
> 
> I would prefer to give arbitrary names suggesting what each test does, instead
> of 1, 2, 3 and 4.  The same applies to the name of tests in resulting gdb.sum.

Done.

> Also I had to create same map of the test for myself, it could be given there:
> 
> ABI registers order: rdi rsi rdx rcx r8 r9
> ==amd64_dummy_call_integer_regs

You're correct that what I originally wrote was not correct, but I think the register ordering used for what was test2, which is the extend-into-next-register behaviour, is actually just using the gdb register number, so this would be from the enum amd64_regnum.

This seems like pretty strange behaviour for x86-64, but the whole concept of passing structures by naturally flowing between registers is not, as I understand it, official dwarf behaviour, but is something that is used by some targets only (http://sourceware.org/ml/gdb-patches/2011-10/msg00052.html) I guess the register usage/ordering makes more sense for those targets.

I've adjusted the registers I use so that they are all within the set that I pre-initialise, and I get the checks I was aiming for.

> Also I would prefer to initialize each 32-bit part of each register by
> a unique value, $0xdeadbeefdeadbeef everywhere may needlessly hide possible
> ordering errors.  That means some 0xdeadbe00deadbe01, 0xdeadbe02deadbe03 or
> anything like that.

Done.
> 
> gdb_test "set print frame-arguments all" ""
> ->
> gdb_test_no_output "set print frame-arguments all"
> 
> gdb_test "break breakpt" "Breakpoint.*at.*"
> ->
> gdb_breakpoint "breakpt"
> 

Done.

I've added KFAILs to the tests, but as you'll spot I've not raised any real defects yet, once the patch is ready to commit I'll raise some defects then commit a version with the real defect IDs in place.

I've only included the testsuite patch here, the fix I propose to commit is still unchanged so I'll not repeat it here.

Any more feedback, or is this ok to commit ?

Andrew





gdb/testsuite/ChangeLog

2012-09-04  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.dwarf2/dw2-op-out-param.S: New file.
	* gdb.dwarf2/dw2-op-out-param.exp: New file.

diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
new file mode 100644
index 0000000..0e41437
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
@@ -0,0 +1,672 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */        
+
+
+/* Test the behaviour of gdb in the following situation, the dwarf debug
+   information describes a parameter as being in a register but a more
+   recent (inner) frame marks the register as being undefined.
+
+   This can arrise if the dwarf producer has the location of a parameter in
+   a callee clobbered register at the time of a call.  Older versions of
+   gcc used to do this, newer versions seem to avoid this issue.
+
+   Though it could be argued that such dwarf is incorrect, we would still
+   like gdb to behave in a user friendly, and helpful way when presented
+   with such dwarf.  */
+
+/* There are 4 test cases in this assembler file.  In each case funcion
+   main calls each test function in turn, each test case then calls the
+   breakpt function.
+
+   We don't actually pass any parameters around, we don't need to, instead
+   the dwarf for each test function declares that the function has some
+   parameters, and tells us which registers these parameters are in.  The
+   breakpt function marks some of these registers as undefined.  The main
+   function helpfully places some marker values into all the registers that
+   are used as parameters so we can see if they ever get printed.
+
+   We use gdb to break in the breakpt function for each of the 4 test
+   cases, and then backtrace through the test function back to main.  In
+   each case some or all of the parameters to the test function should be
+   marked as optimized out, due to the breakpt function effectively
+   clobbering them.
+
+   The dwarf register numbering is different to the gdb register number.
+   In some of the tests we rely on gdb behaviour of being able to specify a
+   struct using a single register location, the structure will then "flow"
+   into the next gdb register.  The initial register is specified using a
+   dwarf register number, but the "next" register will depend on gdb
+   register ordering.
+
+   The breakpt function always marks rcx, rsi, and rdi as undefined.
+
+      register | dwarf | gdb   |         |
+      name     | reg # | reg # | breakpt |
+     ----------|-------|-------|---------|
+        rdx    | 1     | 3     |         |
+        rcx    | 2     | 2     | undef   |
+        rbx    | 3     | 1     |         |
+        rsi    | 4     | 4     | undef   |
+        rdi    | 5     | 5     | undef   |
+
+   We declare the test parameters to be in the register rdx, rcx, rbx, rsi,
+   and rdi.  Of these, rdx and rbx are not traditionally used for parameter
+   passing, but that really doesn't matter for this test.
+   
+   int_param_single_reg_loc: Passes 8-byte integer parameters in 8-byte
+                             registers using DW_OP_regn style location
+                             information.  The parameters are placed as
+                             follows, operand0 (rcx), operand1 (rbx),
+                             operand2 (rsi).  We expect operand0 and
+                             operand2 to be marked as optimised out, but
+                             operand1 to be valid.
+
+   struct_param_single_reg_loc: Passes 16-byte structures in two 8-byte
+                                registers using dwarf DW_OP_regn location
+                                information to describe a single register,
+                                gdb will assume that the structure flows
+                                into the next sequential register.  The
+                                parameters are placed as follows, operand0
+                                (rbx/rcx), operand1 (rcx/rdx), and operand2
+                                (rsi/rdi).  The reuse of rcx between
+                                operand0 and operand1 is intentional.
+
+   struct_param_two_reg_pieces: Passes 16-byte structure in two 8-byte
+                                registers using dwarf DW_OP_piece based
+                                location information to describe both
+                                registers.  The parameters are placed as
+                                follows, operand0 (rdx/rcx), operand1
+                                (rcx/rbx), and operand2 (rsi/rdi).  The
+                                reuse of rcx between operand0 and operand1
+                                is intentional.
+
+   int_param_two_reg_pieces: Passes 8-byte integer values in two 8-byte
+                             registers with 4-bytes being placed in each
+                             register, using dwarf DW_OP_piece based
+                             location information to describe how the
+                             parameters are split up.The parameters are
+                             placed as follows, operand0 (rdx/rcx),
+                             operand1 (rcx/rbx), and operand2 (rsi/rdi).
+                             The reuse of rcx between operand0 and operand1
+                             is intentional.
+*/
+
+        .text
+
+.Ltext0:
+        
+        /* main */
+.globl main
+        .type   main, @function
+main:
+.Ltext1:
+        sub    $0x8,%rsp
+.Ltext2:
+        movq    $0xdeadbe00deadbe01, %rbx
+        movq    $0xdeadbe02deadbe03, %rcx
+        movq    $0xdeadbe04deadbe05, %rdx
+        movq    $0xdeadbe06deadbe07, %rsi
+        movq    $0xdeadbe08deadbe09, %rdi
+        
+        callq    int_param_single_reg_loc
+        nop
+
+        callq    struct_param_single_reg_loc
+        nop
+
+        callq    struct_param_two_reg_pieces
+        nop
+
+        callq    int_param_two_reg_pieces
+        nop
+        
+        add    $0x8,%rsp
+        retq
+.Ltext3:
+        .size   main, .-main
+
+        /* breakpt */
+.globl breakpt
+        .type   breakpt, @function
+breakpt:
+.Ltext4:
+        sub    $0x8,%rsp
+        add    $0x8, %rsp
+        retq
+.Ltext5:
+        .size   breakpt, .-breakpt
+        
+        /* int_param_single_reg_loc */
+.globl int_param_single_reg_loc
+        .type   int_param_single_reg_loc, @function
+int_param_single_reg_loc:
+.Ltext5:
+        sub    $0x8,%rsp
+.Ltext6:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext7:
+        .size   int_param_single_reg_loc, .-int_param_single_reg_loc
+
+        /* struct_param_single_reg_loc */
+.globl struct_param_single_reg_loc
+        .type   struct_param_single_reg_loc, @function
+struct_param_single_reg_loc:
+.Ltext8:
+        sub    $0x8,%rsp
+.Ltext9:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext10:
+        .size   struct_param_single_reg_loc, .-struct_param_single_reg_loc
+
+        /* struct_param_two_reg_pieces */
+.globl struct_param_two_reg_pieces
+        .type   struct_param_two_reg_pieces, @function
+struct_param_two_reg_pieces:
+.Ltext11:
+        sub    $0x8,%rsp
+.Ltext12:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext13:
+        .size   struct_param_two_reg_pieces, .-struct_param_two_reg_pieces
+
+        /* int_param_two_reg_pieces */
+.globl int_param_two_reg_pieces
+        .type   int_param_two_reg_pieces, @function
+int_param_two_reg_pieces:
+.Ltext14:
+        sub    $0x8,%rsp
+.Ltext15:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext16:
+        .size   int_param_two_reg_pieces, .-int_param_two_reg_pieces
+        
+
+.Letext0:
+
+        /*******************************************************/
+
+        .section	.debug_frame,"",@progbits
+        
+        /* CIE */
+.Lframe0:
+	.long	.LECIE0-.LSCIE0 /* length */
+.LSCIE0:
+	.long	0xffffffff      /* CIE_id */
+	.byte	0x1             /* version */
+	.string	""              /* augmentation */
+	.uleb128 0x1            /* code alignment */
+	.sleb128 -8             /* data alignment */
+	.byte	0x10            /* R/A column */
+        /* Initial instructions */
+	.byte	0xc             /* DW_CFA_def_cfa */
+	.uleb128 0x7            /* reg# */
+	.uleb128 0x8            /* offset */
+	.byte	0x90            /* DW_CFA_offset (r16) */
+	.uleb128 0x1            /* offset */
+	.align 8
+.LECIE0:
+
+        /* FDE : breakpt */
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0        /* length */
+.LASFDE0:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext4                 /* start */
+	.quad	.Ltext5-.Ltext4         /* length */
+        /* Instructions */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x2                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x4                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x5                    /* reg# */
+	.align 8
+.LEFDE0:
+
+        /* FDE : int_param_single_reg_loc */
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2        /* length */
+.LASFDE2:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext5                 /* start */
+	.quad	.Ltext7-.Ltext5         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext6-.Ltext5
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE2:
+
+        /* FDE : struct_param_single_reg_loc */
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3        /* length */
+.LASFDE3:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext8                 /* start */
+	.quad	.Ltext10-.Ltext8        /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext9-.Ltext8
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE3:
+
+        /* FDE : struct_param_two_reg_pieces */
+.LSFDE4:
+	.long	.LEFDE4-.LASFDE4        /* length */
+.LASFDE4:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext11                /* start */
+	.quad	.Ltext13-.Ltext11       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext12-.Ltext11
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE4:
+
+        /* FDE : int_param_two_reg_pieces */
+.LSFDE5:
+	.long	.LEFDE5-.LASFDE5        /* length */
+.LASFDE5:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext14                /* start */
+	.quad	.Ltext16-.Ltext14       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext15-.Ltext14
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE5:
+
+        /* FDE : main */
+.LSFDE9:
+	.long	.LEFDE9-.LASFDE9        /* length */
+.LASFDE9:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext1                 /* start */
+	.quad	.Ltext3-.Ltext1         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext2-.Ltext1
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE9:
+
+        /*******************************************************/        
+        
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+        .long  .Ldebug_info_end - .Ldebug_info_start   /* Length */
+.Ldebug_info_start:
+	.value	0x2                     /* DWARF version number. */
+	.long	.Ldebug_abbrev0         /* Offset into .debug_abbrev */
+	.byte	0x8                     /* Pointer size */
+
+.LDI0:        
+	.uleb128 0x1                    /* DW_TAG_compile_unit */
+	.string	"GNU C 4.2.1"           /* DW_AT_producer */
+	.byte	0x1                     /* DW_AT_language */
+	.quad	.Ltext0                 /* DW_AT_low_pc */
+	.quad	.Letext0                /* DW_AT_high_pc */
+
+.LDI1:
+	.uleb128 0x2                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"breakpt"               /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext4                 /* DW_AT_low_pc */
+	.quad	.Ltext5                 /* DW_AT_high_pc */        
+
+.LDI2:
+	.uleb128 0x5                    /* DW_TAG_base_type */
+	.byte	0x8                     /* DW_AT_byte_size */
+	.byte	0x5                     /* DW_AT_encoding (DW_ATE_signed) */
+	.string	"long int"              /* DW_AT_name */
+
+.LDI3:
+        .uleb128 0x7                    /* DW_TAG_structure_type */
+        .string "big"                   /* DW_AT_name */
+        .byte   0x10                    /* DW_AT_byte_size */
+        .long   .LDI6                   /* DW_AT_sibling */
+        
+.LDI4:
+        .uleb128 0x8                    /* DW_TAG_member */
+        .string "a"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x0                    /*   + 0 */
+        
+.LDI5:
+        .uleb128 0x8                    /* DW_TAG_structure_type */
+        .string "b"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x8                    /*   + 8 */
+        .byte   0x0
+
+.LDI6:
+	.uleb128 0x6                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"main"                  /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.quad	.Ltext1                 /* DW_AT_low_pc */
+	.quad	.Ltext3                 /* DW_AT_high_pc */
+
+.LDI7:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext5                 /* DW_AT_low_pc */
+	.quad	.Ltext7                 /* DW_AT_high_pc */
+	.long	.LDI11                  /* DW_AT_sibling */        
+        
+.LDI8:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+
+.LDI9:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */        
+        
+.LDI10:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0        
+
+.LDI11:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext8                 /* DW_AT_low_pc */
+	.quad	.Ltext10                /* DW_AT_high_pc */
+	.long	.LDI15                   /* DW_AT_sibling */        
+        
+.LDI12:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */
+
+.LDI13:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */        
+        
+.LDI14:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0
+
+.LDI15:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext11                /* DW_AT_low_pc */
+	.quad	.Ltext13                /* DW_AT_high_pc */
+	.long	.LDI19                  /* DW_AT_sibling */        
+        
+.LDI16:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+
+.LDI17:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+.LDI18:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+	.byte	0x0
+
+.LDI19:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext14                /* DW_AT_low_pc */
+	.quad	.Ltext16                /* DW_AT_high_pc */
+	.long	.LDIE0                  /* DW_AT_sibling */        
+        
+.LDI20:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+
+.LDI21:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+.LDI22:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+	.byte	0x0
+        
+.LDIE0:
+	.byte	0x0
+.Ldebug_info_end:
+
+        /*******************************************************/        
+        
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1    /* abbrev code */
+	.uleb128 0x11   /* TAG: DW_TAG_compile_unit */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x25   /* DW_AT_producer */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x13   /* DW_AT_language */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+        .uleb128 0x11   /* DW_AT_low_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+        .uleb128 0x12   /* DW_AT_high_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x2    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x3    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x1    /* DW_AT_sibling */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x4    /* abbrev code */
+	.uleb128 0x5    /* TAG: DW_TAG_formal_parameter */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x2    /* DW_AT_location */
+	.uleb128 0xa    /*   DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x5    /* abbrev code */
+	.uleb128 0x24   /* TAG: DW_TAG_base_type */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0xb    /* DW_AT_byte_size */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3e   /* DW_AT_encoding */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x6    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+
+        .uleb128 0x7    /* abbrev code */
+        .uleb128 0x13   /* DW_TAG_structure_type */
+        .byte   0x1     /* DW_CHILDREN_yes */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0xb    /* DW_AT_byte_size */
+        .uleb128 0xb    /*    DW_FORM_data1 */
+        .uleb128 0x1    /* DW_AT_sibling */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .byte   0x0
+        .byte   0x0
+        
+        .uleb128 0x8    /* abbrev code */
+        .uleb128 0xd    /* DW_TAG_member */
+        .byte   0x0     /* DW_children_no */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0x49   /* DW_AT_type */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .uleb128 0x38   /* DW_AT_data_member_location */
+        .uleb128 0xa    /*   DW_FORM_block1 */
+        .byte   0x0
+        .byte   0x0
+        
+	.byte	0x0
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
new file mode 100644
index 0000000..1c7cfad
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -0,0 +1,86 @@
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+set test "dw2-op-out-param"
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if ![dwarf2_support] {
+    return 0  
+}
+
+# This test can only be run on x86-64 targets.
+if {![istarget x86_64-*] || ![is_lp64_target]} {
+    return 0
+}
+
+if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "breakpt"
+
+# Change the radix, making it easier to spot 0xdeadbeef in output.
+gdb_test "set output-radix 16" \
+    "Output radix now set to decimal 16, hex 10, octal 20."
+
+# So we get to see the structure arguments.
+gdb_test_no_output "set print frame-arguments all"
+
+# (1) int_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for test int_param_single_reg_loc"
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_single_reg_loc \\(operand0=<optimized out>, operand1=0xdeadbe00deadbe01, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test int_param_single_reg_loc"
+
+# (2) struct_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_single_reg_loc"
+set test "Backtrace for test struct_param_single_reg_loc"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe04deadbe05}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail gdb/12345 $test
+    }
+}
+
+# (3) struct_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_two_reg_pieces"
+set test "Backtrace for test struct_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail gdb/12345 $test
+    }
+}
+
+# (4) int_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for int_param_two_reg_pieces"
+set test "Backtrace for test int_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail gdb/12345 $test
+    }
+}
+





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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-04 16:58       ` Andrew Burgess
@ 2012-09-05 18:54         ` Jan Kratochvil
  0 siblings, 0 replies; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-05 18:54 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On Tue, 04 Sep 2012 18:57:41 +0200, Andrew Burgess wrote:
> On 03/09/2012 4:16 PM, Jan Kratochvil wrote:
> > ABI registers order: rdi rsi rdx rcx r8 r9
> > ==amd64_dummy_call_integer_regs
> 
> You're correct that what I originally wrote was not correct, but I think the
> register ordering used for what was test2, which is the
> extend-into-next-register behaviour, is actually just using the gdb register
> number, so this would be from the enum amd64_regnum.

In my text above I was only following the ABI standard
	http://www.x86-64.org/documentation/abi.pdf
specifically:
	2. If the class is INTEGER, the next available register of the
	sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used13 .
IIUC this does not mean this hack of register numbers flowing should be used,
it just specifies which registers should be put in DWARF for DW_OP_piece.

In the case the hack of register numbers flowing is used:

For i386 there is:
	i386_register_to_value -> i386_next_regnum
so i386 does not follow GDB numbering but its own one.  During my testcase GDB
(correctly for GCC) composed HIGH(%edx==gdb reg. #2) | LOW(%eax==gdb reg. #0).
as i386_next_regnum (%eax==gdb reg. #0) == %edx==gdb reg. #2.

For amd64 the target code does not do anything specific so it is processed in
read_frame_register_value and it really follows the GDB registers numbering.
But that seems wrong to me as it violates the ABI specification above.
Still it is not being used for anything in real world I think.  An assertion
there does not trigger on GDB testsuite at all.  It would trigger on the AVR
target it was written for
	[RFA/RFC] Restore old handling of multi-register variables
	http://sourceware.org/ml/gdb-patches/2011-10/msg00052.html
but I think that should have been written only to avr-tdep.c with some AVR
registers numbering on mind.

I was unable to produce any such DWARF output (using register numbers flowing)
from any i386/x86_64 GCC compiler here, like FSF 3.4.6, Red Hat 4.1 or FSF
4.4. So I do not think it is of any much concern how multi-register values
behave in read_frame_register_value, except for that AVR compatibility.  It is
also not exploited by your 'bad-bt' testcase. It is exploited by
'struct_param_single_reg_loc' from your new testcase but specifying gdb
numbers of registers there is rather a compatibility with current - assumed
buggy - GDB behavior.


> Any more feedback, or is this ok to commit ?

I am fine with that stating there like:
	This gdb register numbers usage exposed to external DWARF data is more
	a GDB bug and it should be move to target dependent code (such as AVR)
	as a workaround of existing broken DWARF.

Best to keep it here for a week for comments before commit.


Thanks,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-08-31 10:33   ` Andrew Burgess
  2012-09-01  8:17     ` Eli Zaretskii
  2012-09-03 15:17     ` Jan Kratochvil
@ 2012-09-12 17:30     ` Tom Tromey
  2012-09-13 12:34       ` Andrew Burgess
  2 siblings, 1 reply; 21+ messages in thread
From: Tom Tromey @ 2012-09-12 17:30 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, Jan Kratochvil

>>>>> "Andrew" == Andrew Burgess <aburgess@broadcom.com> writes:

Andrew> (3) Structures the size of two registers split over two
Andrew> registers using dwarf piece information.

Andrew> (4) Values the size of a single register split over two
Andrew> registers using dwarf piece information to describe the
Andrew> location.

Andrew> Cases (3) and (4) are not fixed by my original patch, and fail
Andrew> for a different reason.  I could remove these from the test, but
Andrew> I believe the tests are reasonable, or at least not totally
Andrew> crazy, so I'm reluctant to just delete them.  I could just
Andrew> commit the test with these two examples marked as known failing
Andrew> .... or I could fix them :)

Andrew> The problem is this,

Andrew>   - In dwarf2loc.c:dwarf_evaluate_loc_desc_full we create the
Andrew>   computed value from the pieced location information.

Andrew>   - In dwarf2loc.c:read_pieced_value we spot that some of the
Andrew>   registers are missing and mark the computed value as optimized
Andrew>   out.

This scenario seems odd to me.  I think what it means is that the
compiler declares an object as being split between two registers -- but
then also knows that one of the registers is not in fact available.

Does any compiler actually do this?

If it is just a theoretical problem I think we can just declare it
unsupported; and, if we do see it, try reporting it as a compiler bug
first.  After all, the compiler could just emit an empty piece instead.

Tom

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-12 17:30     ` Tom Tromey
@ 2012-09-13 12:34       ` Andrew Burgess
  2012-09-14 19:02         ` Tom Tromey
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Burgess @ 2012-09-13 12:34 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey, Jan Kratochvil

On 12/09/2012 6:29 PM, Tom Tromey wrote:
>>>>>> "Andrew" == Andrew Burgess <aburgess@broadcom.com> writes:
> 
> Andrew> (3) Structures the size of two registers split over two
> Andrew> registers using dwarf piece information.
> 
> Andrew> (4) Values the size of a single register split over two
> Andrew> registers using dwarf piece information to describe the
> Andrew> location.
> 
> Andrew> Cases (3) and (4) are not fixed by my original patch, and fail
> Andrew> for a different reason.  I could remove these from the test, but
> Andrew> I believe the tests are reasonable, or at least not totally
> Andrew> crazy, so I'm reluctant to just delete them.  I could just
> Andrew> commit the test with these two examples marked as known failing
> Andrew> .... or I could fix them :)
> 
> Andrew> The problem is this,
> 
> Andrew>   - In dwarf2loc.c:dwarf_evaluate_loc_desc_full we create the
> Andrew>   computed value from the pieced location information.
> 
> Andrew>   - In dwarf2loc.c:read_pieced_value we spot that some of the
> Andrew>   registers are missing and mark the computed value as optimized
> Andrew>   out.
> 
> This scenario seems odd to me.  I think what it means is that the
> compiler declares an object as being split between two registers -- but
> then also knows that one of the registers is not in fact available.
> 
> Does any compiler actually do this?

I have never seen such debug, I was just thinking up similar cases to the original test #1, that I have seen.  I agree that in all these cases, if they did occur, it would be incorrect (though not invalid) debug information.

> If it is just a theoretical problem I think we can just declare it
> unsupported; and, if we do see it, try reporting it as a compiler bug
> first.  After all, the compiler could just emit an empty piece instead.

I'm happy to mark these tests as unsupported.  As the tests (#2 -> #4) are pretty much zero cost given that I'm adding test #1 anyway I'd like to leave them in.  I've created a new patch, the only change is that test #3 and #4 now report unsupported (with comment), and test #2 reports pass, with a comment to explain the reasoning.

Full patch below, would everyone be happy with this?

Thanks,

Andrew

gdb/ChangeLog

2012-08-24  Andrew Burgess  <aburgess@broadcom.com>

	* findvar.c (read_frame_register_value): Mark the result value as
	optimized out if any of the input registers have been optimized out.

diff --git a/gdb/findvar.c b/gdb/findvar.c
index 66bcebe..ec9dde7 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -677,7 +677,10 @@ default_value_from_register (struct type *type, int regnum,
 /* VALUE must be an lval_register value.  If regnum is the value's
    associated register number, and len the length of the values type,
    read one or more registers in FRAME, starting with register REGNUM,
-   until we've read LEN bytes.  */
+   until we've read LEN bytes.
+
+   If any of the registers we try to read are optimized out, then mark the
+   complete resulting value as optimized out.  */
 
 void
 read_frame_register_value (struct value *value, struct frame_info *frame)
@@ -703,6 +706,12 @@ read_frame_register_value (struct value *value, struct frame_info *frame)
       struct value *regval = get_frame_register_value (frame, regnum);
       int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
 
+      if (value_optimized_out (regval))
+	{
+	  set_value_optimized_out (value, 1);
+	  break;
+	}
+
       /* If the register length is larger than the number of bytes
          remaining to copy, then only copy the appropriate bytes.  */
       if (reg_len > len)


gdb/testsuite/ChangeLog

2012-08-31  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.dwarf2/dw2-op-out-param.S: New file.
	* gdb.dwarf2/dw2-op-out-param.exp: New file.

diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
new file mode 100644
index 0000000..48fa136
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
@@ -0,0 +1,678 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */        
+
+
+/* Test the behaviour of gdb in the following situation, the dwarf debug
+   information describes a parameter as being in a register but a more
+   recent (inner) frame marks the register as being undefined.
+
+   This can arrise if the dwarf producer has the location of a parameter in
+   a callee clobbered register at the time of a call.  Older versions of
+   gcc used to do this, newer versions seem to avoid this issue.
+
+   Though it could be argued that such dwarf is incorrect, we would still
+   like gdb to behave in a user friendly, and helpful way when presented
+   with such dwarf.  */
+
+/* There are 4 test cases in this assembler file.  In each case funcion
+   main calls each test function in turn, each test case then calls the
+   breakpt function.
+
+   We don't actually pass any parameters around, we don't need to, instead
+   the dwarf for each test function declares that the function has some
+   parameters, and tells us which registers these parameters are in.  The
+   breakpt function marks some of these registers as undefined.  The main
+   function helpfully places some marker values into all the registers that
+   are used as parameters so we can see if they ever get printed.
+
+   We use gdb to break in the breakpt function for each of the 4 test
+   cases, and then backtrace through the test function back to main.  In
+   each case some or all of the parameters to the test function should be
+   marked as optimized out, due to the breakpt function effectively
+   clobbering them.
+
+   The dwarf register numbering is different to the gdb register number.
+   In some of the tests we rely on gdb behaviour of being able to specify a
+   struct using a single register location, the structure will then "flow"
+   into the next gdb register.  The initial register is specified using a
+   dwarf register number, but the "next" register will depend on gdb
+   register ordering.
+
+   Exposing this internal gdb register numbering is really a gdb bug, the
+   functionality for selecting the "next" register should be moved into
+   target dependent code (such as AVR).  Right now we work around this
+   bug in this test; if the bug is ever fixed this test is going to need
+   some tweaking.
+
+   The breakpt function always marks rcx, rsi, and rdi as undefined.
+
+      register | dwarf | gdb   |         |
+      name     | reg # | reg # | breakpt |
+     ----------|-------|-------|---------|
+        rdx    | 1     | 3     |         |
+        rcx    | 2     | 2     | undef   |
+        rbx    | 3     | 1     |         |
+        rsi    | 4     | 4     | undef   |
+        rdi    | 5     | 5     | undef   |
+
+   We declare the test parameters to be in the register rdx, rcx, rbx, rsi,
+   and rdi.  Of these, rdx and rbx are not traditionally used for parameter
+   passing, but that really doesn't matter for this test.
+   
+   int_param_single_reg_loc: Passes 8-byte integer parameters in 8-byte
+                             registers using DW_OP_regn style location
+                             information.  The parameters are placed as
+                             follows, operand0 (rcx), operand1 (rbx),
+                             operand2 (rsi).  We expect operand0 and
+                             operand2 to be marked as optimised out, but
+                             operand1 to be valid.
+
+   struct_param_single_reg_loc: Passes 16-byte structures in two 8-byte
+                                registers using dwarf DW_OP_regn location
+                                information to describe a single register,
+                                gdb will assume that the structure flows
+                                into the next sequential register.  The
+                                parameters are placed as follows, operand0
+                                (rbx/rcx), operand1 (rcx/rdx), and operand2
+                                (rsi/rdi).  The reuse of rcx between
+                                operand0 and operand1 is intentional.
+
+   struct_param_two_reg_pieces: Passes 16-byte structure in two 8-byte
+                                registers using dwarf DW_OP_piece based
+                                location information to describe both
+                                registers.  The parameters are placed as
+                                follows, operand0 (rdx/rcx), operand1
+                                (rcx/rbx), and operand2 (rsi/rdi).  The
+                                reuse of rcx between operand0 and operand1
+                                is intentional.
+
+   int_param_two_reg_pieces: Passes 8-byte integer values in two 8-byte
+                             registers with 4-bytes being placed in each
+                             register, using dwarf DW_OP_piece based
+                             location information to describe how the
+                             parameters are split up.The parameters are
+                             placed as follows, operand0 (rdx/rcx),
+                             operand1 (rcx/rbx), and operand2 (rsi/rdi).
+                             The reuse of rcx between operand0 and operand1
+                             is intentional.
+*/
+
+        .text
+
+.Ltext0:
+        
+        /* main */
+.globl main
+        .type   main, @function
+main:
+.Ltext1:
+        sub    $0x8,%rsp
+.Ltext2:
+        movq    $0xdeadbe00deadbe01, %rbx
+        movq    $0xdeadbe02deadbe03, %rcx
+        movq    $0xdeadbe04deadbe05, %rdx
+        movq    $0xdeadbe06deadbe07, %rsi
+        movq    $0xdeadbe08deadbe09, %rdi
+        
+        callq    int_param_single_reg_loc
+        nop
+
+        callq    struct_param_single_reg_loc
+        nop
+
+        callq    struct_param_two_reg_pieces
+        nop
+
+        callq    int_param_two_reg_pieces
+        nop
+        
+        add    $0x8,%rsp
+        retq
+.Ltext3:
+        .size   main, .-main
+
+        /* breakpt */
+.globl breakpt
+        .type   breakpt, @function
+breakpt:
+.Ltext4:
+        sub    $0x8,%rsp
+        add    $0x8, %rsp
+        retq
+.Ltext5:
+        .size   breakpt, .-breakpt
+        
+        /* int_param_single_reg_loc */
+.globl int_param_single_reg_loc
+        .type   int_param_single_reg_loc, @function
+int_param_single_reg_loc:
+.Ltext5:
+        sub    $0x8,%rsp
+.Ltext6:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext7:
+        .size   int_param_single_reg_loc, .-int_param_single_reg_loc
+
+        /* struct_param_single_reg_loc */
+.globl struct_param_single_reg_loc
+        .type   struct_param_single_reg_loc, @function
+struct_param_single_reg_loc:
+.Ltext8:
+        sub    $0x8,%rsp
+.Ltext9:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext10:
+        .size   struct_param_single_reg_loc, .-struct_param_single_reg_loc
+
+        /* struct_param_two_reg_pieces */
+.globl struct_param_two_reg_pieces
+        .type   struct_param_two_reg_pieces, @function
+struct_param_two_reg_pieces:
+.Ltext11:
+        sub    $0x8,%rsp
+.Ltext12:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext13:
+        .size   struct_param_two_reg_pieces, .-struct_param_two_reg_pieces
+
+        /* int_param_two_reg_pieces */
+.globl int_param_two_reg_pieces
+        .type   int_param_two_reg_pieces, @function
+int_param_two_reg_pieces:
+.Ltext14:
+        sub    $0x8,%rsp
+.Ltext15:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext16:
+        .size   int_param_two_reg_pieces, .-int_param_two_reg_pieces
+        
+
+.Letext0:
+
+        /*******************************************************/
+
+        .section	.debug_frame,"",@progbits
+        
+        /* CIE */
+.Lframe0:
+	.long	.LECIE0-.LSCIE0 /* length */
+.LSCIE0:
+	.long	0xffffffff      /* CIE_id */
+	.byte	0x1             /* version */
+	.string	""              /* augmentation */
+	.uleb128 0x1            /* code alignment */
+	.sleb128 -8             /* data alignment */
+	.byte	0x10            /* R/A column */
+        /* Initial instructions */
+	.byte	0xc             /* DW_CFA_def_cfa */
+	.uleb128 0x7            /* reg# */
+	.uleb128 0x8            /* offset */
+	.byte	0x90            /* DW_CFA_offset (r16) */
+	.uleb128 0x1            /* offset */
+	.align 8
+.LECIE0:
+
+        /* FDE : breakpt */
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0        /* length */
+.LASFDE0:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext4                 /* start */
+	.quad	.Ltext5-.Ltext4         /* length */
+        /* Instructions */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x2                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x4                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x5                    /* reg# */
+	.align 8
+.LEFDE0:
+
+        /* FDE : int_param_single_reg_loc */
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2        /* length */
+.LASFDE2:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext5                 /* start */
+	.quad	.Ltext7-.Ltext5         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext6-.Ltext5
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE2:
+
+        /* FDE : struct_param_single_reg_loc */
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3        /* length */
+.LASFDE3:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext8                 /* start */
+	.quad	.Ltext10-.Ltext8        /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext9-.Ltext8
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE3:
+
+        /* FDE : struct_param_two_reg_pieces */
+.LSFDE4:
+	.long	.LEFDE4-.LASFDE4        /* length */
+.LASFDE4:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext11                /* start */
+	.quad	.Ltext13-.Ltext11       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext12-.Ltext11
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE4:
+
+        /* FDE : int_param_two_reg_pieces */
+.LSFDE5:
+	.long	.LEFDE5-.LASFDE5        /* length */
+.LASFDE5:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext14                /* start */
+	.quad	.Ltext16-.Ltext14       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext15-.Ltext14
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE5:
+
+        /* FDE : main */
+.LSFDE9:
+	.long	.LEFDE9-.LASFDE9        /* length */
+.LASFDE9:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext1                 /* start */
+	.quad	.Ltext3-.Ltext1         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext2-.Ltext1
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE9:
+
+        /*******************************************************/        
+        
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+        .long  .Ldebug_info_end - .Ldebug_info_start   /* Length */
+.Ldebug_info_start:
+	.value	0x2                     /* DWARF version number. */
+	.long	.Ldebug_abbrev0         /* Offset into .debug_abbrev */
+	.byte	0x8                     /* Pointer size */
+
+.LDI0:        
+	.uleb128 0x1                    /* DW_TAG_compile_unit */
+	.string	"GNU C 4.2.1"           /* DW_AT_producer */
+	.byte	0x1                     /* DW_AT_language */
+	.quad	.Ltext0                 /* DW_AT_low_pc */
+	.quad	.Letext0                /* DW_AT_high_pc */
+
+.LDI1:
+	.uleb128 0x2                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"breakpt"               /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext4                 /* DW_AT_low_pc */
+	.quad	.Ltext5                 /* DW_AT_high_pc */        
+
+.LDI2:
+	.uleb128 0x5                    /* DW_TAG_base_type */
+	.byte	0x8                     /* DW_AT_byte_size */
+	.byte	0x5                     /* DW_AT_encoding (DW_ATE_signed) */
+	.string	"long int"              /* DW_AT_name */
+
+.LDI3:
+        .uleb128 0x7                    /* DW_TAG_structure_type */
+        .string "big"                   /* DW_AT_name */
+        .byte   0x10                    /* DW_AT_byte_size */
+        .long   .LDI6                   /* DW_AT_sibling */
+        
+.LDI4:
+        .uleb128 0x8                    /* DW_TAG_member */
+        .string "a"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x0                    /*   + 0 */
+        
+.LDI5:
+        .uleb128 0x8                    /* DW_TAG_structure_type */
+        .string "b"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x8                    /*   + 8 */
+        .byte   0x0
+
+.LDI6:
+	.uleb128 0x6                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"main"                  /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.quad	.Ltext1                 /* DW_AT_low_pc */
+	.quad	.Ltext3                 /* DW_AT_high_pc */
+
+.LDI7:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext5                 /* DW_AT_low_pc */
+	.quad	.Ltext7                 /* DW_AT_high_pc */
+	.long	.LDI11                  /* DW_AT_sibling */        
+        
+.LDI8:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+
+.LDI9:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */        
+        
+.LDI10:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0        
+
+.LDI11:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext8                 /* DW_AT_low_pc */
+	.quad	.Ltext10                /* DW_AT_high_pc */
+	.long	.LDI15                   /* DW_AT_sibling */        
+        
+.LDI12:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */
+
+.LDI13:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */        
+        
+.LDI14:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0
+
+.LDI15:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext11                /* DW_AT_low_pc */
+	.quad	.Ltext13                /* DW_AT_high_pc */
+	.long	.LDI19                  /* DW_AT_sibling */        
+        
+.LDI16:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+
+.LDI17:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+.LDI18:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+	.byte	0x0
+
+.LDI19:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext14                /* DW_AT_low_pc */
+	.quad	.Ltext16                /* DW_AT_high_pc */
+	.long	.LDIE0                  /* DW_AT_sibling */        
+        
+.LDI20:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+
+.LDI21:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+.LDI22:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+	.byte	0x0
+        
+.LDIE0:
+	.byte	0x0
+.Ldebug_info_end:
+
+        /*******************************************************/        
+        
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1    /* abbrev code */
+	.uleb128 0x11   /* TAG: DW_TAG_compile_unit */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x25   /* DW_AT_producer */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x13   /* DW_AT_language */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+        .uleb128 0x11   /* DW_AT_low_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+        .uleb128 0x12   /* DW_AT_high_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x2    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x3    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x1    /* DW_AT_sibling */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x4    /* abbrev code */
+	.uleb128 0x5    /* TAG: DW_TAG_formal_parameter */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x2    /* DW_AT_location */
+	.uleb128 0xa    /*   DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x5    /* abbrev code */
+	.uleb128 0x24   /* TAG: DW_TAG_base_type */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0xb    /* DW_AT_byte_size */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3e   /* DW_AT_encoding */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x6    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+
+        .uleb128 0x7    /* abbrev code */
+        .uleb128 0x13   /* DW_TAG_structure_type */
+        .byte   0x1     /* DW_CHILDREN_yes */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0xb    /* DW_AT_byte_size */
+        .uleb128 0xb    /*    DW_FORM_data1 */
+        .uleb128 0x1    /* DW_AT_sibling */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .byte   0x0
+        .byte   0x0
+        
+        .uleb128 0x8    /* abbrev code */
+        .uleb128 0xd    /* DW_TAG_member */
+        .byte   0x0     /* DW_children_no */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0x49   /* DW_AT_type */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .uleb128 0x38   /* DW_AT_data_member_location */
+        .uleb128 0xa    /*   DW_FORM_block1 */
+        .byte   0x0
+        .byte   0x0
+        
+	.byte	0x0
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
new file mode 100644
index 0000000..ec98a3a
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -0,0 +1,108 @@
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+set test "dw2-op-out-param"
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if ![dwarf2_support] {
+    return 0  
+}
+
+# This test can only be run on x86-64 targets.
+if {![istarget x86_64-*] || ![is_lp64_target]} {
+    return 0
+}
+
+if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "breakpt"
+
+# Change the radix, making it easier to spot 0xdeadbeef in output.
+gdb_test "set output-radix 16" \
+    "Output radix now set to decimal 16, hex 10, octal 20."
+
+# So we get to see the structure arguments.
+gdb_test_no_output "set print frame-arguments all"
+
+# (1) int_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for test int_param_single_reg_loc"
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_single_reg_loc \\(operand0=<optimized out>, operand1=0xdeadbe00deadbe01, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test int_param_single_reg_loc"
+
+# (2) struct_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_single_reg_loc"
+set test "Backtrace for test struct_param_single_reg_loc"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe04deadbe05}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# If we ever fix gdb so that we start to hit this case then we
+	# should delete the passing case below as this is a better state to
+	# be in, and we don't want to regress back to the case below.
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# Having DWARF debug information placing things into registers that
+	# are then clobbered is really bad debug information.  If this is
+	# ever seen we'd prefer to fix the producer of the debug
+	# information.  Right now there are no plans to improve this case
+	# in gdb so we're happy with the output given above.
+	pass $test
+    }
+}
+
+# (3) struct_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_two_reg_pieces"
+set test "Backtrace for test struct_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# If we ever fix gdb so this passes we should delete the
+	# unsupported case below.
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# Having DWARF debug information placing things into registers that
+	# are then clobbered is really bad debug information.  If this is
+	# ever seen we'd prefer to fix the producer of the debug
+	# information.  Right now there are no plans to fix this case in
+	# gdb.
+	unsupported $test
+    }
+}
+
+# (4) int_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for int_param_two_reg_pieces"
+set test "Backtrace for test int_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# If we ever fix gdb so this passes we should delete the
+	# unsupported case below.
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	# Having DWARF debug information placing things into registers that
+	# are then clobbered is really bad debug information.  If this is
+	# ever seen we'd prefer to fix the producer of the debug
+	# information.  Right now there are no plans to fix this case in
+	# gdb.
+	unsupported $test
+    }
+}
+


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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-13 12:34       ` Andrew Burgess
@ 2012-09-14 19:02         ` Tom Tromey
  2012-09-14 21:39           ` Andrew Burgess
  0 siblings, 1 reply; 21+ messages in thread
From: Tom Tromey @ 2012-09-14 19:02 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, Jan Kratochvil

>>>>> "Andrew" == Andrew Burgess <aburgess@broadcom.com> writes:

Tom> If it is just a theoretical problem I think we can just declare it
Tom> unsupported; and, if we do see it, try reporting it as a compiler bug
Tom> first.  After all, the compiler could just emit an empty piece instead.

Andrew> I'm happy to mark these tests as unsupported.  As the tests (#2
Andrew> -> #4) are pretty much zero cost given that I'm adding test #1
Andrew> anyway I'd like to leave them in.  I've created a new patch, the
Andrew> only change is that test #3 and #4 now report unsupported (with
Andrew> comment), and test #2 reports pass, with a comment to explain
Andrew> the reasoning.

Andrew> +	# If we ever fix gdb so this passes we should delete the
Andrew> +	# unsupported case below.
Andrew> +	xpass $test

Andrew> +	unsupported $test

I think these tests should 'pass' if they generate the correct output,
and 'kfail' otherwise.

Tom

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-14 19:02         ` Tom Tromey
@ 2012-09-14 21:39           ` Andrew Burgess
  2012-09-17 16:57             ` Jan Kratochvil
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Burgess @ 2012-09-14 21:39 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Jan Kratochvil

On 14/09/2012 8:02 PM, Tom Tromey wrote:
>>>>>> "Andrew" == Andrew Burgess <aburgess@broadcom.com> writes:
>
> Tom> If it is just a theoretical problem I think we can just declare it
> Tom> unsupported; and, if we do see it, try reporting it as a compiler bug
> Tom> first.  After all, the compiler could just emit an empty piece instead.
>
> Andrew> I'm happy to mark these tests as unsupported.  As the tests (#2
> Andrew> -> #4) are pretty much zero cost given that I'm adding test #1
> Andrew> anyway I'd like to leave them in.  I've created a new patch, the
> Andrew> only change is that test #3 and #4 now report unsupported (with
> Andrew> comment), and test #2 reports pass, with a comment to explain
> Andrew> the reasoning.
>
> Andrew> +	# If we ever fix gdb so this passes we should delete the
> Andrew> +	# unsupported case below.
> Andrew> +	xpass $test
>
> Andrew> +	unsupported $test
>
> I think these tests should 'pass' if they generate the correct output,
> and 'kfail' otherwise.

But if they kfail then they need a defect ID, it seems rather pointless 
to raise a defect for unsupported behaviour we have no intention to fix.

Surely xpass is the right choice.  If the test ever does pass I hope the 
unexpected pass result will draw attention to the test so the 
"unsupported" (or kfail) can be removed.  If it was just a pass then 
there's a chance the test could be fixed then regress and we'd never 
notice as the unsupported (or kfail) would never have been removed.

Cheers,
Andrew

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-14 21:39           ` Andrew Burgess
@ 2012-09-17 16:57             ` Jan Kratochvil
  2012-09-19 14:29               ` Andrew Burgess
  0 siblings, 1 reply; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-17 16:57 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Tom Tromey, gdb-patches

On Fri, 14 Sep 2012 23:39:37 +0200, Andrew Burgess wrote:
> On 14/09/2012 8:02 PM, Tom Tromey wrote:
> >Andrew> +	# If we ever fix gdb so this passes we should delete the
> >Andrew> +	# unsupported case below.
> >Andrew> +	xpass $test
> >
> >Andrew> +	unsupported $test
> >
> >I think these tests should 'pass' if they generate the correct output,
> >and 'kfail' otherwise.

I agree with Tom here.

There are ongoing disputes how to mark testsuite results as it is more
a matter of opinion, so I do not want much to argue about anything.
Also I am not sure if I wrote it below so that it can be well understood.


> But if they kfail then they need a defect ID, it seems rather
> pointless to raise a defect for unsupported behaviour we have no
> intention to fix.

Not everything may be perfect but it is the current practice to do it that
way.


> Surely xpass is the right choice.

'xpass' is OK.  But that 'pass' is not right, we know GDB could behave better
(*). 'kfail' is for the 'pass' state more appropriate as we know GDB has
a (theoretical) problem.

(*) It is not important here whether it is worth the effort which it is not.

XPASS
     A pleasant kind of failure: a test was expected to fail, but
     succeeded. This may indicate progress; inspect the test case to
     determine whether you should amend it to stop expecting failure.


> If the test ever does pass I hope
> the unexpected pass result will draw attention to the test so the
> "unsupported" (or kfail) can be removed.  If it was just a pass then
> there's a chance the test could be fixed then regress and we'd never
> notice as the unsupported (or kfail) would never have been removed.

'unsupported' should not apply in any of these cases as it is about the testing
environment.  But all these testcases do not depend on anything in system.

UNSUPPORTED
     A test depends on a conditionally available feature that does not
     exist (in the configured testing environment).  For example, you
     can use this outcome to report on a test case that does not work
     on a particular target because its operating system support does
     not include a required subroutine.


Thanks,
Jan

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-17 16:57             ` Jan Kratochvil
@ 2012-09-19 14:29               ` Andrew Burgess
  2012-09-20 13:28                 ` Jan Kratochvil
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Burgess @ 2012-09-19 14:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil, Tom Tromey

On 17/09/2012 5:56 PM, Jan Kratochvil wrote:
> On Fri, 14 Sep 2012 23:39:37 +0200, Andrew Burgess wrote:
>> On 14/09/2012 8:02 PM, Tom Tromey wrote:
>>> Andrew> +	# If we ever fix gdb so this passes we should delete the
>>> Andrew> +	# unsupported case below.
>>> Andrew> +	xpass $test
>>>
>>> Andrew> +	unsupported $test
>>>
>>> I think these tests should 'pass' if they generate the correct output,
>>> and 'kfail' otherwise.
> 
> I agree with Tom here.

Ok, new version of patch below, same as before except,

  - Uses xpass for the tests that are currently failing if they do ever produce the correct output, this will encourage whoever fixes them to go and remove the kfails.
  - Uses kfail for the current broken output.  There are no real bug IDs in place yet.  Once I get approval to commit I'll open bug reports, and push a version of this patch with the actual bug IDs in place.  I'm happy to open the bugs earlier if that's a requirement for me to get approval.

Is this ok to commit?

Thanks,

Andrew


gdb/ChangeLog

2012-08-24  Andrew Burgess  <aburgess@broadcom.com>

	* findvar.c (read_frame_register_value): Mark the result value as
	optimized out if any of the input registers have been optimized out.

diff --git a/gdb/findvar.c b/gdb/findvar.c
index 66bcebe..ec9dde7 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -677,7 +677,10 @@ default_value_from_register (struct type *type, int regnum,
 /* VALUE must be an lval_register value.  If regnum is the value's
    associated register number, and len the length of the values type,
    read one or more registers in FRAME, starting with register REGNUM,
-   until we've read LEN bytes.  */
+   until we've read LEN bytes.
+
+   If any of the registers we try to read are optimized out, then mark the
+   complete resulting value as optimized out.  */
 
 void
 read_frame_register_value (struct value *value, struct frame_info *frame)
@@ -703,6 +706,12 @@ read_frame_register_value (struct value *value, struct frame_info *frame)
       struct value *regval = get_frame_register_value (frame, regnum);
       int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
 
+      if (value_optimized_out (regval))
+	{
+	  set_value_optimized_out (value, 1);
+	  break;
+	}
+
       /* If the register length is larger than the number of bytes
          remaining to copy, then only copy the appropriate bytes.  */
       if (reg_len > len)


gdb/testsuite/ChangeLog

2012-09-19  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.dwarf2/dw2-op-out-param.S: New file.
	* gdb.dwarf2/dw2-op-out-param.exp: New file.

diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
new file mode 100644
index 0000000..48fa136
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S
@@ -0,0 +1,678 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */        
+
+
+/* Test the behaviour of gdb in the following situation, the dwarf debug
+   information describes a parameter as being in a register but a more
+   recent (inner) frame marks the register as being undefined.
+
+   This can arrise if the dwarf producer has the location of a parameter in
+   a callee clobbered register at the time of a call.  Older versions of
+   gcc used to do this, newer versions seem to avoid this issue.
+
+   Though it could be argued that such dwarf is incorrect, we would still
+   like gdb to behave in a user friendly, and helpful way when presented
+   with such dwarf.  */
+
+/* There are 4 test cases in this assembler file.  In each case funcion
+   main calls each test function in turn, each test case then calls the
+   breakpt function.
+
+   We don't actually pass any parameters around, we don't need to, instead
+   the dwarf for each test function declares that the function has some
+   parameters, and tells us which registers these parameters are in.  The
+   breakpt function marks some of these registers as undefined.  The main
+   function helpfully places some marker values into all the registers that
+   are used as parameters so we can see if they ever get printed.
+
+   We use gdb to break in the breakpt function for each of the 4 test
+   cases, and then backtrace through the test function back to main.  In
+   each case some or all of the parameters to the test function should be
+   marked as optimized out, due to the breakpt function effectively
+   clobbering them.
+
+   The dwarf register numbering is different to the gdb register number.
+   In some of the tests we rely on gdb behaviour of being able to specify a
+   struct using a single register location, the structure will then "flow"
+   into the next gdb register.  The initial register is specified using a
+   dwarf register number, but the "next" register will depend on gdb
+   register ordering.
+
+   Exposing this internal gdb register numbering is really a gdb bug, the
+   functionality for selecting the "next" register should be moved into
+   target dependent code (such as AVR).  Right now we work around this
+   bug in this test; if the bug is ever fixed this test is going to need
+   some tweaking.
+
+   The breakpt function always marks rcx, rsi, and rdi as undefined.
+
+      register | dwarf | gdb   |         |
+      name     | reg # | reg # | breakpt |
+     ----------|-------|-------|---------|
+        rdx    | 1     | 3     |         |
+        rcx    | 2     | 2     | undef   |
+        rbx    | 3     | 1     |         |
+        rsi    | 4     | 4     | undef   |
+        rdi    | 5     | 5     | undef   |
+
+   We declare the test parameters to be in the register rdx, rcx, rbx, rsi,
+   and rdi.  Of these, rdx and rbx are not traditionally used for parameter
+   passing, but that really doesn't matter for this test.
+   
+   int_param_single_reg_loc: Passes 8-byte integer parameters in 8-byte
+                             registers using DW_OP_regn style location
+                             information.  The parameters are placed as
+                             follows, operand0 (rcx), operand1 (rbx),
+                             operand2 (rsi).  We expect operand0 and
+                             operand2 to be marked as optimised out, but
+                             operand1 to be valid.
+
+   struct_param_single_reg_loc: Passes 16-byte structures in two 8-byte
+                                registers using dwarf DW_OP_regn location
+                                information to describe a single register,
+                                gdb will assume that the structure flows
+                                into the next sequential register.  The
+                                parameters are placed as follows, operand0
+                                (rbx/rcx), operand1 (rcx/rdx), and operand2
+                                (rsi/rdi).  The reuse of rcx between
+                                operand0 and operand1 is intentional.
+
+   struct_param_two_reg_pieces: Passes 16-byte structure in two 8-byte
+                                registers using dwarf DW_OP_piece based
+                                location information to describe both
+                                registers.  The parameters are placed as
+                                follows, operand0 (rdx/rcx), operand1
+                                (rcx/rbx), and operand2 (rsi/rdi).  The
+                                reuse of rcx between operand0 and operand1
+                                is intentional.
+
+   int_param_two_reg_pieces: Passes 8-byte integer values in two 8-byte
+                             registers with 4-bytes being placed in each
+                             register, using dwarf DW_OP_piece based
+                             location information to describe how the
+                             parameters are split up.The parameters are
+                             placed as follows, operand0 (rdx/rcx),
+                             operand1 (rcx/rbx), and operand2 (rsi/rdi).
+                             The reuse of rcx between operand0 and operand1
+                             is intentional.
+*/
+
+        .text
+
+.Ltext0:
+        
+        /* main */
+.globl main
+        .type   main, @function
+main:
+.Ltext1:
+        sub    $0x8,%rsp
+.Ltext2:
+        movq    $0xdeadbe00deadbe01, %rbx
+        movq    $0xdeadbe02deadbe03, %rcx
+        movq    $0xdeadbe04deadbe05, %rdx
+        movq    $0xdeadbe06deadbe07, %rsi
+        movq    $0xdeadbe08deadbe09, %rdi
+        
+        callq    int_param_single_reg_loc
+        nop
+
+        callq    struct_param_single_reg_loc
+        nop
+
+        callq    struct_param_two_reg_pieces
+        nop
+
+        callq    int_param_two_reg_pieces
+        nop
+        
+        add    $0x8,%rsp
+        retq
+.Ltext3:
+        .size   main, .-main
+
+        /* breakpt */
+.globl breakpt
+        .type   breakpt, @function
+breakpt:
+.Ltext4:
+        sub    $0x8,%rsp
+        add    $0x8, %rsp
+        retq
+.Ltext5:
+        .size   breakpt, .-breakpt
+        
+        /* int_param_single_reg_loc */
+.globl int_param_single_reg_loc
+        .type   int_param_single_reg_loc, @function
+int_param_single_reg_loc:
+.Ltext5:
+        sub    $0x8,%rsp
+.Ltext6:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext7:
+        .size   int_param_single_reg_loc, .-int_param_single_reg_loc
+
+        /* struct_param_single_reg_loc */
+.globl struct_param_single_reg_loc
+        .type   struct_param_single_reg_loc, @function
+struct_param_single_reg_loc:
+.Ltext8:
+        sub    $0x8,%rsp
+.Ltext9:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext10:
+        .size   struct_param_single_reg_loc, .-struct_param_single_reg_loc
+
+        /* struct_param_two_reg_pieces */
+.globl struct_param_two_reg_pieces
+        .type   struct_param_two_reg_pieces, @function
+struct_param_two_reg_pieces:
+.Ltext11:
+        sub    $0x8,%rsp
+.Ltext12:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext13:
+        .size   struct_param_two_reg_pieces, .-struct_param_two_reg_pieces
+
+        /* int_param_two_reg_pieces */
+.globl int_param_two_reg_pieces
+        .type   int_param_two_reg_pieces, @function
+int_param_two_reg_pieces:
+.Ltext14:
+        sub    $0x8,%rsp
+.Ltext15:
+        nop
+        callq    breakpt
+        nop
+        add    $0x8,%rsp
+        retq
+.Ltext16:
+        .size   int_param_two_reg_pieces, .-int_param_two_reg_pieces
+        
+
+.Letext0:
+
+        /*******************************************************/
+
+        .section	.debug_frame,"",@progbits
+        
+        /* CIE */
+.Lframe0:
+	.long	.LECIE0-.LSCIE0 /* length */
+.LSCIE0:
+	.long	0xffffffff      /* CIE_id */
+	.byte	0x1             /* version */
+	.string	""              /* augmentation */
+	.uleb128 0x1            /* code alignment */
+	.sleb128 -8             /* data alignment */
+	.byte	0x10            /* R/A column */
+        /* Initial instructions */
+	.byte	0xc             /* DW_CFA_def_cfa */
+	.uleb128 0x7            /* reg# */
+	.uleb128 0x8            /* offset */
+	.byte	0x90            /* DW_CFA_offset (r16) */
+	.uleb128 0x1            /* offset */
+	.align 8
+.LECIE0:
+
+        /* FDE : breakpt */
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0        /* length */
+.LASFDE0:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext4                 /* start */
+	.quad	.Ltext5-.Ltext4         /* length */
+        /* Instructions */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x2                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x4                    /* reg# */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x5                    /* reg# */
+	.align 8
+.LEFDE0:
+
+        /* FDE : int_param_single_reg_loc */
+.LSFDE2:
+	.long	.LEFDE2-.LASFDE2        /* length */
+.LASFDE2:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext5                 /* start */
+	.quad	.Ltext7-.Ltext5         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext6-.Ltext5
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE2:
+
+        /* FDE : struct_param_single_reg_loc */
+.LSFDE3:
+	.long	.LEFDE3-.LASFDE3        /* length */
+.LASFDE3:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext8                 /* start */
+	.quad	.Ltext10-.Ltext8        /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext9-.Ltext8
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE3:
+
+        /* FDE : struct_param_two_reg_pieces */
+.LSFDE4:
+	.long	.LEFDE4-.LASFDE4        /* length */
+.LASFDE4:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext11                /* start */
+	.quad	.Ltext13-.Ltext11       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext12-.Ltext11
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE4:
+
+        /* FDE : int_param_two_reg_pieces */
+.LSFDE5:
+	.long	.LEFDE5-.LASFDE5        /* length */
+.LASFDE5:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext14                /* start */
+	.quad	.Ltext16-.Ltext14       /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext15-.Ltext14
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE5:
+
+        /* FDE : main */
+.LSFDE9:
+	.long	.LEFDE9-.LASFDE9        /* length */
+.LASFDE9:
+	.long	.Lframe0                /* CIE reference */
+	.quad	.Ltext1                 /* start */
+	.quad	.Ltext3-.Ltext1         /* length */
+        /* Instructions */
+ 	.byte	0x4
+	.long	.Ltext2-.Ltext1
+	.byte	0xe
+	.uleb128 0x10
+	.align 8
+.LEFDE9:
+
+        /*******************************************************/        
+        
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+        .long  .Ldebug_info_end - .Ldebug_info_start   /* Length */
+.Ldebug_info_start:
+	.value	0x2                     /* DWARF version number. */
+	.long	.Ldebug_abbrev0         /* Offset into .debug_abbrev */
+	.byte	0x8                     /* Pointer size */
+
+.LDI0:        
+	.uleb128 0x1                    /* DW_TAG_compile_unit */
+	.string	"GNU C 4.2.1"           /* DW_AT_producer */
+	.byte	0x1                     /* DW_AT_language */
+	.quad	.Ltext0                 /* DW_AT_low_pc */
+	.quad	.Letext0                /* DW_AT_high_pc */
+
+.LDI1:
+	.uleb128 0x2                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"breakpt"               /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext4                 /* DW_AT_low_pc */
+	.quad	.Ltext5                 /* DW_AT_high_pc */        
+
+.LDI2:
+	.uleb128 0x5                    /* DW_TAG_base_type */
+	.byte	0x8                     /* DW_AT_byte_size */
+	.byte	0x5                     /* DW_AT_encoding (DW_ATE_signed) */
+	.string	"long int"              /* DW_AT_name */
+
+.LDI3:
+        .uleb128 0x7                    /* DW_TAG_structure_type */
+        .string "big"                   /* DW_AT_name */
+        .byte   0x10                    /* DW_AT_byte_size */
+        .long   .LDI6                   /* DW_AT_sibling */
+        
+.LDI4:
+        .uleb128 0x8                    /* DW_TAG_member */
+        .string "a"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x0                    /*   + 0 */
+        
+.LDI5:
+        .uleb128 0x8                    /* DW_TAG_structure_type */
+        .string "b"                     /* DW_AT_name */
+        .long   .LDI2                   /* DW_AT_type */
+        .byte   0x2                     /* DW_AT_data_member_location : length */
+        .byte   0x23                    /* DW_OP_plus_uconst */
+        .uleb128 0x8                    /*   + 8 */
+        .byte   0x0
+
+.LDI6:
+	.uleb128 0x6                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"main"                  /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.quad	.Ltext1                 /* DW_AT_low_pc */
+	.quad	.Ltext3                 /* DW_AT_high_pc */
+
+.LDI7:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext5                 /* DW_AT_low_pc */
+	.quad	.Ltext7                 /* DW_AT_high_pc */
+	.long	.LDI11                  /* DW_AT_sibling */        
+        
+.LDI8:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+
+.LDI9:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */        
+        
+.LDI10:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0        
+
+.LDI11:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_single_reg_loc"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext8                 /* DW_AT_low_pc */
+	.quad	.Ltext10                /* DW_AT_high_pc */
+	.long	.LDI15                   /* DW_AT_sibling */        
+        
+.LDI12:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x53                    /* DW_OP_reg3 */
+
+.LDI13:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */        
+        
+.LDI14:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	1                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        
+	.byte	0x0
+
+.LDI15:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"struct_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext11                /* DW_AT_low_pc */
+	.quad	.Ltext13                /* DW_AT_high_pc */
+	.long	.LDI19                  /* DW_AT_sibling */        
+        
+.LDI16:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+
+.LDI17:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+.LDI18:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI3                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x8                    /*    8 bytes */
+        
+	.byte	0x0
+
+.LDI19:
+	.uleb128 0x3                    /* DW_TAG_subprogram */
+	.byte	0x1                     /* DW_AT_external */
+	.string	"int_param_two_reg_pieces"                 /* DW_AT_name */
+	.byte	0x1                     /* DW_AT_prototyped */
+	.quad	.Ltext14                /* DW_AT_low_pc */
+	.quad	.Ltext16                /* DW_AT_high_pc */
+	.long	.LDIE0                  /* DW_AT_sibling */        
+        
+.LDI20:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand0"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x51                    /* DW_OP_reg1 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+
+.LDI21:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand1"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x52                    /* DW_OP_reg2 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x53                    /* DW_OP_reg3 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+.LDI22:
+	.uleb128 0x4                    /* DW_TAG_formal_parameter */
+	.string	"operand2"              /* DW_AT_name */
+	.long	.LDI2                   /* DW_AT_type */
+	.byte	6                       /* DW_AT_location : length */
+	.byte	0x54                    /* DW_OP_reg4 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+	.byte	0x55                    /* DW_OP_reg5 */
+        .byte   0x93                    /* DW_OP_piece */
+        .uleb128 0x4                    /*    4 bytes */
+        
+	.byte	0x0
+        
+.LDIE0:
+	.byte	0x0
+.Ldebug_info_end:
+
+        /*******************************************************/        
+        
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1    /* abbrev code */
+	.uleb128 0x11   /* TAG: DW_TAG_compile_unit */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x25   /* DW_AT_producer */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x13   /* DW_AT_language */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+        .uleb128 0x11   /* DW_AT_low_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+        .uleb128 0x12   /* DW_AT_high_pc */
+        .uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x2    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x3    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x1     /* DW_CHILDREN_yes */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x27   /* DW_AT_prototyped */
+	.uleb128 0xc    /*    DW_FORM_flag*/
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x1    /* DW_AT_sibling */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x4    /* abbrev code */
+	.uleb128 0x5    /* TAG: DW_TAG_formal_parameter */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x2    /* DW_AT_location */
+	.uleb128 0xa    /*   DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x5    /* abbrev code */
+	.uleb128 0x24   /* TAG: DW_TAG_base_type */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0xb    /* DW_AT_byte_size */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3e   /* DW_AT_encoding */
+	.uleb128 0xb    /*   DW_FORM_data1 */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.byte	0x0
+	.byte	0x0
+        
+	.uleb128 0x6    /* abbrev code */
+	.uleb128 0x2e   /* TAG: DW_TAG_subprogram */
+	.byte	0x0     /* DW_CHILDREN_no */
+	.uleb128 0x3f   /* DW_AT_external */
+	.uleb128 0xc    /*   DW_FORM_flag */
+	.uleb128 0x3    /* DW_AT_name */
+	.uleb128 0x8    /*   DW_FORM_string */
+	.uleb128 0x49   /* DW_AT_type */
+	.uleb128 0x13   /*   DW_FORM_ref4 */
+	.uleb128 0x11   /* DW_AT_low_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.uleb128 0x12   /* DW_AT_high_pc */
+	.uleb128 0x1    /*   DW_FORM_addr */
+	.byte	0x0
+	.byte	0x0
+
+        .uleb128 0x7    /* abbrev code */
+        .uleb128 0x13   /* DW_TAG_structure_type */
+        .byte   0x1     /* DW_CHILDREN_yes */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0xb    /* DW_AT_byte_size */
+        .uleb128 0xb    /*    DW_FORM_data1 */
+        .uleb128 0x1    /* DW_AT_sibling */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .byte   0x0
+        .byte   0x0
+        
+        .uleb128 0x8    /* abbrev code */
+        .uleb128 0xd    /* DW_TAG_member */
+        .byte   0x0     /* DW_children_no */
+        .uleb128 0x3    /* DW_AT_name */
+        .uleb128 0x8    /*   DW_FORM_string */
+        .uleb128 0x49   /* DW_AT_type */
+        .uleb128 0x13   /*   DW_FORM_ref4 */
+        .uleb128 0x38   /* DW_AT_data_member_location */
+        .uleb128 0xa    /*   DW_FORM_block1 */
+        .byte   0x0
+        .byte   0x0
+        
+	.byte	0x0
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
new file mode 100644
index 0000000..20e29d0
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -0,0 +1,86 @@
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+set test "dw2-op-out-param"
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if ![dwarf2_support] {
+    return 0  
+}
+
+# This test can only be run on x86-64 targets.
+if {![istarget x86_64-*] || ![is_lp64_target]} {
+    return 0
+}
+
+if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "breakpt"
+
+# Change the radix, making it easier to spot 0xdeadbeef in output.
+gdb_test "set output-radix 16" \
+    "Output radix now set to decimal 16, hex 10, octal 20."
+
+# So we get to see the structure arguments.
+gdb_test_no_output "set print frame-arguments all"
+
+# (1) int_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for test int_param_single_reg_loc"
+gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_single_reg_loc \\(operand0=<optimized out>, operand1=0xdeadbe00deadbe01, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)" "Backtrace for test int_param_single_reg_loc"
+
+# (2) struct_param_single_reg_loc
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_single_reg_loc"
+set test "Backtrace for test struct_param_single_reg_loc"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe04deadbe05}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_single_reg_loc \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail "BUG-ID" $test
+    }
+}
+
+# (3) struct_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for struct_param_two_reg_pieces"
+set test "Backtrace for test struct_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?struct_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail "BUG-ID" $test
+    }
+}
+
+# (4) int_param_two_reg_pieces
+gdb_continue_to_breakpoint "Stop in breakpt for int_param_two_reg_pieces"
+set test "Backtrace for test int_param_two_reg_pieces"
+gdb_test_multiple "bt" "$test" {
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	xpass $test
+    }
+    -re "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2  ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+	kfail "BUG-ID" $test
+    }
+}
+


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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-19 14:29               ` Andrew Burgess
@ 2012-09-20 13:28                 ` Jan Kratochvil
  2012-09-21 17:19                   ` Andrew Burgess
  0 siblings, 1 reply; 21+ messages in thread
From: Jan Kratochvil @ 2012-09-20 13:28 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, Tom Tromey

On Wed, 19 Sep 2012 16:28:45 +0200, Andrew Burgess wrote:
> Ok, new version of patch below, same as before except,
> 
>   - Uses xpass for the tests that are currently failing if they do ever produce the correct output, this will encourage whoever fixes them to go and remove the kfails.
>   - Uses kfail for the current broken output.  There are no real bug IDs in place yet.  Once I get approval to commit I'll open bug reports, and push a version of this patch with the actual bug IDs in place.  I'm happy to open the bugs earlier if that's a requirement for me to get approval.
> 
> Is this ok to commit?

I am fine with this patch.


Thanks,
Jan


> gdb/ChangeLog
> 
> 2012-08-24  Andrew Burgess  <aburgess@broadcom.com>
> 
> 	* findvar.c (read_frame_register_value): Mark the result value as
> 	optimized out if any of the input registers have been optimized out.
[...]
> gdb/testsuite/ChangeLog
> 
> 2012-09-19  Andrew Burgess  <aburgess@broadcom.com>
> 
> 	* gdb.dwarf2/dw2-op-out-param.S: New file.
> 	* gdb.dwarf2/dw2-op-out-param.exp: New file.

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

* Re: PATCH: error reading variable: value has been optimized out
  2012-09-20 13:28                 ` Jan Kratochvil
@ 2012-09-21 17:19                   ` Andrew Burgess
  0 siblings, 0 replies; 21+ messages in thread
From: Andrew Burgess @ 2012-09-21 17:19 UTC (permalink / raw)
  To: gdb-patches

On 20/09/2012 2:28 PM, Jan Kratochvil wrote:
> 
> I am fine with this patch.

Committed.

Thanks,

Andrew


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

end of thread, other threads:[~2012-09-21 17:19 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-24 12:11 PATCH: error reading variable: value has been optimized out Andrew Burgess
2012-08-26 18:22 ` Jan Kratochvil
2012-08-27 15:46   ` Tom Tromey
2012-08-31  9:59     ` Eli Zaretskii
2012-09-03 15:07     ` Jan Kratochvil
2012-08-31 10:33   ` Andrew Burgess
2012-09-01  8:17     ` Eli Zaretskii
2012-09-03  8:32       ` Andrew Burgess
2012-09-03 11:24       ` Jan Kratochvil
2012-09-03 15:38         ` Eli Zaretskii
2012-09-03 15:17     ` Jan Kratochvil
2012-09-04 16:58       ` Andrew Burgess
2012-09-05 18:54         ` Jan Kratochvil
2012-09-12 17:30     ` Tom Tromey
2012-09-13 12:34       ` Andrew Burgess
2012-09-14 19:02         ` Tom Tromey
2012-09-14 21:39           ` Andrew Burgess
2012-09-17 16:57             ` Jan Kratochvil
2012-09-19 14:29               ` Andrew Burgess
2012-09-20 13:28                 ` Jan Kratochvil
2012-09-21 17:19                   ` Andrew Burgess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).