]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | # Copyright 2009-2024 Free Software Foundation, Inc. |
35669430 DE |
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 is part of the gdb testsuite. | |
17 | ||
18 | # Test amd64 displaced stepping. | |
19 | ||
4fe960e8 | 20 | require is_x86_64_m64_target |
35669430 DE |
21 | |
22 | set newline "\[\r\n\]*" | |
23 | ||
6e8b1ab2 | 24 | set opts {debug nopie} |
cf141dd8 | 25 | standard_testfile .S -signal.c |
35669430 | 26 | |
cf141dd8 | 27 | if { [prepare_for_testing "failed to prepare" $testfile "$srcfile $srcfile2" $opts] } { |
35669430 DE |
28 | return -1 |
29 | } | |
30 | ||
35669430 DE |
31 | gdb_test "set displaced-stepping on" "" |
32 | gdb_test "show displaced-stepping" ".* displaced stepping .* is on.*" | |
33 | ||
75b6f386 | 34 | if {![runto_main]} { |
35669430 DE |
35 | return 0 |
36 | } | |
37 | ||
38 | ########################################## | |
39 | ||
40 | # Test call/ret. | |
41 | ||
42 | gdb_test "break test_call" \ | |
d1e36019 | 43 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 44 | gdb_test "break test_call_end" \ |
d1e36019 | 45 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 DE |
46 | |
47 | gdb_test "break test_ret" \ | |
d1e36019 | 48 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 49 | gdb_test "break test_ret_end" \ |
d1e36019 | 50 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 DE |
51 | |
52 | gdb_test "continue" \ | |
53 | "Continuing.*Breakpoint.*, test_call ().*" \ | |
54 | "continue to test_call" | |
55 | gdb_test "continue" \ | |
56 | "Continuing.*Breakpoint.*, test_call_end ().*" \ | |
57 | "continue to test_call_end" | |
58 | ||
59 | gdb_test "continue" \ | |
60 | "Continuing.*Breakpoint.*, test_ret ().*" \ | |
61 | "continue to test_ret" | |
62 | gdb_test "continue" \ | |
63 | "Continuing.*Breakpoint.*, test_ret_end ().*" \ | |
64 | "continue to test_ret_end" | |
65 | ||
66 | ########################################## | |
67 | ||
68 | # Test abs-jmp/rep-ret. | |
69 | ||
70 | gdb_test "break test_abs_jmp" \ | |
d1e36019 | 71 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 72 | gdb_test "break test_abs_jmp_end" \ |
d1e36019 | 73 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 DE |
74 | |
75 | gdb_test "break test_rep_ret" \ | |
d1e36019 | 76 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 77 | gdb_test "break test_rep_ret_end" \ |
d1e36019 | 78 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 DE |
79 | |
80 | gdb_test "continue" \ | |
81 | "Continuing.*Breakpoint.*, test_abs_jmp ().*" \ | |
82 | "continue to test_abs_jmp" | |
83 | gdb_test "continue" \ | |
84 | "Continuing.*Breakpoint.*, test_abs_jmp_end ().*" \ | |
85 | "continue to test_abs_jmp_end" | |
86 | ||
87 | gdb_test "continue" \ | |
88 | "Continuing.*Breakpoint.*, test_rep_ret ().*" \ | |
89 | "continue to test_rep_ret" | |
90 | gdb_test "continue" \ | |
91 | "Continuing.*Breakpoint.*, test_rep_ret_end ().*" \ | |
92 | "continue to test_rep_ret_end" | |
93 | ||
94 | ########################################## | |
95 | ||
96 | # Test syscall. | |
97 | ||
98 | gdb_test "break test_syscall" \ | |
d1e36019 | 99 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 100 | gdb_test "break test_syscall_end" \ |
d1e36019 | 101 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 DE |
102 | |
103 | gdb_test "continue" \ | |
104 | "Continuing.*Breakpoint.*, test_syscall ().*" \ | |
105 | "continue to test_syscall" | |
106 | gdb_test "continue" \ | |
107 | "Continuing.*Breakpoint.*, test_syscall_end ().*" \ | |
108 | "continue to test_syscall_end" | |
109 | ||
110 | ########################################## | |
111 | ||
1903f0e6 DE |
112 | # int3 (with prefixes) |
113 | # These don't occur in normal code, but gdb should still DTRT. | |
114 | ||
115 | gdb_test "break test_int3" \ | |
d1e36019 | 116 | "Breakpoint.*at.* file .*$srcfile, line.*" |
1903f0e6 | 117 | gdb_test "break test_int3_end" \ |
d1e36019 | 118 | "Breakpoint.*at.* file .*$srcfile, line.*" |
1903f0e6 DE |
119 | |
120 | gdb_test "continue" \ | |
121 | "Continuing.*Breakpoint.*, test_int3 ().*" \ | |
122 | "continue to test_int3" | |
123 | ||
124 | gdb_test "continue" \ | |
125 | "Continuing.*Breakpoint.*, test_int3_end ().*" \ | |
126 | "continue to test_int3_end" | |
127 | ||
128 | ########################################## | |
129 | ||
35669430 DE |
130 | # Test rip-relative. |
131 | # GDB picks a spare register to hold the rip-relative address. | |
132 | # Exercise all the possibilities (rax-rdi, sans rsp). | |
133 | ||
134 | # The order must much the order in srcfile. | |
135 | set rip_regs { "rax" "rbx" "rcx" "rdx" "rbp" "rsi" "rdi" } | |
136 | ||
137 | # Assign val to all specified regs. | |
138 | ||
139 | proc set_regs { regs val } { | |
140 | global gdb_prompt | |
141 | ||
142 | foreach reg ${regs} { | |
143 | # Use send_gdb/gdb_expect so that these aren't logged as pass/fail. | |
144 | send_gdb "set \$${reg} = ${val}\n" | |
145 | gdb_expect 10 { | |
146 | -re "$gdb_prompt $" { | |
147 | verbose "Setting ${reg} to ${val}." 2 | |
148 | } | |
149 | timeout { | |
150 | warning "Couldn't set ${reg} to ${val}." | |
151 | } | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
cf141dd8 AB |
156 | # Verify all REGS equal VAL, except EXCEPT_REG which equals |
157 | # EXCEPT_REG_VAL. | |
158 | # | |
159 | # It is fine for EXCEPT_REG to be the empty string, in which case no | |
160 | # register will be checked for EXCEPT_REG_VAL. | |
35669430 | 161 | |
cf141dd8 | 162 | proc_with_prefix verify_regs { regs val except_reg except_reg_val } { |
35669430 DE |
163 | global newline |
164 | ||
165 | foreach reg ${regs} { | |
166 | set expected ${val} | |
167 | if { "${reg}" == "${except_reg}" } { | |
168 | set expected ${except_reg_val} | |
169 | } | |
170 | # The cast to (int) is because RBP is printed as a pointer. | |
cf141dd8 | 171 | gdb_test "p (int) \$${reg}" " = ${expected}${newline}" "${reg} expected value" |
35669430 DE |
172 | } |
173 | } | |
174 | ||
cf141dd8 AB |
175 | # Run the rip-relative tests. |
176 | # | |
177 | # TEST_START_LABEL and TEST_END_LABEL are two labels that delimit the | |
178 | # test in the srcfile. | |
179 | # | |
180 | # REG is either the name of a register which is the destination | |
181 | # location (when testing the add instruction), otherwise REG should be | |
182 | # the empty string, when testing the 'jmpq*' instruction. | |
183 | # | |
184 | # SIGNAL_MODES is a list which always contains 'off' and optionally | |
185 | # might also contain 'on'. The 'on' value is only included if the | |
186 | # target supports sending SIGALRM to the inferior. The test is | |
187 | # repeated for each signal mode. With signal mode 'on' we send a | |
188 | # signal to the inferior while it is performing a displaced step. | |
189 | proc rip_test { reg test_start_label test_end_label signal_modes } { | |
35669430 DE |
190 | global srcfile rip_regs |
191 | ||
35669430 | 192 | gdb_test "break ${test_start_label}" \ |
d1e36019 | 193 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 194 | gdb_test "break ${test_end_label}" \ |
d1e36019 | 195 | "Breakpoint.*at.* file .*$srcfile, line.*" |
35669430 | 196 | |
cf141dd8 AB |
197 | foreach_with_prefix send_signal $signal_modes { |
198 | if {$send_signal eq [lindex $signal_modes 0]} { | |
199 | # The first time through we can just continue to the | |
200 | # breakpoint. | |
201 | gdb_test "continue" \ | |
202 | "Continuing.*Breakpoint.*, ${test_start_label} ().*" \ | |
203 | "continue to ${test_start_label}" | |
204 | } else { | |
205 | # For the second time through the test we need to jump | |
206 | # back to the beginning. | |
207 | gdb_test "jump ${test_start_label}" \ | |
208 | "Breakpoint.*, ${test_start_label} ().*" \ | |
209 | "jump back to ${test_start_label}" | |
210 | } | |
211 | ||
212 | set_regs ${rip_regs} 0 | |
213 | ||
214 | if {$send_signal} { | |
215 | # The signal sending tests require that the signal appear to | |
216 | # arrive from an outside source, i.e. we can't use GDB's 'signal' | |
217 | # command to deliver it. | |
218 | # | |
219 | # The signal must arrive while GDB is processing the displaced | |
220 | # step instruction. | |
221 | # | |
222 | # If we use 'signal' to send the signal GDB doesn't actually do | |
223 | # the displaced step, but instead just delivers the signal. | |
224 | set inferior_pid [get_inferior_pid] | |
67be0489 RO |
225 | # Ensure that $inferior_pid refers to a single process. |
226 | gdb_assert {[expr $inferior_pid > 0]} \ | |
227 | "check for a sane inferior pid" | |
228 | if {$inferior_pid > 0} { | |
229 | remote_exec target "kill -ALRM $inferior_pid" | |
230 | } | |
cf141dd8 | 231 | } |
35669430 | 232 | |
cf141dd8 AB |
233 | gdb_test "continue" \ |
234 | "Continuing.*Breakpoint.*, ${test_end_label} ().*" \ | |
235 | "continue to ${test_end_label}" | |
35669430 | 236 | |
cf141dd8 AB |
237 | verify_regs ${rip_regs} 0 ${reg} 42 |
238 | } | |
239 | } | |
35669430 | 240 | |
cf141dd8 AB |
241 | if {![target_info exists gdb,nosignals] && ![istarget "*-*-mingw*"]} { |
242 | # Only targets that support SIGALRM can run the signal tests. | |
243 | set signal_modes { off on } | |
244 | } else { | |
245 | set signal_modes { off } | |
35669430 DE |
246 | } |
247 | ||
cf141dd8 AB |
248 | # The rip-relative add instructions. There's a test writing to |
249 | # each register in RIP_REGS in turn. | |
35669430 | 250 | foreach reg ${rip_regs} { |
cf141dd8 AB |
251 | with_test_prefix "add into ${reg}" { |
252 | rip_test $reg "test_rip_${reg}" "test_rip_${reg}_end" $signal_modes | |
253 | } | |
254 | } | |
255 | ||
256 | # Now test the rip-relative 'jmpq*' instruction. | |
257 | with_test_prefix "rip-relative jmpq*" { | |
258 | rip_test "" "test_jmp" "test_jmp_end" $signal_modes | |
35669430 DE |
259 | } |
260 | ||
261 | ########################################## | |
262 | ||
263 | # Done, run program to exit. | |
264 | ||
265 | gdb_continue_to_end "amd64-disp-step" |