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