http://sourceware.org/ml/gdb-patches/2013-07/msg00059.html
authorAndrew Burgess <aburgess@broadcom.com>
Thu, 4 Jul 2013 11:11:25 +0000 (11:11 +0000)
committerAndrew Burgess <aburgess@broadcom.com>
Thu, 4 Jul 2013 11:11:25 +0000 (11:11 +0000)
gdb/ChangeLog

        * stack.c (read_frame_arg): No longer fetch lazy values.
        * value.c (value_optimized_out): If the value is not already
        marked optimized out, and is lazy then fetch it.
        (value_primitive_field): Move optimized out check to later in the
        function, after we have loaded any lazy values.
        (value_fetch_lazy): Use optimized out flag directly rather than
        calling optimized_out method.

gdb/testsuite/ChangeLog

        * gdb.dwarf2/dw2-reg-undefined.exp: New file.
        * gdb.dwarf2/dw2-reg-undefined.c: Likewise.
        * gdb.dwarf2/dw2-reg-undefined.S: Likewise.

gdb/ChangeLog
gdb/stack.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp [new file with mode: 0644]
gdb/value.c

index f9a2b30..77db200 100644 (file)
@@ -1,5 +1,15 @@
 2013-07-04  Andrew Burgess  <aburgess@broadcom.com>
 
+       * stack.c (read_frame_arg): No longer fetch lazy values.
+       * value.c (value_optimized_out): If the value is not already
+       marked optimized out, and is lazy then fetch it.
+       (value_primitive_field): Move optimized out check to later in the
+       function, after we have loaded any lazy values.
+       (value_fetch_lazy): Use optimized out flag directly rather than
+       calling optimized_out method.
+
+2013-07-04  Andrew Burgess  <aburgess@broadcom.com>
+
        * valops.c: Don't include "user-regs.h".
        (value_fetch_lazy): Moved to value.c.
        * value.c: Include "user-regs.h".
index 08431bb..2462931 100644 (file)
@@ -359,10 +359,6 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
            {
              struct type *type = value_type (val);
 
-             if (!value_optimized_out (val) && value_lazy (val))
-               value_fetch_lazy (val);
-             if (!value_optimized_out (val) && value_lazy (entryval))
-               value_fetch_lazy (entryval);
              if (!value_optimized_out (val)
                  && value_available_contents_eq (val, 0, entryval, 0,
                                                  TYPE_LENGTH (type)))
index 063489c..883826d 100644 (file)
@@ -1,3 +1,9 @@
+2013-07-04  Andrew Burgess  <aburgess@broadcom.com>
+
+       * gdb.dwarf2/dw2-reg-undefined.exp: New file.
+       * gdb.dwarf2/dw2-reg-undefined.c: Likewise.
+       * gdb.dwarf2/dw2-reg-undefined.S: Likewise.
+
 2013-07-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * gdb.base/break-on-linker-gcd-function.exp: Replace
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S
new file mode 100644 (file)
index 0000000..ae071d9
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+   Copyright 2013 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/>.  */
+
+       /* The FDE entry for "stop_frame" in the .debug_frame section has
+       been hand modified to mark a set of registers as undefined.
+       Otherwise this file is as generated by gcc 4.7.2 for x86_64.  */
+       .file   "dw2-reg-undefined.c"
+       .text
+.Ltext0:
+       .globl  stop_frame
+       .type   stop_frame, @function
+stop_frame:
+.LFB0:
+       .file 1 "dw2-reg-undefined.c"
+       .loc 1 19 0
+       pushq   %rbp
+.LCFI0:
+       movq    %rsp, %rbp
+.LCFI1:
+       .loc 1 22 0
+       popq    %rbp
+.LCFI2:
+       ret
+.LFE0:
+       .size   stop_frame, .-stop_frame
+       .globl  first_frame
+       .type   first_frame, @function
+first_frame:
+.LFB1:
+       .loc 1 26 0
+       pushq   %rbp
+.LCFI3:
+       movq    %rsp, %rbp
+.LCFI4:
+       .loc 1 27 0
+       movl    $0, %eax
+       call    stop_frame
+       .loc 1 28 0
+       popq    %rbp
+.LCFI5:
+       ret
+.LFE1:
+       .size   first_frame, .-first_frame
+       .globl  main
+       .type   main, @function
+main:
+.LFB2:
+       .loc 1 32 0
+       pushq   %rbp
+.LCFI6:
+       movq    %rsp, %rbp
+.LCFI7:
+       .loc 1 33 0
+       movl    $0, %eax
+       call    first_frame
+       .loc 1 35 0
+       movl    $0, %eax
+       .loc 1 36 0
+       popq    %rbp
+.LCFI8:
+       ret
+.LFE2:
+       .size   main, .-main
+       .section        .debug_frame,"",@progbits
+.Lframe0:
+       .long   .LECIE0-.LSCIE0
+.LSCIE0:
+       .long   0xffffffff
+       .byte   0x1
+       .string ""
+       .uleb128 0x1
+       .sleb128 -8
+       .byte   0x10
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .byte   0x90
+       .uleb128 0x1
+       .align 8
+.LECIE0:
+        /* This FDE entry, for stop_frame was modified to mark
+           registers 0 -> 6 as being undefined.  */
+.LSFDE0:
+       .long   .LEFDE0-.LASFDE0
+.LASFDE0:
+       .long   .Lframe0
+       .quad   .LFB0
+       .quad   .LFE0-.LFB0
+
+               /* START OF NEW CONTENT.  */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x0                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x1                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x2                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x3                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x4                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x5                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x6                    /*   ULEB128 register */
+        .byte   0x7                     /* DW_CFA_undefined */
+        .uleb128 0x7                    /*   ULEB128 register */
+               /* END OF NEW CONTENT.  */
+
+       .byte   0x4
+       .long   .LCFI0-.LFB0
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI1-.LCFI0
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI2-.LCFI1
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE0:
+.LSFDE2:
+       .long   .LEFDE2-.LASFDE2
+.LASFDE2:
+       .long   .Lframe0
+       .quad   .LFB1
+       .quad   .LFE1-.LFB1
+       .byte   0x4
+       .long   .LCFI3-.LFB1
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI4-.LCFI3
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI5-.LCFI4
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE2:
+.LSFDE4:
+       .long   .LEFDE4-.LASFDE4
+.LASFDE4:
+       .long   .Lframe0
+       .quad   .LFB2
+       .quad   .LFE2-.LFB2
+       .byte   0x4
+       .long   .LCFI6-.LFB2
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI7-.LCFI6
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI8-.LCFI7
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE4:
+       .section        .eh_frame,"a",@progbits
+.Lframe1:
+       .long   .LECIE1-.LSCIE1
+.LSCIE1:
+       .long   0
+       .byte   0x1
+       .string "zR"
+       .uleb128 0x1
+       .sleb128 -8
+       .byte   0x10
+       .uleb128 0x1
+       .byte   0x3
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .byte   0x90
+       .uleb128 0x1
+       .align 8
+.LECIE1:
+.LSFDE7:
+       .long   .LEFDE7-.LASFDE7
+.LASFDE7:
+       .long   .LASFDE7-.Lframe1
+       .long   .LFB0
+       .long   .LFE0-.LFB0
+       .uleb128 0
+       .byte   0x4
+       .long   .LCFI0-.LFB0
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI1-.LCFI0
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI2-.LCFI1
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE7:
+.LSFDE9:
+       .long   .LEFDE9-.LASFDE9
+.LASFDE9:
+       .long   .LASFDE9-.Lframe1
+       .long   .LFB1
+       .long   .LFE1-.LFB1
+       .uleb128 0
+       .byte   0x4
+       .long   .LCFI3-.LFB1
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI4-.LCFI3
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI5-.LCFI4
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE9:
+.LSFDE11:
+       .long   .LEFDE11-.LASFDE11
+.LASFDE11:
+       .long   .LASFDE11-.Lframe1
+       .long   .LFB2
+       .long   .LFE2-.LFB2
+       .uleb128 0
+       .byte   0x4
+       .long   .LCFI6-.LFB2
+       .byte   0xe
+       .uleb128 0x10
+       .byte   0x86
+       .uleb128 0x2
+       .byte   0x4
+       .long   .LCFI7-.LCFI6
+       .byte   0xd
+       .uleb128 0x6
+       .byte   0x4
+       .long   .LCFI8-.LCFI7
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .align 8
+.LEFDE11:
+       .text
+.Letext0:
+       .section        .debug_info,"",@progbits
+.Ldebug_info0:
+       .long   0x8c
+       .value  0x2
+       .long   .Ldebug_abbrev0
+       .byte   0x8
+       .uleb128 0x1
+       .long   .LASF2
+       .byte   0x1
+       .long   .LASF3
+       .long   .LASF4
+       .quad   .Ltext0
+       .quad   .Letext0
+       .long   .Ldebug_line0
+       .uleb128 0x2
+       .byte   0x1
+       .long   .LASF0
+       .byte   0x1
+       .byte   0x12
+       .quad   .LFB0
+       .quad   .LFE0
+       .long   .LLST0
+       .byte   0x1
+       .uleb128 0x3
+       .byte   0x1
+       .long   .LASF1
+       .byte   0x1
+       .byte   0x19
+       .quad   .LFB1
+       .quad   .LFE1
+       .long   .LLST1
+       .byte   0x1
+       .uleb128 0x4
+       .byte   0x1
+       .long   .LASF5
+       .byte   0x1
+       .byte   0x1f
+       .long   0x88
+       .quad   .LFB2
+       .quad   .LFE2
+       .long   .LLST2
+       .byte   0x1
+       .uleb128 0x5
+       .byte   0x4
+       .byte   0x5
+       .string "int"
+       .byte   0
+       .section        .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+       .uleb128 0x1
+       .uleb128 0x11
+       .byte   0x1
+       .uleb128 0x25
+       .uleb128 0xe
+       .uleb128 0x13
+       .uleb128 0xb
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x1b
+       .uleb128 0xe
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x10
+       .uleb128 0x6
+       .byte   0
+       .byte   0
+       .uleb128 0x2
+       .uleb128 0x2e
+       .byte   0
+       .uleb128 0x3f
+       .uleb128 0xc
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x40
+       .uleb128 0x6
+       .uleb128 0x2117
+       .uleb128 0xc
+       .byte   0
+       .byte   0
+       .uleb128 0x3
+       .uleb128 0x2e
+       .byte   0
+       .uleb128 0x3f
+       .uleb128 0xc
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x40
+       .uleb128 0x6
+       .uleb128 0x2116
+       .uleb128 0xc
+       .byte   0
+       .byte   0
+       .uleb128 0x4
+       .uleb128 0x2e
+       .byte   0
+       .uleb128 0x3f
+       .uleb128 0xc
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x49
+       .uleb128 0x13
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x40
+       .uleb128 0x6
+       .uleb128 0x2116
+       .uleb128 0xc
+       .byte   0
+       .byte   0
+       .uleb128 0x5
+       .uleb128 0x24
+       .byte   0
+       .uleb128 0xb
+       .uleb128 0xb
+       .uleb128 0x3e
+       .uleb128 0xb
+       .uleb128 0x3
+       .uleb128 0x8
+       .byte   0
+       .byte   0
+       .byte   0
+       .section        .debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+       .quad   .LFB0-.Ltext0
+       .quad   .LCFI0-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   .LCFI0-.Ltext0
+       .quad   .LCFI1-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 16
+       .quad   .LCFI1-.Ltext0
+       .quad   .LCFI2-.Ltext0
+       .value  0x2
+       .byte   0x76
+       .sleb128 16
+       .quad   .LCFI2-.Ltext0
+       .quad   .LFE0-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   0
+       .quad   0
+.LLST1:
+       .quad   .LFB1-.Ltext0
+       .quad   .LCFI3-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   .LCFI3-.Ltext0
+       .quad   .LCFI4-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 16
+       .quad   .LCFI4-.Ltext0
+       .quad   .LCFI5-.Ltext0
+       .value  0x2
+       .byte   0x76
+       .sleb128 16
+       .quad   .LCFI5-.Ltext0
+       .quad   .LFE1-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   0
+       .quad   0
+.LLST2:
+       .quad   .LFB2-.Ltext0
+       .quad   .LCFI6-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   .LCFI6-.Ltext0
+       .quad   .LCFI7-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 16
+       .quad   .LCFI7-.Ltext0
+       .quad   .LCFI8-.Ltext0
+       .value  0x2
+       .byte   0x76
+       .sleb128 16
+       .quad   .LCFI8-.Ltext0
+       .quad   .LFE2-.Ltext0
+       .value  0x2
+       .byte   0x77
+       .sleb128 8
+       .quad   0
+       .quad   0
+       .section        .debug_aranges,"",@progbits
+       .long   0x2c
+       .value  0x2
+       .long   .Ldebug_info0
+       .byte   0x8
+       .byte   0
+       .value  0
+       .value  0
+       .quad   .Ltext0
+       .quad   .Letext0-.Ltext0
+       .quad   0
+       .quad   0
+       .section        .debug_line,"",@progbits
+.Ldebug_line0:
+       .section        .debug_str,"MS",@progbits,1
+.LASF0:
+       .string "stop_frame"
+.LASF3:
+       .string "dw2-reg-undefined.c"
+.LASF2:
+       .string "GNU C 4.7.2"
+.LASF1:
+       .string "first_frame"
+.LASF5:
+       .string "main"
+.LASF4:
+       .string "/home/username/src/gdb/testsuite/gdb.dwarf2"
+       .ident  "GCC: (GNU) 4.7.2"
+       .section        .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c
new file mode 100644 (file)
index 0000000..6a177c5
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+   Copyright 2013 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/>.  */
+
+void
+stop_frame ()
+{
+  /* The debug information for this frame is modified in the accompanying
+     .S file, to mark a set of registers as being undefined.  */
+}
+
+void
+first_frame ()
+{
+  stop_frame ();
+}
+
+int
+main ()
+{
+  first_frame ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
new file mode 100644 (file)
index 0000000..7b7b4d1
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright 2013 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
+
+# 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
+}
+
+standard_testfile .S
+
+if { [prepare_for_testing $testfile.exp $testfile $srcfile {nodebug}] } {
+    return -1
+}
+
+if ![runto stop_frame] {
+    perror "Failed to stop in stop_frame"
+    return -1
+}
+
+gdb_test "bt" "#0  (0x\[0-9a-f\]+ in )?stop_frame \[^\r\n\]*\r\n#1  \[^\r\n\]*first_frame \[^\r\n\]*\r\n#2  \[^\r\n\]*main\[^\r\n\]*" \
+    "backtrace from stop_frame"
+
+set value_pattern "0x\[0-9a-f\]+\\s+\[0-9\]+"
+set opt_out_pattern "\\*value not available\\*"
+
+for {set f 0} {$f < 3} {incr f} {
+    if {${f} == 0} {
+       set pattern_rax_rbx_rcx ${value_pattern}
+       set pattern_r8_r9 ${value_pattern}
+    } else {
+       set pattern_rax_rbx_rcx ${opt_out_pattern}
+       set pattern_r8_r9 ${value_pattern}
+    }
+
+    # Select frame.
+    gdb_test "frame ${f}" "#${f}.*" "Switch to frame ${f}"
+
+    # Display register values.
+    gdb_test "info registers rax rbx rcx r8 r9" "rax\\s+${pattern_rax_rbx_rcx}\\s*\r\nrbx\\s+${pattern_rax_rbx_rcx}\\s*\r\nrcx\\s+${pattern_rax_rbx_rcx}\\s*\r\nr8\\s+${pattern_r8_r9}\\s*\r\nr9\\s+${pattern_r8_r9}\\s*" \
+       "Check values of rax, rbx, rcx, r8, r9 in frame ${f}"
+}
index 8547590..ce4b13a 100644 (file)
@@ -1054,6 +1054,11 @@ value_contents_equal (struct value *val1, struct value *val2)
 int
 value_optimized_out (struct value *value)
 {
+  /* We can only know if a value is optimized out once we have tried to
+     fetch it.  */
+  if (!value->optimized_out && value->lazy)
+    value_fetch_lazy (value);
+
   return value->optimized_out;
 }
 
@@ -2628,9 +2633,7 @@ value_primitive_field (struct value *arg1, int offset,
      description correctly.  */
   check_typedef (type);
 
-  if (value_optimized_out (arg1))
-    v = allocate_optimized_out_value (type);
-  else if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
+  if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
     {
       /* Handle packed fields.
 
@@ -2644,19 +2647,24 @@ value_primitive_field (struct value *arg1, int offset,
       int bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
       int container_bitsize = TYPE_LENGTH (type) * 8;
 
-      v = allocate_value_lazy (type);
-      v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
-      if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
-         && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
-       v->bitpos = bitpos % container_bitsize;
+      if (arg1->optimized_out)
+       v = allocate_optimized_out_value (type);
       else
-       v->bitpos = bitpos % 8;
-      v->offset = (value_embedded_offset (arg1)
-                  + offset
-                  + (bitpos - v->bitpos) / 8);
-      set_value_parent (v, arg1);
-      if (!value_lazy (arg1))
-       value_fetch_lazy (v);
+       {
+         v = allocate_value_lazy (type);
+         v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+         if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
+             && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
+           v->bitpos = bitpos % container_bitsize;
+         else
+           v->bitpos = bitpos % 8;
+         v->offset = (value_embedded_offset (arg1)
+                      + offset
+                      + (bitpos - v->bitpos) / 8);
+         set_value_parent (v, arg1);
+         if (!value_lazy (arg1))
+           value_fetch_lazy (v);
+       }
     }
   else if (fieldno < TYPE_N_BASECLASSES (arg_type))
     {
@@ -2669,29 +2677,37 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
        value_fetch_lazy (arg1);
 
-      /* We special case virtual inheritance here because this
-        requires access to the contents, which we would rather avoid
-        for references to ordinary fields of unavailable values.  */
-      if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
-       boffset = baseclass_offset (arg_type, fieldno,
-                                   value_contents (arg1),
-                                   value_embedded_offset (arg1),
-                                   value_address (arg1),
-                                   arg1);
-      else
-       boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
-
-      if (value_lazy (arg1))
-       v = allocate_value_lazy (value_enclosing_type (arg1));
+      /* The optimized_out flag is only set correctly once a lazy value is
+         loaded, having just loaded some lazy values we should check the
+         optimized out case now.  */
+      if (arg1->optimized_out)
+       v = allocate_optimized_out_value (type);
       else
        {
-         v = allocate_value (value_enclosing_type (arg1));
-         value_contents_copy_raw (v, 0, arg1, 0,
-                                  TYPE_LENGTH (value_enclosing_type (arg1)));
+         /* We special case virtual inheritance here because this
+            requires access to the contents, which we would rather avoid
+            for references to ordinary fields of unavailable values.  */
+         if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
+           boffset = baseclass_offset (arg_type, fieldno,
+                                       value_contents (arg1),
+                                       value_embedded_offset (arg1),
+                                       value_address (arg1),
+                                       arg1);
+         else
+           boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+
+         if (value_lazy (arg1))
+           v = allocate_value_lazy (value_enclosing_type (arg1));
+         else
+           {
+             v = allocate_value (value_enclosing_type (arg1));
+             value_contents_copy_raw (v, 0, arg1, 0,
+                                      TYPE_LENGTH (value_enclosing_type (arg1)));
+           }
+         v->type = type;
+         v->offset = value_offset (arg1);
+         v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
        }
-      v->type = type;
-      v->offset = value_offset (arg1);
-      v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
     }
   else
     {
@@ -2702,7 +2718,12 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
        value_fetch_lazy (arg1);
 
-      if (value_lazy (arg1))
+      /* The optimized_out flag is only set correctly once a lazy value is
+         loaded, having just loaded some lazy values we should check for
+         the optimized out case now.  */
+      if (arg1->optimized_out)
+       v = allocate_optimized_out_value (type);
+      else if (value_lazy (arg1))
        v = allocate_value_lazy (type);
       else
        {
@@ -3526,7 +3547,10 @@ value_fetch_lazy (struct value *val)
   else if (VALUE_LVAL (val) == lval_computed
           && value_computed_funcs (val)->read != NULL)
     value_computed_funcs (val)->read (val);
-  else if (value_optimized_out (val))
+  /* Don't call value_optimized_out on val, doing so would result in a
+     recursive call back to value_fetch_lazy, instead check the
+     optimized_out flag directly.  */
+  else if (val->optimized_out)
     /* Keep it optimized out.  */;
   else
     internal_error (__FILE__, __LINE__, _("Unexpected lazy value type."));