1# Copyright 2016-2020 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This test ensures that with "set print object on", -var-create will 17# return "<optimized out>" for an optimized out pointer to structure, 18# rather than attempting to dereference the pointer to determine its 19# actual type (instead of its declared type). We want to test that GDB 20# can display such a pointer without throwing an error, while also 21# ensuring that any attempt to dereference the pointer *will* throw an 22# error. 23 24load_lib dwarf.exp 25 26# This test can only be run on targets which support DWARF-2 and use gas. 27if {![dwarf2_support]} { 28 return 0 29} 30 31standard_testfile dw2-opt-structptr.c dw2-opt-structptr-dw.S 32 33# Generate a test program with dwarf information showing the variable 34# 'ptr', a pointer-to-struct, as optimized out. The dwarf will also 35# describe the structure as have a scalar, array, and pointer-to-struct 36# members. 37 38proc build_test_program {} { 39 global testfile srcfile srcfile2 40 41 # Make some DWARF for the test. 42 set asm_file [standard_output_file $srcfile2] 43 Dwarf::assemble $asm_file { 44 45 # Creating a CU with 4-byte addresses lets this test link on 46 # both 32- and 64-bit machines. 47 cu { addr_size 4 } { 48 49 DW_TAG_compile_unit { 50 {DW_AT_language @DW_LANG_C99} 51 {DW_AT_name dw2-opt-structptr.c} 52 {DW_AT_comp_dir /tmp} 53 } { 54 declare_labels int_label struct_label pointer_label \ 55 array_label 56 57 int_label: DW_TAG_base_type { 58 {DW_AT_byte_size 4 DW_FORM_sdata} 59 {DW_AT_encoding @DW_ATE_signed} 60 {DW_AT_name integer} 61 } 62 63 array_label: DW_TAG_array_type { 64 {DW_AT_name foo__array_type} 65 {DW_AT_type :$int_label} 66 } { 67 DW_TAG_subrange_type { 68 {DW_AT_type :$int_label} 69 {DW_AT_lower_bound 0 DW_FORM_data1} 70 {DW_AT_upper_bound 127 DW_FORM_data1} 71 } 72 } 73 74 struct_label: DW_TAG_structure_type { 75 {DW_AT_name "foo"} 76 {DW_AT_byte_size 12 DW_FORM_sdata} 77 } { 78 member { 79 {name a} 80 {type :$int_label} 81 {data_member_location 0 data1} 82 } 83 member { 84 {name x} 85 {type :$array_label} 86 {data_member_location 4 data1} 87 } 88 member { 89 {name y} 90 {type :$pointer_label} 91 {data_member_location 8 data1} 92 } 93 } 94 95 pointer_label: DW_TAG_pointer_type { 96 {DW_AT_byte_size 4 DW_FORM_sdata} 97 {DW_AT_type :$struct_label} 98 } 99 100 DW_TAG_subprogram { 101 {DW_AT_name func01} 102 {DW_AT_type :$int_label} 103 {external 1 flag} 104 {MACRO_AT_func {func01}} 105 } { 106 DW_TAG_variable { 107 {DW_AT_name ptr} 108 {DW_AT_type :$pointer_label} 109 {DW_AT_location {} DW_FORM_block1} 110 } 111 } 112 113 DW_TAG_subprogram { 114 {DW_AT_name main} 115 {DW_AT_type :$int_label} 116 {external 1 flag} 117 {MACRO_AT_func {main}} 118 } { 119 } 120 } 121 } 122 } 123 124 set sources "$srcfile $asm_file" 125 if {[build_executable $testfile.exp $testfile $sources {nodebug}]} { 126 untested "failed to compile" 127 return -1 128 } 129} 130 131# Test access to an optimized-out pointer-to-struct using the 132# console interpreter. 133 134proc do_console_test {} { 135 global binfile 136 137 clean_restart $binfile 138 139 with_test_prefix "console" { 140 gdb_test_no_output "set print object on" 141 142 if {![runto_main]} { 143 return -1 144 } 145 146 if {![runto func01]} { 147 return -1 148 } 149 150 gdb_test "info addr ptr" "Symbol \"ptr\" is optimized out." 151 152 gdb_test "print ptr" "<optimized out>" 153 154 gdb_test "print *ptr" "value has been optimized out" 155 156 gdb_test "print ptr->a" "value has been optimized out" 157 158 gdb_test "print ptr->x" "value has been optimized out" 159 160 gdb_test "print ptr->y" "value has been optimized out" 161 } 162} 163 164# Test access to an optimized-out pointer-to-struct using the 165# MI interpreter. 166 167proc do_mi_test {} { 168 169 load_lib mi-support.exp 170 set MIFLAGS "-i=mi" 171 172 global mi_gdb_prompt 173 global srcdir 174 global subdir 175 global binfile 176 177 with_test_prefix "mi" { 178 gdb_exit 179 if {[mi_gdb_start]} { 180 return -1 181 } 182 183 mi_delete_breakpoints 184 mi_gdb_reinitialize_dir $srcdir/$subdir 185 mi_gdb_load $binfile 186 187 # This causes GDB to dereference a pointer-to-structure when doing 188 # -var-create. 189 mi_gdb_test "-gdb-set print object on" ".*" "set print object on" 190 191 mi_gdb_test "-break-insert main" ".*" "insert breakpoint main" 192 mi_gdb_test "-break-insert func01" ".*" "insert breakpoint func01" 193 194 # Run to main. Use an explicit expect here since the limited 195 # debug info will result in output that isn't handled by the 196 # MI test utilities. 197 set test "run to main" 198 mi_run_cmd 199 gdb_expect { 200 -re "\\*stopped,reason=\"breakpoint-hit\".*func=\"main\".*$mi_gdb_prompt$" { 201 pass "$test" 202 } 203 timeout { 204 fail "$test (timeout)" 205 } 206 } 207 208 # Run to func01. Use an explicit expect here as above. 209 set test "continue to func01" 210 mi_send_resuming_command "exec-continue" "$test" 211 gdb_expect { 212 -re "\\*stopped,reason=\"breakpoint-hit\".*func=\"func01\".*$mi_gdb_prompt$" { 213 pass "$test" 214 } 215 timeout { 216 fail "$test (timeout)" 217 } 218 } 219 220 # Test that -var-create for 'ptr' is successful. 221 mi_create_varobj "var1" "ptr" "create varobj for ptr" 222 223 # Test that -var-list-children of 'ptr' is successful. 224 mi_list_varobj_children "var1" { \ 225 {var1.a a 0 integer} \ 226 {var1.x x 128 foo__array_type} \ 227 {var1.y y 3 "struct foo \\*"} \ 228 } "get children of var1 (ptr)" 229 230 # Test that dereferencing 'ptr' will throw an error. 231 mi_gdb_test "-var-create var2 * &((ptr)->a)" \ 232 "\\^error,msg=\"value has been optimized out\"" \ 233 "throw error, dereference ptr to access integer member " 234 235 # Test that dereferencing 'ptr' will throw an error. 236 mi_gdb_test "-var-create var3 * &((ptr)->x)" \ 237 "\\^error,msg=\"value has been optimized out\"" \ 238 "throw error, dereference ptr to access array member " 239 240 # Test that dereferencing 'ptr' will throw an error. 241 mi_gdb_test "-var-create var4 * &((ptr)->y)" \ 242 "\\^error,msg=\"value has been optimized out\"" \ 243 "throw error, dereference ptr to access pointer member " 244 } 245} 246 247build_test_program 248do_console_test 249do_mi_test 250