Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.arch / insn-reloc.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3 Copyright 2015-2022 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <stddef.h>
19 #include <stdint.h>
20
21 typedef void (*testcase_ftype)(void);
22
23 /* Each function checks the correctness of the instruction being
24 relocated due to a fast tracepoint. Call function pass if it is
25 correct, otherwise call function fail. GDB sets a breakpoints on
26 pass and fail in order to check the correctness. */
27
28 static void
29 pass (void)
30 {
31 }
32
33 static void
34 fail (void)
35 {
36 }
37
38 #if (defined __x86_64__ || defined __i386__)
39
40 #ifdef SYMBOL_PREFIX
41 #define SYMBOL(str) SYMBOL_PREFIX #str
42 #else
43 #define SYMBOL(str) #str
44 #endif
45
46 /* Make sure we can relocate a CALL instruction. CALL instructions are
47 5 bytes long so we can always set a fast tracepoints on them.
48
49 JMP set_point0
50 f:
51 MOV $1, %[ok]
52 JMP end
53 set_point0:
54 CALL f ; tracepoint here.
55 end:
56
57 */
58
59 static void
60 can_relocate_call (void)
61 {
62 int ok = 0;
63
64 asm (" .global " SYMBOL (set_point0) "\n"
65 " jmp " SYMBOL (set_point0) "\n"
66 "0:\n"
67 " mov $1, %[ok]\n"
68 " jmp 1f\n"
69 SYMBOL (set_point0) ":\n"
70 " call 0b\n"
71 "1:\n"
72 : [ok] "=r" (ok));
73
74 if (ok == 1)
75 pass ();
76 else
77 fail ();
78 }
79
80 /* Make sure we can relocate a JMP instruction. We need the JMP
81 instruction to be 5 bytes long in order to set a fast tracepoint on
82 it. To do this, we emit the opcode directly.
83
84 JMP next ; tracepoint here.
85 next:
86 MOV $1, %[ok]
87
88 */
89
90 static void
91 can_relocate_jump (void)
92 {
93 int ok = 0;
94
95 asm (" .global " SYMBOL (set_point1) "\n"
96 SYMBOL (set_point1) ":\n"
97 ".byte 0xe9\n" /* jmp */
98 ".byte 0x00\n"
99 ".byte 0x00\n"
100 ".byte 0x00\n"
101 ".byte 0x00\n"
102 " mov $1, %[ok]\n"
103 : [ok] "=r" (ok));
104
105 if (ok == 1)
106 pass ();
107 else
108 fail ();
109 }
110 #elif (defined __aarch64__)
111
112 /* Make sure we can relocate a B instruction.
113
114 B set_point0
115 set_ok:
116 MOV %[ok], #1
117 B end
118 set_point0:
119 B set_ok ; tracepoint here.
120 MOV %[ok], #0
121 end
122
123 */
124
125 static void
126 can_relocate_b (void)
127 {
128 int ok = 0;
129
130 asm (" b set_point0\n"
131 "0:\n"
132 " mov %[ok], #1\n"
133 " b 1f\n"
134 "set_point0:\n"
135 " b 0b\n"
136 " mov %[ok], #0\n"
137 "1:\n"
138 : [ok] "=r" (ok));
139
140 if (ok == 1)
141 pass ();
142 else
143 fail ();
144 }
145
146 /* Make sure we can relocate a B.cond instruction.
147
148 MOV x0, #8
149 TST x0, #8 ; Clear the Z flag.
150 B set_point1
151 set_ok:
152 MOV %[ok], #1
153 B end
154 set_point1:
155 B.NE set_ok ; tracepoint here.
156 MOV %[ok], #0
157 end
158
159 */
160
161 static void
162 can_relocate_bcond_true (void)
163 {
164 int ok = 0;
165
166 asm (" mov x0, #8\n"
167 " tst x0, #8\n"
168 " b set_point1\n"
169 "0:\n"
170 " mov %[ok], #1\n"
171 " b 1f\n"
172 "set_point1:\n"
173 " b.ne 0b\n"
174 " mov %[ok], #0\n"
175 "1:\n"
176 : [ok] "=r" (ok)
177 :
178 : "0", "cc");
179
180 if (ok == 1)
181 pass ();
182 else
183 fail ();
184 }
185
186 /* Make sure we can relocate a CBZ instruction.
187
188 MOV x0, #0
189 B set_point2
190 set_ok:
191 MOV %[ok], #1
192 B end
193 set_point2:
194 CBZ x0, set_ok ; tracepoint here.
195 MOV %[ok], #0
196 end
197
198 */
199
200 static void
201 can_relocate_cbz (void)
202 {
203 int ok = 0;
204
205 asm (" mov x0, #0\n"
206 " b set_point2\n"
207 "0:\n"
208 " mov %[ok], #1\n"
209 " b 1f\n"
210 "set_point2:\n"
211 " cbz x0, 0b\n"
212 " mov %[ok], #0\n"
213 "1:\n"
214 : [ok] "=r" (ok)
215 :
216 : "0");
217
218 if (ok == 1)
219 pass ();
220 else
221 fail ();
222 }
223
224 /* Make sure we can relocate a CBNZ instruction.
225
226 MOV x0, #8
227 B set_point3
228 set_ok:
229 MOV %[ok], #1
230 B end
231 set_point3:
232 CBNZ x0, set_ok ; tracepoint here.
233 MOV %[ok], #0
234 end
235
236 */
237
238 static void
239 can_relocate_cbnz (void)
240 {
241 int ok = 0;
242
243 asm (" mov x0, #8\n"
244 " b set_point3\n"
245 "0:\n"
246 " mov %[ok], #1\n"
247 " b 1f\n"
248 "set_point3:\n"
249 " cbnz x0, 0b\n"
250 " mov %[ok], #0\n"
251 "1:\n"
252 : [ok] "=r" (ok)
253 :
254 : "0");
255
256 if (ok == 1)
257 pass ();
258 else
259 fail ();
260 }
261
262 /* Make sure we can relocate a TBZ instruction.
263
264 MOV x0, #8
265 MVN x0, x0 ; Clear bit 3.
266 B set_point4
267 set_ok:
268 MOV %[ok], #1
269 B end
270 set_point4:
271 TBZ x0, #3, set_ok ; tracepoint here.
272 MOV %[ok], #0
273 end
274
275 */
276
277 static void
278 can_relocate_tbz (void)
279 {
280 int ok = 0;
281
282 asm (" mov x0, #8\n"
283 " mvn x0, x0\n"
284 " b set_point4\n"
285 "0:\n"
286 " mov %[ok], #1\n"
287 " b 1f\n"
288 "set_point4:\n"
289 " tbz x0, #3, 0b\n"
290 " mov %[ok], #0\n"
291 "1:\n"
292 : [ok] "=r" (ok)
293 :
294 : "0");
295
296 if (ok == 1)
297 pass ();
298 else
299 fail ();
300 }
301
302 /* Make sure we can relocate a TBNZ instruction.
303
304 MOV x0, #8 ; Set bit 3.
305 B set_point5
306 set_ok:
307 MOV %[ok], #1
308 B end
309 set_point5:
310 TBNZ x0, #3, set_ok ; tracepoint here.
311 MOV %[ok], #0
312 end
313
314 */
315
316 static void
317 can_relocate_tbnz (void)
318 {
319 int ok = 0;
320
321 asm (" mov x0, #8\n"
322 " b set_point5\n"
323 "0:\n"
324 " mov %[ok], #1\n"
325 " b 1f\n"
326 "set_point5:\n"
327 " tbnz x0, #3, 0b\n"
328 " mov %[ok], #0\n"
329 "1:\n"
330 : [ok] "=r" (ok)
331 :
332 : "0");
333
334 if (ok == 1)
335 pass ();
336 else
337 fail ();
338 }
339
340 /* Make sure we can relocate an ADR instruction with a positive offset.
341
342 set_point6:
343 ADR x0, target ; tracepoint here.
344 BR x0 ; jump to target
345 MOV %[ok], #0
346 B end
347 target:
348 MOV %[ok], #1
349 end
350
351 */
352
353 static void
354 can_relocate_adr_forward (void)
355 {
356 int ok = 0;
357
358 asm ("set_point6:\n"
359 " adr x0, 0f\n"
360 " br x0\n"
361 " mov %[ok], #0\n"
362 " b 1f\n"
363 "0:\n"
364 " mov %[ok], #1\n"
365 "1:\n"
366 : [ok] "=r" (ok)
367 :
368 : "0");
369
370 if (ok == 1)
371 pass ();
372 else
373 fail ();
374 }
375
376 /* Make sure we can relocate an ADR instruction with a negative offset.
377
378 B set_point7
379 target:
380 MOV %[ok], #1
381 B end
382 set_point7:
383 ADR x0, target ; tracepoint here.
384 BR x0 ; jump to target
385 MOV %[ok], #0
386 end
387
388 */
389
390 static void
391 can_relocate_adr_backward (void)
392 {
393 int ok = 0;
394
395 asm ("b set_point7\n"
396 "0:\n"
397 " mov %[ok], #1\n"
398 " b 1f\n"
399 "set_point7:\n"
400 " adr x0, 0b\n"
401 " br x0\n"
402 " mov %[ok], #0\n"
403 "1:\n"
404 : [ok] "=r" (ok)
405 :
406 : "0");
407
408 if (ok == 1)
409 pass ();
410 else
411 fail ();
412 }
413
414 /* Make sure we can relocate an ADRP instruction.
415
416 set_point8:
417 ADRP %[addr], set_point8 ; tracepoint here.
418 ADR %[pc], set_point8
419
420 ADR computes the address of the given label. While ADRP gives us its
421 page, on a 4K boundary. We can check ADRP executed normally by
422 making sure the result of ADR and ADRP are equivalent, except for the
423 12 lowest bits which should be cleared.
424
425 */
426
427 static void
428 can_relocate_adrp (void)
429 {
430 uintptr_t page;
431 uintptr_t pc;
432
433 asm ("set_point8:\n"
434 " adrp %[page], set_point8\n"
435 " adr %[pc], set_point8\n"
436 : [page] "=r" (page), [pc] "=r" (pc));
437
438 if (page == (pc & ~0xfff))
439 pass ();
440 else
441 fail ();
442 }
443
444 /* Make sure we can relocate an LDR instruction, where the memory to
445 read is an offset from the current PC.
446
447 B set_point9
448 data:
449 .word 0x0cabba9e
450 set_point9:
451 LDR %[result], data ; tracepoint here.
452
453 */
454
455 static void
456 can_relocate_ldr (void)
457 {
458 uint32_t result = 0;
459
460 asm ("b set_point9\n"
461 "0:\n"
462 " .word 0x0cabba9e\n"
463 "set_point9:\n"
464 " ldr %w[result], 0b\n"
465 : [result] "=r" (result));
466
467 if (result == 0x0cabba9e)
468 pass ();
469 else
470 fail ();
471 }
472
473 /* Make sure we can relocate a B.cond instruction and condition is false. */
474
475 static void
476 can_relocate_bcond_false (void)
477 {
478 int ok = 0;
479
480 asm (" mov x0, #8\n"
481 " tst x0, #8\n" /* Clear the Z flag. */
482 "set_point10:\n" /* Set tracepoint here. */
483 " b.eq 0b\n" /* Condition is false. */
484 " mov %[ok], #1\n"
485 " b 1f\n"
486 "0:\n"
487 " mov %[ok], #0\n"
488 "1:\n"
489 : [ok] "=r" (ok)
490 :
491 : "0", "cc");
492
493 if (ok == 1)
494 pass ();
495 else
496 fail ();
497 }
498
499 static void
500 foo (void)
501 {
502 }
503
504 /* Make sure we can relocate a BL instruction. */
505
506 static void
507 can_relocate_bl (void)
508 {
509 asm ("set_point11:\n"
510 " bl foo\n"
511 " bl pass\n"
512 : : : "x30"); /* Test that LR is updated correctly. */
513 }
514
515 /* Make sure we can relocate a BR instruction.
516
517 ... Set x0 to target
518 set_point12:
519 BR x0 ; jump to target (tracepoint here).
520 fail()
521 return
522 target:
523 pass()
524 end
525
526 */
527
528 static void
529 can_relocate_br (void)
530 {
531 int ok = 0;
532
533 asm goto (" adr x0, %l0\n"
534 "set_point12:\n"
535 " br x0\n"
536 :
537 :
538 : "x0"
539 : madejump);
540
541 fail ();
542 return;
543 madejump:
544 pass ();
545 }
546
547 /* Make sure we can relocate a BLR instruction.
548
549 We use two different functions since the test runner expects one breakpoint
550 per function and we want to test two different things.
551 For BLR we want to test that the BLR actually jumps to the relevant
552 function, *and* that it sets the LR register correctly.
553
554 Hence we create one testcase that jumps to `pass` using BLR, and one
555 testcase that jumps to `pass` if BLR has set the LR correctly.
556
557 -- can_relocate_blr_jumps
558 ... Set x0 to pass
559 set_point13:
560 BLR x0 ; jump to pass (tracepoint here).
561
562 -- can_relocate_blr_sets_lr
563 ... Set x0 to foo
564 set_point14:
565 BLR x0 ; jumps somewhere else (tracepoint here).
566 BL pass ; ensures the LR was set correctly by the BLR.
567
568 */
569
570 static void
571 can_relocate_blr_jumps (void)
572 {
573 int ok = 0;
574
575 /* Test BLR indeed jumps to the target. */
576 asm ("set_point13:\n"
577 " blr %[address]\n"
578 : : [address] "r" (&pass) : "x30");
579 }
580
581 static void
582 can_relocate_blr_sets_lr (void)
583 {
584 int ok = 0;
585
586 /* Test BLR sets the LR correctly. */
587 asm ("set_point14:\n"
588 " blr %[address]\n"
589 " bl pass\n"
590 : : [address] "r" (&foo) : "x30");
591 }
592
593 #endif
594
595 /* Functions testing relocations need to be placed here. GDB will read
596 n_testcases to know how many fast tracepoints to place. It will look
597 for symbols in the form of 'set_point\[0-9\]+' so each functions
598 needs one, starting at 0. */
599
600 static testcase_ftype testcases[] = {
601 #if (defined __x86_64__ || defined __i386__)
602 can_relocate_call,
603 can_relocate_jump
604 #elif (defined __aarch64__)
605 can_relocate_b,
606 can_relocate_bcond_true,
607 can_relocate_cbz,
608 can_relocate_cbnz,
609 can_relocate_tbz,
610 can_relocate_tbnz,
611 can_relocate_adr_forward,
612 can_relocate_adr_backward,
613 can_relocate_adrp,
614 can_relocate_ldr,
615 can_relocate_bcond_false,
616 can_relocate_bl,
617 can_relocate_br,
618 can_relocate_blr_jumps,
619 can_relocate_blr_sets_lr,
620 #endif
621 };
622
623 static size_t n_testcases = (sizeof (testcases) / sizeof (testcase_ftype));
624
625 int
626 main ()
627 {
628 int i = 0;
629
630 for (i = 0; i < n_testcases; i++)
631 testcases[i] ();
632
633 return 0;
634 }
This page took 0.042158 seconds and 4 git commands to generate.