From 691a26f5ddd5f061ae8cd1be7c68212041da6ac2 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Thu, 4 Jul 2013 11:11:25 +0000 Subject: [PATCH] http://sourceware.org/ml/gdb-patches/2013-07/msg00059.html 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 | 10 + gdb/stack.c | 4 - gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S | 522 ++++++++++++++++++ gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c | 36 ++ .../gdb.dwarf2/dw2-reg-undefined.exp | 59 ++ gdb/value.c | 98 ++-- 7 files changed, 694 insertions(+), 41 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f9a2b30b6d..77db20096f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2013-07-04 Andrew Burgess + + * 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 * valops.c: Don't include "user-regs.h". diff --git a/gdb/stack.c b/gdb/stack.c index 08431bb19d..24629311d1 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -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))) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 063489cbf2..883826d4de 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-07-04 Andrew Burgess + + * 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 * 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 index 0000000000..ae071d9bf6 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.S @@ -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 . */ + + /* 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 index 0000000000..6a177c54a2 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.c @@ -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 . */ + +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 index 0000000000..7b7b4d19a0 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp @@ -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 . +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}" +} diff --git a/gdb/value.c b/gdb/value.c index 85475908e5..ce4b13a17a 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -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."));