http://sourceware.org/ml/gdb-patches/2012-08/msg00715.html
authorAndrew Burgess <aburgess@broadcom.com>
Fri, 21 Sep 2012 17:17:23 +0000 (17:17 +0000)
committerAndrew Burgess <aburgess@broadcom.com>
Fri, 21 Sep 2012 17:17:23 +0000 (17:17 +0000)
gdb/ChangeLog

        * 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

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

gdb/ChangeLog
gdb/findvar.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/dw2-op-out-param.S [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp [new file with mode: 0644]

index 2fb946d9d4b33fa76017621476763e5c582fd07a..ae08dd46f9b183aa8f38983c7d277760e8ab9918 100644 (file)
@@ -1,3 +1,8 @@
+2012-09-21  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.
+
 2012-09-21  Andreas Schwab  <schwab@linux-m68k.org>
 
        * python/python.c (finalize_python): Only define if HAVE_PYTHON.
index 66bcebee3486e8e4bd726b7431dfeaadcaf303f0..ec9dde7810d2a73cafec1d1a91694dd427df4067 100644 (file)
@@ -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)
index e147df0230165ca052e6e3b27036fbcd27dfbf67..36f1c726d0ca33fe59e812ecb55c06c547ea4e73 100644 (file)
@@ -1,3 +1,8 @@
+2012-09-21  Andrew Burgess  <aburgess@broadcom.com>
+
+       * gdb.dwarf2/dw2-op-out-param.S: New file.
+       * gdb.dwarf2/dw2-op-out-param.exp: New file.
+
 2012-09-21  Yao Qi  <yao@codesourcery.com>
 
        * gdb.mi/mi2-cli.exp: Remove redundant '\'.
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 (file)
index 0000000..629a819
--- /dev/null
@@ -0,0 +1,677 @@
+/* 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 (file)
index 0000000..76a000e
--- /dev/null
@@ -0,0 +1,85 @@
+# 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 "symtab/14604" $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 "symtab/14605" $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 "symtab/14605" $test
+    }
+}