1# Copyright 2015-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 testsuite is to test examining memory backward by specifying a negative 17# number in the 'x' command. 18 19standard_testfile 20if { [prepare_for_testing "failed to prepare for examine-backward" \ 21 ${testfile} ${srcfile}] } { 22 return -1 23} 24 25if ![runto_main] { 26 untested "could not run to main" 27 return -1 28} 29 30proc get_first_mapped_address {} { 31 global gdb_prompt 32 33 set addr "0" 34 gdb_test_multiple "info proc mappings" "info proc mappings" { 35 -re "objfile\[\r\n\t \]+(0x\[0-9a-fA-F\]+).*\[\r\n\]*$gdb_prompt $" { 36 set addr $expect_out(1,string) 37 } 38 -re "$gdb_prompt $" { 39 unsupported "current target does not support 'info proc mappings'" 40 } 41 } 42 return ${addr} 43} 44 45with_test_prefix "invalid format" { 46 gdb_test "x/- 10xb main" "Invalid number \"10xb\"\." \ 47 "a whitespace after a leading hyphen" 48 gdb_test "x/--10xb main" "Invalid number \"10xb\"\." \ 49 "double hyphen" 50 gdb_test "x/-a10xb main" "Invalid number \"10xb\"\." \ 51 "an alphabet after a leading hyphen" 52 gdb_test_no_output "x/-0i main" "zero with backward disassemble" 53 gdb_test_no_output "x/-0sh main" "zero with backward examine string" 54} 55 56with_test_prefix "memory page boundary" { 57 set boundary [get_first_mapped_address] 58 if {![is_address_zero_readable] && $boundary != 0} { 59 gdb_test_no_output "set print elements 0" 60 gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward" { 61 "0x" 62 "0x" 63 "0x" 64 } 65 gdb_test_sequence "x/-4s" "take 4 strings backward" { 66 "Cannot access memory at address 0x" 67 "0x" 68 "0x" 69 "0x" 70 } 71 gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward again" { 72 "0x" 73 "0x" 74 "0x" 75 } 76 gdb_test_sequence "x/-3s" "take 3 strings backward" { 77 "Cannot access memory at address 0x" 78 "0x" 79 "0x" 80 "0x" 81 } 82 } 83} 84 85with_test_prefix "address zero boundary" { 86 global gdb_prompt 87 88 set address_zero "0x0" 89 set byte "\t0x\[0-9a-f\]+" 90 91 set test "examine 3 bytes forward from ${address_zero}" 92 gdb_test_multiple "x/3xb ${address_zero}" "$test" { 93 -re "0x\[0-9a-f\]*0.*:${byte}${byte}${byte}\[\r\n\]*$gdb_prompt $" { 94 pass $test 95 } 96 -re "0x\[0-9a-f\]*0.*:\tCannot access memory at address 0x\[0-9a-f\]*0\[\r\n\]*$gdb_prompt $" { 97 # If we failed to read address 0 then this is fine, so 98 # long as we're not expecting to be able to read from 99 # address 0. 100 if {![is_address_zero_readable]} { 101 # The next test assumes that the last address examined 102 # would be 0x2. As we just failed to read address 0x0 103 # things are going to go wrong unless we now tell GDB 104 # to examine address 0x2. We assume here that if we 105 # can't read 0x0 we can't read 0x2 either. 106 gdb_test "x/3xb 0x2" "Cannot access memory at address 0x\[0-9a-f\]*2" \ 107 "set last examined address to 0x2" 108 pass $test 109 } else { 110 fail $test 111 } 112 } 113 } 114 115 set test "examine 6 bytes backward" 116 gdb_test_multiple "x/-6x" "$test" { 117 -re "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}${byte}${byte}${byte}.*\[\r\n\]*$gdb_prompt $" { 118 pass $test 119 } 120 -re "0x\[0-9a-f\]+fd.*:\tCannot access memory at address 0x\[0-9a-f\]+fd.*\[\r\n\]*$gdb_prompt $" { 121 # We may, or may not have managed to read from address 0x0 122 # in the previous test, however, being able to read 0x0 is 123 # no guarantee that we can read from the other end of the 124 # address space. If we get an error about trying to read 125 # from the expected address then we count that as a pass, 126 # GDB did try to read the correct location, and this test 127 # is (mostly) about does GDB calculate the correct address 128 # when wrapping around. 129 pass $test 130 } 131 } 132 133 set test "examine 3 bytes backward from ${address_zero}" 134 gdb_test_multiple "x/-3x ${address_zero}" "$test" { 135 -re "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}.*\[\r\n\]*$gdb_prompt $" { 136 pass $test 137 } 138 -re "0x\[0-9a-f\]+fd.*:\tCannot access memory at address 0x\[0-9a-f\]+fd.*\[\r\n\]*$gdb_prompt $" { 139 # See previous test for why this is a pass. 140 pass $test 141 } 142 } 143} 144 145gdb_test_no_output "set charset ASCII" 146 147with_test_prefix "char-width=1, print-max=20" { 148 gdb_test_no_output "set print elements 20" 149 gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward" { 150 "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 151 "\"UVWXYZ\"" 152 "\"\"" 153 "\"\"" 154 "\"[^\"]+\"" 155 "\"01234567890123456789\"\.\.\." 156 } 157 gdb_test "x/-1xb" "0x39" "take 1 char backward" 158 gdb_test_sequence "x/-6s" "take 6 strings backward" { 159 "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 160 "\"UVWXYZ\"" 161 "\"\"" 162 "\"\"" 163 "\"[^\"]+\"" 164 "\"01234567890123456789\"\.\.\." 165 } 166 gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward again" { 167 "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 168 "\"UVWXYZ\"" 169 "\"\"" 170 "\"\"" 171 "\"[^\"]+\"" 172 "\"01234567890123456789\"\.\.\." 173 } 174 gdb_test "x/-xb" "0x39" "take 1 char backward again" 175 gdb_test "x/-s" "\"01234567890123456789\"\.\.\." \ 176 "take 1 string backward (1/6)" 177 gdb_test "x/-s" "\".+\"" \ 178 "take 1 string backward (2/6)" 179 gdb_test "x/-s" "\"\"" \ 180 "take 1 string backward (3/6)" 181 gdb_test "x/-s" "\"\"" \ 182 "take 1 string backward (4/6)" 183 gdb_test "x/-s" "\"GHIJKLMNOPQRSTUVWXYZ\"" \ 184 "take 1 string backward (5/6)" 185 gdb_test "x/-s" "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \ 186 "take 1 string backward (6/6)" 187} 188 189with_test_prefix "char-width=2, print-max=20" { 190 gdb_test_no_output "set print elements 20" 191 gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" { 192 "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 193 "u\"UVWXYZ\"" 194 "u\"\"" 195 "u\"\"" 196 "u\"[^\"]+\"" 197 "u\"01234567890123456789\"\.\.\." 198 } 199 gdb_test "x/-1xh" "0x0039" "take 1 char backward" 200 gdb_test_sequence "x/-6sh" "take 6 strings backward" { 201 "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 202 "u\"UVWXYZ\"" 203 "u\"\"" 204 "u\"\"" 205 "u\"[^\"]+\"" 206 "u\"01234567890123456789\"\.\.\." 207 } 208 gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" { 209 "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 210 "u\"UVWXYZ\"" 211 "u\"\"" 212 "u\"\"" 213 "u\"[^\"]+\"" 214 "u\"01234567890123456789\"\.\.\." 215 } 216 gdb_test "x/-xh" "0x0039" "take 1 char backward again" 217 gdb_test "x/-sh" "u\"01234567890123456789\"\.\.\." \ 218 "take 1 string backward (1/6)" 219 gdb_test "x/-sh" "u\".+\"" \ 220 "take 1 string backward (2/6)" 221 gdb_test "x/-sh" "u\"\"" \ 222 "take 1 string backward (3/6)" 223 gdb_test "x/-sh" "u\"\"" \ 224 "take 1 string backward (4/6)" 225 gdb_test "x/-sh" "u\"GHIJKLMNOPQRSTUVWXYZ\"" \ 226 "take 1 string backward (5/6)" 227 gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \ 228 "take 1 string backward (6/6)" 229} 230 231with_test_prefix "char-width=4, print-max=20" { 232 gdb_test_no_output "set print elements 20" 233 gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward" { 234 "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 235 "U\"UVWXYZ\"" 236 "U\"\"" 237 "U\"\"" 238 "U\"[^\"]+\"" 239 "U\"01234567890123456789\"\.\.\." 240 } 241 gdb_test "x/-1xw" "0x00000039" "take 1 char backward" 242 gdb_test_sequence "x/-6sw" "take 6 strings backward" { 243 "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 244 "U\"UVWXYZ\"" 245 "U\"\"" 246 "U\"\"" 247 "U\"[^\"]+\"" 248 "U\"01234567890123456789\"\.\.\." 249 } 250 gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward again" { 251 "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." 252 "U\"UVWXYZ\"" 253 "U\"\"" 254 "U\"\"" 255 "U\"[^\"]+\"" 256 "U\"01234567890123456789\"\.\.\." 257 } 258 gdb_test "x/-xw" "0x00000039" "take 1 char backward again" 259 gdb_test "x/-sw" "U\"01234567890123456789\"\.\.\." \ 260 "take 1 string backward (1/6)" 261 gdb_test "x/-sw" "U\".+\"" \ 262 "take 1 string backward (2/6)" 263 gdb_test "x/-sw" "U\"\"" \ 264 "take 1 string backward (3/6)" 265 gdb_test "x/-sw" "U\"\"" \ 266 "take 1 string backward (4/6)" 267 gdb_test "x/-sw" "U\"GHIJKLMNOPQRSTUVWXYZ\"" \ 268 "take 1 string backward (5/6)" 269 gdb_test "x/-sw" "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \ 270 "take 1 string backward (6/6)" 271} 272 273with_test_prefix "char-width=2, print-max=0" { 274 gdb_test_no_output "set print elements 0" 275 gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" { 276 "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" 277 "u\"\"" 278 "u\"\"" 279 "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\"" 280 "u\"012345678901234567890123456789\"" 281 "u\"!!!!!!\"" 282 } 283 gdb_test "x/-4xh" "0x0021\[\t \]+0x0021\[\t \]+0x0021\[\t \]+0x0000" \ 284 "take 4 characters backward" 285 gdb_test_sequence "x/-6sh" "take 6 strings backward" { 286 "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" 287 "u\"\"" 288 "u\"\"" 289 "u\"[^\"]+\"" 290 "u\"012345678901234567890123456789\"" 291 "u\"!!!!!!\"" 292 } 293 gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" { 294 "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" 295 "u\"\"" 296 "u\"\"" 297 "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\"" 298 "u\"012345678901234567890123456789\"" 299 "u\"!!!!!!\"" 300 } 301 gdb_test "x/-xh" "0x0000" "take 1 char backward" 302 gdb_test "x/-sh" "u\"!!!!!!\"" \ 303 "take 1 string backward (1/6)" 304 gdb_test "x/-sh" "u\"012345678901234567890123456789\"" \ 305 "take 1 string backward (2/6)" 306 gdb_test "x/-sh" "u\".+\"" \ 307 "take 1 string backward (3/6)" 308 gdb_test "x/-sh" "u\"\"" \ 309 "take 1 string backward (4/6)" 310 gdb_test "x/-sh" "u\"\"" \ 311 "take 1 string backward (5/6)" 312 gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" \ 313 "take 1 string backward (6/6)" 314} 315 316with_test_prefix "char-width=1, print-max=4" { 317 gdb_test_no_output "set print elements 4" 318 gdb_test_sequence "x/9s &TestStrings" "take 9 strings forward" { 319 "\"ABCD\"\.\.\." 320 "\"EFGH\"\.\.\." 321 "\"IJKL\"\.\.\." 322 "\"MNOP\"\.\.\." 323 "\"QRST\"\.\.\." 324 "\"UVWX\"\.\.\." 325 "\"YZ\"" 326 "\"\"" 327 "\"\"" 328 } 329 gdb_test "x/-xb" "0x00" "take 1 byte backward" 330 gdb_test_sequence "x/-4s" "take 4 strings backward (1/2)" { 331 "\"TUVW\"\.\.\." 332 "\"XYZ\"" 333 "\"\"" 334 "\"\"" 335 } 336 gdb_test_sequence "x/-4s" "take 4 strings backward (2/2)" { 337 "\"CDEF\"\.\.\." 338 "\"GHIJ\"\.\.\." 339 "\"KLMN\"\.\.\." 340 "\"OPQR\"\.\.\." 341 } 342} 343 344with_test_prefix "backward disassemble general" { 345 set length_to_examine {1 2 3 4 10} 346 set disassmbly {} 347 348 gdb_test "x/i main" "0x\[0-9a-fA-F\]+ <main>:\t.*" \ 349 "move the current position to main (x/i)" 350 gdb_test "x/-i" "0x\[0-9a-fA-F\]+ <main>:\t.*" \ 351 "move the current position to main (x/-i)" 352 for {set i 0} {$i < [llength $length_to_examine]} {incr i} { 353 set len [lindex $length_to_examine $i] 354 set instructions [capture_command_output "x/${len}i" ""] 355 lappend disassmbly $instructions 356 } 357 for {set i 0} {$i < [llength $length_to_examine]} {incr i} { 358 set idx [expr [llength $length_to_examine] - $i - 1] 359 set len [lindex $length_to_examine $idx] 360 set actual [capture_command_output "x/-${len}i" ""] 361 set expected [lindex $disassmbly $idx] 362 if {$actual == $expected} { 363 pass "inst:$idx" 364 } else { 365 fail "inst:$idx" 366 } 367 } 368} 369