1# Copyright 2002-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 file was written by Michael Snyder (msnyder@redhat.com) 17# This is a test for the gdb command "dump". 18 19 20standard_testfile 21 22set options {debug} 23 24set is64bitonly "no" 25set endian "auto" 26 27if [istarget "alpha*-*-*"] then { 28 # SREC etc cannot handle 64-bit addresses. Force the test 29 # program into the low 31 bits of the address space. 30 lappend options "additional_flags=-Wl,-taso" 31} 32 33# Runs the command 'print zero_all ()'. Uses the PRINT_ZERO_ALL_COUNT 34# global to ensure the test names are unique. 35set print_zero_all_count 0 36proc print_zero_all { } { 37 global print_zero_all_count 38 39 incr print_zero_all_count 40 gdb_test "print zero_all ()" " = void" \ 41 "call ${print_zero_all_count} to zero_all function" 42} 43 44# Debian9/Ubuntu16.10 onwards default to PIE enabled. Ensure it is disabled as 45# this causes addresses to be out of range for IHEX. 46lappend options {nopie} 47 48if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${options}] != "" } { 49 untested "failed to compile" 50 return -1 51} 52 53# Start with a fresh gdb. 54 55gdb_exit 56gdb_start 57gdb_reinitialize_dir $srcdir/$subdir 58 59gdb_test "dump mem /dev/null 0x10 0x20" "Cannot access memory at address 0x10" \ 60 "inaccessible memory is reported" 61 62gdb_load ${binfile} 63 64# Check the address of a variable. If it is bigger than 32-bit, 65# assume our target has 64-bit addresses that are not supported by SREC, 66# IHEX and TEKHEX. We skip those tests then. 67set max_32bit_address "0xffffffff" 68set data_address [get_hexadecimal_valueof "&intarray" 0x100000000] 69if {${data_address} > ${max_32bit_address}} then { 70 set is64bitonly "yes" 71} 72 73# Clean up any stale output files from previous test runs 74 75set filenames {} 76set all_files { 77 intarr1.bin intarr1b.bin intarr1.ihex 78 intarr1.srec intarr1.tekhex intarr1.verilog 79 intarr2.bin intarr2b.bin intarr2.ihex 80 intarr2.srec intarr2.tekhex intarr2.verilog 81 intstr1.bin intstr1b.bin intstr1.ihex 82 intstr1.srec intstr1.tekhex intstr1.verilog 83 intstr2.bin intstr2b.bin intstr2.ihex 84 intstr2.srec intstr2.tekhex intstr2.verilog 85 intarr3.srec 86} 87 88# This loop sets variables dynamically -- each name listed in 89# $ALL_FILES is both a file name and a variable name. 90foreach file $all_files { 91 if {[is_remote host]} { 92 set this_name $file 93 } else { 94 set this_name [standard_output_file $file] 95 } 96 97 lappend filenames [set ${file} $this_name] 98} 99 100remote_exec host "rm -f $filenames" 101 102# Test help (FIXME:) 103 104# Run target program until data structs are initialized. 105 106if { ! [ runto checkpoint1 ] } then { 107 untested "couldn't run to checkpoint" 108 return -1 109} 110 111# Get the endianness for the later use with endianless formats. 112 113set endian [get_endianness] 114 115# Now generate some dump files. 116 117proc make_dump_file { command msg } { 118 global gdb_prompt 119 120 gdb_test_multiple "${command}" "$msg" { 121 -re ".*\[Ee\]rror.*$gdb_prompt $" { fail $msg } 122 -re ".*\[Ww\]arning.*$gdb_prompt $" { fail $msg } 123 -re ".*\[Uu\]ndefined .*$gdb_prompt $" { fail $msg } 124 -re ".*$gdb_prompt $" { pass $msg } 125 } 126} 127 128make_dump_file "dump val [set intarr1.bin] intarray" \ 129 "dump array as value, default" 130 131make_dump_file "dump val [set intstr1.bin] intstruct" \ 132 "dump struct as value, default" 133 134make_dump_file "dump bin val [set intarr1b.bin] intarray" \ 135 "dump array as value, binary" 136 137make_dump_file "dump bin val [set intstr1b.bin] intstruct" \ 138 "dump struct as value, binary" 139 140make_dump_file "dump srec val [set intarr1.srec] intarray" \ 141 "dump array as value, srec" 142 143make_dump_file "dump srec val [set intstr1.srec] intstruct" \ 144 "dump struct as value, srec" 145 146make_dump_file "dump ihex val [set intarr1.ihex] intarray" \ 147 "dump array as value, intel hex" 148 149make_dump_file "dump ihex val [set intstr1.ihex] intstruct" \ 150 "dump struct as value, intel hex" 151 152make_dump_file "dump tekhex val [set intarr1.tekhex] intarray" \ 153 "dump array as value, tekhex" 154 155make_dump_file "dump tekhex val [set intstr1.tekhex] intstruct" \ 156 "dump struct as value, tekhex" 157 158make_dump_file "dump verilog val [set intarr1.verilog] intarray" \ 159 "dump array as value, verilog" 160 161make_dump_file "dump verilog val [set intstr1.verilog] intstruct" \ 162 "dump struct as value, verilog" 163 164proc capture_value { expression args } { 165 global gdb_prompt 166 global expect_out 167 168 set output_string "" 169 if {[llength $args] > 0} { 170 # Convert $args into a simple string and don't use EXPRESSION 171 # in the test name. 172 set test "[join $args]; capture" 173 } { 174 set test "capture $expression" 175 } 176 gdb_test_multiple "print ${expression}" "$test" { 177 -re "\\$\[0-9\]+ = (\[^\r\n\]+).*$gdb_prompt $" { 178 set output_string "$expect_out(1,string)" 179 pass "$test" 180 } 181 -re "(Cannot access memory at address \[^\r\n\]+).*$gdb_prompt $" { 182 # Even a failed value is valid 183 set output_string "$expect_out(1,string)" 184 pass "$test" 185 } 186 } 187 return $output_string 188} 189 190# POINTER is a pointer and this proc captures the value of POINTER along 191# with POINTER's type. For example, POINTER is "&intarray", this proc will 192# call "p &intarray", capture "(int (*)[32]) 0x804a0e0", and return this 193# string. 194 195proc capture_pointer_with_type { pointer } { 196 global gdb_prompt 197 global expect_out 198 199 set test "capture type of pointer $pointer" 200 set output_string "" 201 gdb_test_multiple "p ${pointer}" $test { 202 -re "\\$\[0-9\]+ = .*$gdb_prompt $" { 203 # Expected output of "p ${pointer}" is like "$7 = (int (*)[32]) 0x804a0e0", 204 # and we want to extract "(int (*)[32]) 0x804a0e0" from it via 205 # following regexp. 206 if [regexp " \\(.*\\).* 0x\[0-9a-fA-F\]+" $expect_out(0,string) output_string] { 207 # OUTPUT_STRING is expected to be like "(int (*)[32]) 0x804a0e0". 208 pass "$test" 209 } else { 210 fail "$test" 211 } 212 } 213 } 214 215 return $output_string 216} 217 218set array_start [capture_value "/x &intarray\[0\]"] 219set array_end [capture_value "/x &intarray\[32\]"] 220set struct_start [capture_value "/x &intstruct"] 221set struct_end [capture_value "/x &intstruct + 1"] 222 223set array_val [capture_value "intarray"] 224set struct_val [capture_value "intstruct"] 225 226set array_ptr_type [capture_pointer_with_type "&intarray"] 227set struct_ptr_type [capture_pointer_with_type "&intstruct"] 228 229make_dump_file "dump mem [set intarr2.bin] $array_start $array_end" \ 230 "dump array as memory, default" 231 232make_dump_file "dump mem [set intstr2.bin] $struct_start $struct_end" \ 233 "dump struct as memory, default" 234 235make_dump_file "dump bin mem [set intarr2b.bin] $array_start $array_end" \ 236 "dump array as memory, binary" 237 238make_dump_file "dump bin mem [set intstr2b.bin] $struct_start $struct_end" \ 239 "dump struct as memory, binary" 240 241make_dump_file "dump srec mem [set intarr2.srec] $array_start $array_end" \ 242 "dump array as memory, srec" 243 244make_dump_file "dump srec mem [set intstr2.srec] $struct_start $struct_end" \ 245 "dump struct as memory, srec" 246 247make_dump_file "dump ihex mem [set intarr2.ihex] $array_start $array_end" \ 248 "dump array as memory, ihex" 249 250make_dump_file "dump ihex mem [set intstr2.ihex] $struct_start $struct_end" \ 251 "dump struct as memory, ihex" 252 253make_dump_file "dump tekhex mem [set intarr2.tekhex] $array_start $array_end" \ 254 "dump array as memory, tekhex" 255 256make_dump_file "dump tekhex mem [set intstr2.tekhex] $struct_start $struct_end" \ 257 "dump struct as memory, tekhex" 258 259make_dump_file "dump verilog mem [set intarr2.verilog] $array_start $array_end" \ 260 "dump array as memory, verilog" 261 262make_dump_file "dump verilog mem [set intstr2.verilog] $struct_start $struct_end" \ 263 "dump struct as memory, verilog" 264 265# test complex expressions 266make_dump_file \ 267 "dump srec mem [set intarr3.srec] &intarray \(char *\) &intarray + sizeof intarray" \ 268 "dump array as mem, srec, expressions" 269 270proc test_restore_saved_value { restore_args msg oldval newval } { 271 global gdb_prompt 272 273 gdb_test "restore $restore_args" \ 274 "Restoring .*" \ 275 "$msg; file restored ok" 276 if { ![string compare $oldval \ 277 [capture_value $newval "$msg"]] } then { 278 pass "$msg; value restored ok" 279 } else { 280 fail "$msg; value restored ok" 281 } 282} 283 284if ![string compare $is64bitonly "no"] then { 285 286 287 test_restore_saved_value "[set intarr1.srec]" "array as value, srec" \ 288 $array_val "intarray" 289 290 test_restore_saved_value "[set intstr1.srec]" "struct as value, srec" \ 291 $struct_val "intstruct" 292 293 print_zero_all 294 295 test_restore_saved_value "[set intarr2.srec]" "array as memory, srec" \ 296 $array_val "intarray" 297 298 test_restore_saved_value "[set intstr2.srec]" "struct as memory, srec" \ 299 $struct_val "intstruct" 300 301 print_zero_all 302 303 test_restore_saved_value "[set intarr1.ihex]" "array as value, ihex" \ 304 $array_val "intarray" 305 306 test_restore_saved_value "[set intstr1.ihex]" "struct as value, ihex" \ 307 $struct_val "intstruct" 308 309 print_zero_all 310 311 test_restore_saved_value "[set intarr2.ihex]" "array as memory, ihex" \ 312 $array_val "intarray" 313 314 test_restore_saved_value "[set intstr2.ihex]" "struct as memory, ihex" \ 315 $struct_val "intstruct" 316 317 print_zero_all 318 319 test_restore_saved_value "[set intarr1.tekhex]" "array as value, tekhex" \ 320 $array_val "intarray" 321 322 test_restore_saved_value "[set intstr1.tekhex]" "struct as value, tekhex" \ 323 $struct_val "intstruct" 324 325 print_zero_all 326 327 test_restore_saved_value "[set intarr2.tekhex]" "array as memory, tekhex" \ 328 $array_val "intarray" 329 330 test_restore_saved_value "[set intstr2.tekhex]" "struct as memory, tekhex" \ 331 $struct_val "intstruct" 332} 333 334print_zero_all 335 336test_restore_saved_value "[set intarr1.bin] binary $array_start" \ 337 "array as value, binary" \ 338 $array_val "intarray" 339 340test_restore_saved_value "[set intstr1.bin] binary $struct_start" \ 341 "struct as value, binary" \ 342 $struct_val "intstruct" 343 344print_zero_all 345 346test_restore_saved_value "[set intarr2.bin] binary $array_start" \ 347 "array as memory, binary" \ 348 $array_val "intarray" 349 350test_restore_saved_value "[set intstr2.bin] binary $struct_start" \ 351 "struct as memory, binary" \ 352 $struct_val "intstruct" 353 354# test restore with offset. 355 356set array2_start [capture_value "/x &intarray2\[0\]"] 357set struct2_start [capture_value "/x &intstruct2"] 358set array2_offset \ 359 [capture_value "(char *) &intarray2 - (char *) &intarray"] 360set struct2_offset \ 361 [capture_value "(char *) &intstruct2 - (char *) &intstruct"] 362 363print_zero_all 364 365 366if ![string compare $is64bitonly "no"] then { 367 test_restore_saved_value "[set intarr1.srec] $array2_offset" \ 368 "array copy, srec" \ 369 $array_val "intarray2" 370 371 test_restore_saved_value "[set intstr1.srec] $struct2_offset" \ 372 "struct copy, srec" \ 373 $struct_val "intstruct2" 374 375 print_zero_all 376 377 test_restore_saved_value "[set intarr1.ihex] $array2_offset" \ 378 "array copy, ihex" \ 379 $array_val "intarray2" 380 381 test_restore_saved_value "[set intstr1.ihex] $struct2_offset" \ 382 "struct copy, ihex" \ 383 $struct_val "intstruct2" 384 385 print_zero_all 386 387 test_restore_saved_value "[set intarr1.tekhex] $array2_offset" \ 388 "array copy, tekhex" \ 389 $array_val "intarray2" 390 391 test_restore_saved_value "[set intstr1.tekhex] $struct2_offset" \ 392 "struct copy, tekhex" \ 393 $struct_val "intstruct2" 394} 395 396print_zero_all 397 398test_restore_saved_value "[set intarr1.bin] binary $array2_start" \ 399 "array copy, binary" \ 400 $array_val "intarray2" 401 402test_restore_saved_value "[set intstr1.bin] binary $struct2_start" \ 403 "struct copy, binary" \ 404 $struct_val "intstruct2" 405 406# 407# test restore with start/stop addresses. 408# 409# For this purpose, we will restore just the third element of the array, 410# and check to see that adjacent elements are not modified. 411# 412# We will need the address and offset of the third and fourth elements. 413# 414 415set element3_start [capture_value "/x &intarray\[3\]"] 416set element4_start [capture_value "/x &intarray\[4\]"] 417set element3_offset \ 418 [capture_value "/x (char *) &intarray\[3\] - (char *) &intarray\[0\]"] 419set element4_offset \ 420 [capture_value "/x (char *) &intarray\[4\] - (char *) &intarray\[0\]"] 421 422if ![string compare $is64bitonly "no"] then { 423 print_zero_all 424 425 test_restore_saved_value "[set intarr1.srec] 0 $element3_start $element4_start" \ 426 "array partial, srec" 4 "intarray\[3\]" 427 428 gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 1" 429 gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 1" 430 431 print_zero_all 432 433 test_restore_saved_value "[set intarr1.ihex] 0 $element3_start $element4_start" \ 434 "array partial, ihex" 4 "intarray\[3\]" 435 436 gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 2" 437 gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 2" 438 439 print_zero_all 440 441 test_restore_saved_value "[set intarr1.tekhex] 0 $element3_start $element4_start" \ 442 "array partial, tekhex" 4 "intarray\[3\]" 443 444 gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 3" 445 gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 3" 446} 447 448print_zero_all 449 450test_restore_saved_value \ 451 "[set intarr1.bin] binary $array_start $element3_offset $element4_offset" \ 452 "array partial, binary" 4 "intarray\[3\]" 453 454gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 4" 455gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 4" 456 457if ![string compare $is64bitonly "no"] then { 458 print_zero_all 459 460 # restore with expressions 461 test_restore_saved_value \ 462 "[set intarr3.srec] (char*)${array2_start}-(char*)${array_start} &intarray\[3\] &intarray\[4\]" \ 463 "array partial with expressions" 4 "intarray2\[3\]" 464 465 gdb_test "print intarray2\[2\] == 0" " = 1" "element 2 not changed, == 4" 466 gdb_test "print intarray2\[4\] == 0" " = 1" "element 4 not changed, == 4" 467} 468 469 470# Now start a fresh gdb session, and reload the saved value files. 471 472gdb_exit 473gdb_start 474gdb_file_cmd ${binfile} 475 476# Now fix the endianness at the correct state. 477 478gdb_test_multiple "set endian $endian" "set endianness" { 479 -re ".* (big|little) endian.*$gdb_prompt $" { 480 pass "setting $endian endianness" 481 } 482} 483 484# Reload saved values one by one, and compare. 485 486if { ![string compare $array_val \ 487 [capture_value "intarray" "file binfile; intarray"]] } then { 488 fail "start with intarray un-initialized" 489} else { 490 pass "start with intarray un-initialized" 491} 492 493if { ![string compare $struct_val \ 494 [capture_value "intstruct" "file binfile; intstruct"]] } then { 495 fail "start with intstruct un-initialized" 496} else { 497 pass "start with intstruct un-initialized" 498} 499 500proc test_reload_saved_value { filename msg oldval newval } { 501 global gdb_prompt 502 503 gdb_file_cmd $filename 504 if { ![string compare $oldval \ 505 [capture_value $newval "$msg"]] } then { 506 pass "$msg; value restored ok" 507 } else { 508 fail "$msg; value restored ok" 509 } 510} 511 512# srec format can not be loaded for 64-bit-only platforms 513if ![string compare $is64bitonly "no"] then { 514 test_reload_saved_value "[set intarr1.srec]" "reload array as value, srec" \ 515 $array_val "\*$array_ptr_type" 516 test_reload_saved_value "[set intstr1.srec]" "reload struct as value, srec" \ 517 $struct_val "\*$struct_ptr_type" 518 test_reload_saved_value "[set intarr2.srec]" "reload array as memory, srec" \ 519 $array_val "\*$array_ptr_type" 520 test_reload_saved_value "[set intstr2.srec]" "reload struct as memory, srec" \ 521 $struct_val "\*$struct_ptr_type" 522} 523 524# ihex format can not be loaded for 64-bit-only platforms 525if ![string compare $is64bitonly "no"] then { 526 527 test_reload_saved_value "[set intarr1.ihex]" \ 528 "reload array as value, intel hex" \ 529 $array_val "\*$array_ptr_type" 530 test_reload_saved_value "[set intstr1.ihex]" \ 531 "reload struct as value, intel hex" \ 532 $struct_val "\*$struct_ptr_type" 533 test_reload_saved_value "[set intarr2.ihex]" \ 534 "reload array as memory, intel hex" \ 535 $array_val "\*$array_ptr_type" 536 test_reload_saved_value "[set intstr2.ihex]" \ 537 "reload struct as memory, intel hex" \ 538 $struct_val "\*$struct_ptr_type" 539} 540 541# tekhex format can not be loaded for 64-bit-only platforms 542if ![string compare $is64bitonly "no"] then { 543 test_reload_saved_value "[set intarr1.tekhex]" \ 544 "reload array as value, tekhex" \ 545 $array_val "\*$array_ptr_type" 546 test_reload_saved_value "[set intstr1.tekhex]" \ 547 "reload struct as value, tekhex" \ 548 $struct_val "\*$struct_ptr_type" 549 test_reload_saved_value "[set intarr2.tekhex]" \ 550 "reload array as memory, tekhex" \ 551 $array_val "\*$array_ptr_type" 552 test_reload_saved_value "[set intstr2.tekhex]" \ 553 "reload struct as memory, tekhex" \ 554 $struct_val "\*$struct_ptr_type" 555} 556 557# clean up files 558 559remote_exec host "rm -f $filenames" 560