1# Copyright 2016-2019 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 global srcdir subdir srcfile 45 46 # Creating a CU with 4-byte addresses lets this test link on 47 # both 32- and 64-bit machines. 48 cu { addr_size 4 } { 49 50 DW_TAG_compile_unit { 51 {DW_AT_language @DW_LANG_C99} 52 {DW_AT_name dw2-opt-structptr.c} 53 {DW_AT_comp_dir /tmp} 54 } { 55 declare_labels int_label struct_label pointer_label \ 56 array_label 57 58 int_label: DW_TAG_base_type { 59 {DW_AT_byte_size 4 DW_FORM_sdata} 60 {DW_AT_encoding @DW_ATE_signed} 61 {DW_AT_name integer} 62 } 63 64 array_label: DW_TAG_array_type { 65 {DW_AT_name foo__array_type} 66 {DW_AT_type :$int_label} 67 } { 68 DW_TAG_subrange_type { 69 {DW_AT_type :$int_label} 70 {DW_AT_lower_bound 0 DW_FORM_data1} 71 {DW_AT_upper_bound 127 DW_FORM_data1} 72 } 73 } 74 75 struct_label: DW_TAG_structure_type { 76 {DW_AT_name "foo"} 77 {DW_AT_byte_size 12 DW_FORM_sdata} 78 } { 79 member { 80 {name a} 81 {type :$int_label} 82 {data_member_location 0 data1} 83 } 84 member { 85 {name x} 86 {type :$array_label} 87 {data_member_location 4 data1} 88 } 89 member { 90 {name y} 91 {type :$pointer_label} 92 {data_member_location 8 data1} 93 } 94 } 95 96 pointer_label: DW_TAG_pointer_type { 97 {DW_AT_byte_size 4 DW_FORM_sdata} 98 {DW_AT_type :$struct_label} 99 } 100 101 DW_TAG_subprogram { 102 {DW_AT_name func01} 103 {DW_AT_type :$int_label} 104 {external 1 flag} 105 {MACRO_AT_func {func01 ${srcdir}/${subdir}/${srcfile}}} 106 } { 107 DW_TAG_variable { 108 {DW_AT_name ptr} 109 {DW_AT_type :$pointer_label} 110 {DW_AT_location {} DW_FORM_block1} 111 } 112 } 113 114 DW_TAG_subprogram { 115 {DW_AT_name main} 116 {DW_AT_type :$int_label} 117 {external 1 flag} 118 {MACRO_AT_func {main ${srcdir}/${subdir}/${srcfile}}} 119 } { 120 } 121 } 122 } 123 } 124 125 set sources "$srcfile $asm_file" 126 if {[build_executable $testfile.exp $testfile $sources {nodebug}]} { 127 untested "failed to compile" 128 return -1 129 } 130} 131 132# Test access to an optimized-out pointer-to-struct using the 133# console interpreter. 134 135proc do_console_test {} { 136 global binfile 137 138 clean_restart $binfile 139 140 with_test_prefix "console" { 141 gdb_test_no_output "set print object on" 142 143 if {![runto_main]} { 144 return -1 145 } 146 147 if {![runto func01]} { 148 return -1 149 } 150 151 gdb_test "info addr ptr" "Symbol \"ptr\" is optimized out." 152 153 gdb_test "print ptr" "<optimized out>" 154 155 gdb_test "print *ptr" "value has been optimized out" 156 157 gdb_test "print ptr->a" "value has been optimized out" 158 159 gdb_test "print ptr->x" "value has been optimized out" 160 161 gdb_test "print ptr->y" "value has been optimized out" 162 } 163} 164 165# Test access to an optimized-out pointer-to-struct using the 166# MI interpreter. 167 168proc do_mi_test {} { 169 170 load_lib mi-support.exp 171 set MIFLAGS "-i=mi" 172 173 global mi_gdb_prompt 174 global srcdir 175 global subdir 176 global binfile 177 178 with_test_prefix "mi" { 179 gdb_exit 180 if {[mi_gdb_start]} { 181 return -1 182 } 183 184 mi_delete_breakpoints 185 mi_gdb_reinitialize_dir $srcdir/$subdir 186 mi_gdb_load $binfile 187 188 # This causes GDB to dereference a pointer-to-structure when doing 189 # -var-create. 190 mi_gdb_test "-gdb-set print object on" ".*" "set print object on" 191 192 mi_gdb_test "-break-insert main" ".*" "insert breakpoint main" 193 mi_gdb_test "-break-insert func01" ".*" "insert breakpoint func01" 194 195 # Run to main. Use an explicit expect here since the limited 196 # debug info will result in output that isn't handled by the 197 # MI test utilities. 198 set test "run to main" 199 mi_run_cmd 200 gdb_expect { 201 -re "\\*stopped,reason=\"breakpoint-hit\".*func=\"main\".*$mi_gdb_prompt$" { 202 pass "$test" 203 } 204 timeout { 205 fail "$test (timeout)" 206 } 207 } 208 209 # Run to func01. Use an explicit expect here as above. 210 set test "continue to func01" 211 mi_send_resuming_command "exec-continue" "$test" 212 gdb_expect { 213 -re "\\*stopped,reason=\"breakpoint-hit\".*func=\"func01\".*$mi_gdb_prompt$" { 214 pass "$test" 215 } 216 timeout { 217 fail "$test (timeout)" 218 } 219 } 220 221 # Test that -var-create for 'ptr' is successful. 222 mi_create_varobj "var1" "ptr" "create varobj for ptr" 223 224 # Test that -var-list-children of 'ptr' is successful. 225 mi_list_varobj_children "var1" { \ 226 {var1.a a 0 integer} \ 227 {var1.x x 128 foo__array_type} \ 228 {var1.y y 3 "struct foo \\*"} \ 229 } "get children of var1 (ptr)" 230 231 # Test that dereferencing 'ptr' will throw an error. 232 mi_gdb_test "-var-create var2 * &((ptr)->a)" \ 233 "\\^error,msg=\"value has been optimized out\"" \ 234 "throw error, dereference ptr to access integer member " 235 236 # Test that dereferencing 'ptr' will throw an error. 237 mi_gdb_test "-var-create var3 * &((ptr)->x)" \ 238 "\\^error,msg=\"value has been optimized out\"" \ 239 "throw error, dereference ptr to access array member " 240 241 # Test that dereferencing 'ptr' will throw an error. 242 mi_gdb_test "-var-create var4 * &((ptr)->y)" \ 243 "\\^error,msg=\"value has been optimized out\"" \ 244 "throw error, dereference ptr to access pointer member " 245 } 246} 247 248build_test_program 249do_console_test 250do_mi_test 251