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