1 // Copyright 2023, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "test-debugger-aarch64.h"
28
29 namespace vixl {
30 namespace aarch64 {
31
32 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
33 // The debugger is only available to be tested in simulator builds.
34
TEST(breakpoints_invalid)35 TEST(breakpoints_invalid) {
36 SETUP();
37
38 // Test invalid strings instead of numbers.
39 SETUP_CMD("break a", "Error: Use `break <address>` to set a breakpoint");
40 SETUP_CMD("break abcdef", "Error: Use `break <address>` to set a breakpoint");
41 SETUP_CMD("break A", "Error: Use `break <address>` to set a breakpoint");
42 SETUP_CMD("break ABCDEF", "Error: Use `break <address>` to set a breakpoint");
43 SETUP_CMD("break 0x", "Error: Use `break <address>` to set a breakpoint");
44 SETUP_CMD("break 0xg", "Error: Use `break <address>` to set a breakpoint");
45
46 // Test different amounts of parameters.
47 SETUP_CMD("break", "Error: Use `break <address>` to set a breakpoint");
48 SETUP_CMD("break 42 52", "Error: Use `break <address>` to set a breakpoint");
49
50 // Test out of range addresses.
51 SETUP_CMD("break 0xFFFFFFFFFFFFFFFF1",
52 "Error: Use `break <address>` to set a breakpoint");
53 SETUP_CMD("break 18446744073709551616",
54 "Error: Use `break <address>` to set a breakpoint");
55
56 // Continue to exit the debugger.
57 SETUP_CMD("continue", "Continuing...");
58 RUN();
59
60 CHECK_OUTPUT();
61 }
62
TEST(breakpoints_valid)63 TEST(breakpoints_valid) {
64 SETUP();
65
66 // Test bottom boundary of addresses.
67 SETUP_CMD("break 0x0", "Breakpoint successfully added at: 0x0");
68 SETUP_CMD("break 0", "Breakpoint successfully removed at: 0x0");
69 SETUP_CMD("break 0x1", "Breakpoint successfully added at: 0x1");
70 SETUP_CMD("break 1", "Breakpoint successfully removed at: 0x1");
71
72 // Test top boundary of addresses.
73 SETUP_CMD("break 0xFFFFFFFFFFFFFFFF",
74 "Breakpoint successfully added at: 0xffffffffffffffff");
75 SETUP_CMD("break 18446744073709551615",
76 "Breakpoint successfully removed at: 0xffffffffffffffff");
77
78 // Continue to exit the debugger.
79 SETUP_CMD("continue", "Continuing...");
80 RUN();
81
82 CHECK_OUTPUT();
83 }
84
TEST(breakpoints_hit)85 TEST(breakpoints_hit) {
86 SETUP();
87
88 // Test hitting a breakpoint.
89 std::string mov_addr = GET_INSTRUCTION_ADDRESS("mov x2, #0x2");
90 std::string break_cmd = "break ";
91 break_cmd += mov_addr;
92 std::string expected_trace = "Breakpoint successfully added at: ";
93 expected_trace += mov_addr;
94 SETUP_CMD(break_cmd, expected_trace);
95 SETUP_CMD("continue",
96 "Continuing...\n"
97 "Debugger hit breakpoint, breaking...");
98
99 // Continue to exit the debugger.
100 SETUP_CMD("continue", "Continuing...");
101 RUN();
102
103 CHECK_OUTPUT();
104 }
105
TEST(cmd_aliases)106 TEST(cmd_aliases) {
107 SETUP();
108
109 // Test all short form commands, to ensure they correctly run their long form
110 // counterparts.
111 SETUP_CMD("b", "Error: Use `break <address>` to set a breakpoint");
112 SETUP_CMD("s x",
113 "Error: use `step \\[number\\]` to step an optional number of"
114 " instructions");
115 SETUP_CMD("p",
116 "Error: use `print <register|all>` to print the contents of a"
117 " specific register or all registers.");
118 SETUP_CMD("t 1", "Error: use `trace` to toggle tracing of registers.");
119 SETUP_CMD("g 1",
120 "Error: use `gdb` to enter GDB from the simulator debugger.");
121
122 // Continue to exit the debugger.
123 SETUP_CMD("c", "Continuing...");
124 RUN();
125
126 CHECK_OUTPUT();
127 }
128
TEST(stepping_single)129 TEST(stepping_single) {
130 SETUP();
131
132 // Test single stepping through the whole program.
133 SETUP_CMD("step", ".*mov x2, #0x2");
134 SETUP_CMD("step", ".*sub x3, x1, x2");
135 SETUP_CMD("step", ".*ret");
136 SETUP_CMD("step",
137 ".*Debugger at the end of simulation, leaving simulator...");
138
139 RUN();
140
141 CHECK_OUTPUT();
142 }
143
TEST(stepping_single_and_continue)144 TEST(stepping_single_and_continue) {
145 SETUP();
146
147 // Test single stepping and then continuing.
148 SETUP_CMD("step", ".*mov x2, #0x2");
149 SETUP_CMD("continue", "Continuing...");
150
151 RUN();
152
153 CHECK_OUTPUT();
154 }
155
TEST(stepping_multi_1)156 TEST(stepping_multi_1) {
157 SETUP();
158
159 // Test multi stepping a single instruction.
160 SETUP_CMD("step 1", ".*mov x2, #0x2");
161
162 // Continue to exit the debugger.
163 SETUP_CMD("continue", "Continuing...");
164 RUN();
165
166 CHECK_OUTPUT();
167 }
168
TEST(stepping_multi_2)169 TEST(stepping_multi_2) {
170 SETUP();
171
172 // Test multi stepping two instructions.
173 SETUP_CMD("step 2",
174 ".*mov x2, #0x2\n"
175 ".*sub x3, x1, x2");
176
177 // Continue to exit the debugger.
178 SETUP_CMD("continue", "Continuing...");
179 RUN();
180
181 CHECK_OUTPUT();
182 }
183
TEST(stepping_multi_3)184 TEST(stepping_multi_3) {
185 SETUP();
186
187 // Test multi stepping three instructions.
188 SETUP_CMD("step 3",
189 ".*mov x2, #0x2\n"
190 ".*sub x3, x1, x2\n"
191 ".*ret");
192
193 // Continue to exit the debugger.
194 SETUP_CMD("continue", "Continuing...");
195 RUN();
196
197 CHECK_OUTPUT();
198 }
199
TEST(stepping_multi_4)200 TEST(stepping_multi_4) {
201 SETUP();
202
203 // Test stepping through the whole program in one go.
204 SETUP_CMD("step 4",
205 ".*mov x2, #0x2\n"
206 ".*sub x3, x1, x2\n"
207 ".*ret\n"
208 "Debugger at the end of simulation, leaving simulator...");
209
210 RUN();
211
212 CHECK_OUTPUT();
213 }
214
TEST(stepping_multi_5)215 TEST(stepping_multi_5) {
216 SETUP();
217
218 // Test multi stepping past the end of the program.
219 SETUP_CMD("step 5",
220 ".*mov x2, #0x2\n"
221 ".*sub x3, x1, x2\n"
222 ".*ret\n"
223 "Debugger at the end of simulation, leaving simulator...");
224
225 RUN();
226
227 CHECK_OUTPUT();
228 }
229
TEST(stepping_invalid)230 TEST(stepping_invalid) {
231 SETUP();
232
233 // Test invalid arguments to step command.
234 SETUP_CMD("step 1 2",
235 "Error: use `step \\[number\\]` to step an optional number of"
236 " instructions");
237
238 // Continue to exit the debugger.
239 SETUP_CMD("continue", "Continuing...");
240 RUN();
241
242 CHECK_OUTPUT();
243 }
244
TEST(print_invalid)245 TEST(print_invalid) {
246 SETUP();
247
248 // Test invalid amounts of arguments to the print command.
249 SETUP_CMD("print",
250 "Error: use `print <register|all>` to print the contents of a"
251 " specific register or all registers.");
252 SETUP_CMD("print all all",
253 "Error: use `print <register|all>` to print the contents of a"
254 " specific register or all registers.");
255
256 // Test invalid types of registers.
257 SETUP_CMD("print alls",
258 "Error: incorrect register format, use e.g: X0, x0, etc...");
259 SETUP_CMD("print a",
260 "Error: incorrect register format, use e.g: X0, x0, etc...");
261 SETUP_CMD("print x",
262 "Error: incorrect register format, use e.g: X0, x0, etc...");
263 SETUP_CMD("print 0",
264 "Error: incorrect register format, use e.g: X0, x0, etc...");
265
266 // Test registers that don't exist on AARCH64.
267 SETUP_CMD("print w32",
268 "Error: incorrect register format, use e.g: X0, x0, etc...");
269 SETUP_CMD("print W32",
270 "Error: incorrect register format, use e.g: X0, x0, etc...");
271 SETUP_CMD("print x32",
272 "Error: incorrect register format, use e.g: X0, x0, etc...");
273 SETUP_CMD("print X32",
274 "Error: incorrect register format, use e.g: X0, x0, etc...");
275 SETUP_CMD("print v32",
276 "Error: incorrect register format, use e.g: X0, x0, etc...");
277 SETUP_CMD("print V32",
278 "Error: incorrect register format, use e.g: X0, x0, etc...");
279
280 // Continue to exit the debugger.
281 SETUP_CMD("continue", "Continuing...");
282 RUN();
283
284 CHECK_OUTPUT();
285 }
286
TEST(trace_invalid)287 TEST(trace_invalid) {
288 SETUP();
289
290 // Test invalid arguments to trace command.
291 SETUP_CMD("trace 1 2", "Error: use `trace` to toggle tracing of registers.");
292
293 // Continue to exit the debugger.
294 SETUP_CMD("continue", "Continuing...");
295 RUN();
296
297 CHECK_OUTPUT();
298 }
299
TEST(trace_toggling)300 TEST(trace_toggling) {
301 SETUP();
302
303 // Test toggling tracing.
304 SETUP_CMD("trace",
305 "Enabling disassembly, registers and memory write tracing");
306 SETUP_CMD("trace",
307 "Disabling disassembly, registers and memory write tracing");
308 SETUP_CMD("trace",
309 "Enabling disassembly, registers and memory write tracing");
310 SETUP_CMD("trace",
311 "Disabling disassembly, registers and memory write tracing");
312
313 // Continue to exit the debugger.
314 SETUP_CMD("continue", "Continuing...");
315 RUN();
316
317 CHECK_OUTPUT();
318 }
319
TEST(trace_full)320 TEST(trace_full) {
321 SETUP();
322
323 // Test tracing the whole program.
324 SETUP_CMD("trace",
325 "Enabling disassembly, registers and memory write tracing");
326
327 std::string expected_trace = "Continuing...\n";
328 expected_trace += ".*add x1, x0, #0x5 \\(5\\)\n";
329 expected_trace += "(" + x_register_trace + "\\n){32}";
330 expected_trace += "(" + v_register_trace + "\\n){32}";
331 expected_trace += ".*mov x2, #0x2\n";
332 expected_trace += x_register_trace + "\n";
333 expected_trace += ".*sub x3, x1, x2\n";
334 expected_trace += x_register_trace + "\n";
335 expected_trace += ".*ret\n";
336 expected_trace += "# Branch to 0x0000000000000000.";
337 SETUP_CMD("continue", expected_trace);
338
339 RUN();
340
341 CHECK_OUTPUT();
342 }
343
TEST(trace_partial)344 TEST(trace_partial) {
345 SETUP();
346
347 // Test tracing a single line.
348 SETUP_CMD("trace",
349 "Enabling disassembly, registers and memory write tracing");
350
351 std::string expected_trace = ".*add x1, x0, #0x5 \\(5\\)\n";
352 expected_trace += "(" + x_register_trace + "\\n){32}";
353 expected_trace += "(" + v_register_trace + "\\n){32}";
354 expected_trace += ".*mov x2, #0x2\n";
355 SETUP_CMD("step", expected_trace);
356 SETUP_CMD("trace",
357 "Disabling disassembly, registers and memory write tracing");
358 SETUP_CMD("continue", "Continuing...\n");
359
360 RUN();
361
362 CHECK_OUTPUT();
363 }
364
365 #endif // VIXL_INCLUDE_SIMULATOR_AARCH64
366
367 } // namespace aarch64
368 } // namespace vixl
369