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
29namespace vixl {
30namespace aarch64 {
31
32#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
33// The debugger is only available to be tested in simulator builds.
34
35TEST(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
63TEST(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
85TEST(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
106TEST(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
129TEST(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
144TEST(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
156TEST(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
169TEST(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
184TEST(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
200TEST(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
215TEST(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
230TEST(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
245TEST(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
287TEST(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
300TEST(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
320TEST(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
344TEST(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