1# Copyright 2017-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# Test reading/writing variables with non-trivial DWARF locations. In 17# particular the test uses register- and memory locations as well as 18# composite locations with register- and memory pieces. 19 20load_lib dwarf.exp 21 22# This test can only be run on targets which support DWARF-2 and use gas. 23if {![dwarf2_support]} { 24 return 0 25} 26 27# Choose suitable integer registers for the test. 28 29set dwarf_regnum {0 1} 30 31if { [is_aarch64_target] } { 32 set regname {x0 x1} 33} elseif { [is_aarch32_target] 34 || [istarget "s390*-*-*" ] 35 || [istarget "powerpc*-*-*"] 36 || [istarget "rs6000*-*-aix*"] } { 37 set regname {r0 r1} 38} elseif { [is_x86_like_target] } { 39 set regname {eax ecx} 40} elseif { [is_amd64_regs_target] } { 41 set regname {rax rdx} 42} else { 43 verbose "Skipping tests for accessing DWARF-described variables." 44 return 45} 46 47standard_testfile .c ${gdb_test_file_name}-dw.S 48 49# Make some DWARF for the test. 50 51set asm_file [standard_output_file $srcfile2] 52Dwarf::assemble $asm_file { 53 global dwarf_regnum regname 54 55 set buf_var [gdb_target_symbol buf] 56 57 cu {} { 58 DW_TAG_compile_unit { 59 {DW_AT_name var-pieces-dw.c} 60 {DW_AT_comp_dir /tmp} 61 } { 62 declare_labels char_type_label 63 declare_labels int_type_label short_type_label 64 declare_labels array_a8_label struct_s_label struct_t_label 65 declare_labels struct_st_label 66 67 # char 68 char_type_label: base_type { 69 {name "char"} 70 {encoding @DW_ATE_unsigned_char} 71 {byte_size 1 DW_FORM_sdata} 72 } 73 74 # int 75 int_type_label: base_type { 76 {name "int"} 77 {encoding @DW_ATE_signed} 78 {byte_size 4 DW_FORM_sdata} 79 } 80 81 # char [8] 82 array_a8_label: array_type { 83 {type :$char_type_label} 84 } { 85 subrange_type { 86 {type :$int_type_label} 87 {upper_bound 7 DW_FORM_udata} 88 } 89 } 90 91 # struct s { char a, b, c, d; }; 92 struct_s_label: structure_type { 93 {name "s"} 94 {byte_size 4 DW_FORM_sdata} 95 } { 96 member { 97 {name "a"} 98 {type :$char_type_label} 99 {data_member_location 0 DW_FORM_udata} 100 } 101 member { 102 {name "b"} 103 {type :$char_type_label} 104 {data_member_location 1 DW_FORM_udata} 105 } 106 member { 107 {name "c"} 108 {type :$char_type_label} 109 {data_member_location 2 DW_FORM_udata} 110 } 111 member { 112 {name "d"} 113 {type :$char_type_label} 114 {data_member_location 3 DW_FORM_udata} 115 } 116 } 117 118 # struct t { int u, x:9, y:13, z:10; }; 119 struct_t_label: structure_type { 120 {name "t"} 121 {byte_size 8 DW_FORM_sdata} 122 } { 123 member { 124 {name "u"} 125 {type :$int_type_label} 126 } 127 member { 128 {name "x"} 129 {type :$int_type_label} 130 {data_member_location 4 DW_FORM_udata} 131 {bit_size 9 DW_FORM_udata} 132 } 133 member { 134 {name "y"} 135 {type :$int_type_label} 136 {data_bit_offset 41 DW_FORM_udata} 137 {bit_size 13 DW_FORM_udata} 138 } 139 member { 140 {name "z"} 141 {type :$int_type_label} 142 {data_bit_offset 54 DW_FORM_udata} 143 {bit_size 10 DW_FORM_udata} 144 } 145 } 146 147 # struct st { struct s s; struct t t; }; 148 struct_st_label: structure_type { 149 {name "st"} 150 {byte_size 12 DW_FORM_udata} 151 } { 152 member { 153 {name "s"} 154 {type :$struct_s_label} 155 } 156 member { 157 {name "t"} 158 {type :$struct_t_label} 159 {data_member_location 4 DW_FORM_udata} 160 } 161 } 162 163 DW_TAG_subprogram { 164 {MACRO_AT_func { main }} 165 {DW_AT_external 1 flag} 166 } { 167 # Simple memory location. 168 DW_TAG_variable { 169 {name "a"} 170 {type :$array_a8_label} 171 {location { 172 addr $buf_var 173 } SPECIAL_expr} 174 } 175 # Memory pieces: two bytes from &buf[2], and two bytes 176 # from &buf[0]. 177 DW_TAG_variable { 178 {name "s1"} 179 {type :$struct_s_label} 180 {location { 181 addr $buf_var 182 plus_uconst 2 183 piece 2 184 addr $buf_var 185 piece 2 186 } SPECIAL_expr} 187 } 188 # Register- and memory pieces: one byte each from r0, 189 # &buf[4], r1, and &buf[5]. 190 DW_TAG_variable { 191 {name "s2"} 192 {type :$struct_s_label} 193 {location { 194 regx [lindex $dwarf_regnum 0] 195 piece 1 196 addr "$buf_var + 4" 197 piece 1 198 regx [lindex $dwarf_regnum 1] 199 piece 1 200 addr "$buf_var + 5" 201 piece 1 202 } SPECIAL_expr} 203 } 204 # Memory pieces for bitfield access: 8 bytes optimized 205 # out, 3 bytes from &buf[3], and 1 byte from &buf[1]. 206 DW_TAG_variable { 207 {name "st1"} 208 {type :$struct_st_label} 209 {location { 210 piece 8 211 addr "$buf_var + 3" 212 piece 3 213 addr "$buf_var + 1" 214 piece 1 215 } SPECIAL_expr} 216 } 217 # Register pieces for bitfield access: 4 bytes optimized 218 # out, 3 bytes from r0, and 1 byte from r1. 219 DW_TAG_variable { 220 {name "t2"} 221 {type :$struct_t_label} 222 {location { 223 piece 4 224 regx [lindex $dwarf_regnum 0] 225 piece 3 226 regx [lindex $dwarf_regnum 1] 227 piece 1 228 } SPECIAL_expr} 229 } 230 # One piece per bitfield, using piece offsets: 32 bits of 231 # an implicit value, 9 bits of a stack value, 13 bits of 232 # r0, and 10 bits of buf. 233 DW_TAG_variable { 234 {name "t3"} 235 {type :$struct_t_label} 236 {location { 237 implicit_value 0x12 0x34 0x56 0x78 0x9a 238 bit_piece 32 4 239 const2s -280 240 stack_value 241 bit_piece 9 2 242 regx [lindex $dwarf_regnum 0] 243 bit_piece 13 14 244 addr $buf_var 245 bit_piece 10 42 246 } SPECIAL_expr} 247 } 248 } 249 } 250 } 251} 252 253if { [prepare_for_testing ${testfile}.exp ${testfile} \ 254 [list $srcfile $asm_file] {nodebug}] } { 255 return -1 256} 257 258if ![runto_main] { 259 return -1 260} 261 262# Determine byte order. 263set endian [get_endianness] 264 265# Byte-aligned memory pieces. 266gdb_test "print/d s1" " = \\{a = 2, b = 3, c = 0, d = 1\\}" \ 267 "s1 == re-ordered buf" 268gdb_test_no_output "set var s1.a = 63" 269gdb_test "print/d s1" " = \\{a = 63, b = 3, c = 0, d = 1\\}" \ 270 "verify s1.a" 271gdb_test "print/d a" " = \\{0, 1, 63, 3, 4, 5, 6, 7\\}" \ 272 "verify s1.a through a" 273gdb_test_no_output "set var s1.b = 42" 274gdb_test "print/d s1" " = \\{a = 63, b = 42, c = 0, d = 1\\}" \ 275 "verify s1.b" 276gdb_test "print/d a" " = \\{0, 1, 63, 42, 4, 5, 6, 7\\}" \ 277 "verify s1.b through a" 278 279# Byte-aligned register- and memory pieces. 280gdb_test_no_output "set var \$[lindex $regname 0] = 81" \ 281 "init reg for s2.a" 282gdb_test_no_output "set var \$[lindex $regname 1] = 28" \ 283 "init reg for s2.c" 284gdb_test "print/u s2" " = \\{a = 81, b = 4, c = 28, d = 5\\}" \ 285 "initialized s2 from mem and regs" 286gdb_test_no_output "set var s2.c += s2.a + s2.b - s2.d" 287gdb_test "print/u s2" " = \\{a = 81, b = 4, c = 108, d = 5\\}" \ 288 "verify s2.c" 289gdb_test "print/u \$[lindex $regname 1]" " = 108" \ 290 "verify s2.c through reg" 291gdb_test_no_output "set var s2 = {191, 73, 231, 123}" \ 292 "re-initialize s2" 293gdb_test "print/u s2" " = \\{a = 191, b = 73, c = 231, d = 123\\}" \ 294 "verify re-initialized s2" 295 296# Unaligned bitfield access through byte-aligned pieces. 297gdb_test_no_output "set var a = { 0 }" 298gdb_test_no_output "set var st1.t.x = -7" 299gdb_test_no_output "set var st1.t.z = 340" 300gdb_test_no_output "set var st1.t.y = 1234" 301gdb_test "print st1.t" " = \\{u = <optimized out>, x = -7, y = 1234, z = 340\\}" \ 302 "verify st1.t" 303switch $endian { 304 little {set val "0x55, 0x0, 0xf9, 0xa5, 0x9"} 305 big {set val "0x54, 0x0, 0xfc, 0x93, 0x49"} 306} 307# | -- | z:2-9 | -- | x:0-7 | x:8 y:0-6 | y:7-12 z:0-1 | -- | -- | 308# \_______________________________________________/ 309# val 310gdb_test "print/x a" " = \\{0x0, ${val}, 0x0, 0x0\\}" \ 311 "verify st1 through a" 312 313switch $endian { big {set val 0x7ffc} little {set val 0x3ffe00} } 314gdb_test_no_output "set var \$[lindex $regname 0] = $val" \ 315 "init t2, first piece" 316gdb_test_no_output "set var \$[lindex $regname 1] = 0" \ 317 "init t2, second piece" 318gdb_test "print/d t2" " = \\{u = <optimized out>, x = 0, y = -1, z = 0\\}" \ 319 "initialized t2 from regs" 320gdb_test_no_output "set var t2.y = 2641" 321gdb_test_no_output "set var t2.z = -400" 322gdb_test_no_output "set var t2.x = 200" 323gdb_test "print t2.x + t2.y + t2.z" " = 2441" 324 325# Bitfield access through pieces with nonzero piece offsets. 326gdb_test_no_output "set var \$[lindex $regname 0] = 0xa8000" \ 327 "init reg for t3.y" 328gdb_test_no_output "set var *(char \[2\] *) (a + 5) = { 70, 82 }" \ 329 "init mem for t3.z" 330switch $endian { 331 little {set val "u = -1484430527, x = -70, y = 42, z = 145"} 332 big {set val "u = 591751049, x = -70, y = 42, z = 101"} 333} 334gdb_test "print t3" " = \\{$val\\}" \ 335 "initialized t3 from reg and mem" 336gdb_test_no_output "set var t3.y = -1" \ 337 "overwrite t3.y" 338gdb_test "print/x \$[lindex $regname 0]" " = 0x7ffc000" \ 339 "verify t3.y through reg" 340gdb_test_no_output "set var t3.z = -614" \ 341 "overwrite t3.z" 342switch $endian {big {set val "0x59, 0xa2"} little {set val "0x6a, 0x56"}} 343gdb_test "print/x *(char \[2\] *) (a + 5)" " = \\{$val\\}" \ 344 "verify t3.z through mem" 345