1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2015-2023 Free Software Foundation, Inc.
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.
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.
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/>. */
21 typedef void (*testcase_ftype
)(void);
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. */
38 #if (defined __x86_64__ || defined __i386__)
41 #define SYMBOL(str) SYMBOL_PREFIX #str
43 #define SYMBOL(str) #str
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.
54 CALL f ; tracepoint here.
60 can_relocate_call (void)
64 asm (" .global " SYMBOL (set_point0
) "\n"
65 " jmp " SYMBOL (set_point0
) "\n"
69 SYMBOL (set_point0
) ":\n"
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.
84 JMP next ; tracepoint here.
91 can_relocate_jump (void)
95 asm (" .global " SYMBOL (set_point1
) "\n"
96 SYMBOL (set_point1
) ":\n"
97 ".byte 0xe9\n" /* jmp */
110 #elif (defined __aarch64__)
112 /* Make sure we can relocate a B instruction.
119 B set_ok ; tracepoint here.
126 can_relocate_b (void)
130 asm (" b set_point0\n"
146 /* Make sure we can relocate a B.cond instruction.
149 TST x0, #8 ; Clear the Z flag.
155 B.NE set_ok ; tracepoint here.
162 can_relocate_bcond_true (void)
186 /* Make sure we can relocate a CBZ instruction.
194 CBZ x0, set_ok ; tracepoint here.
201 can_relocate_cbz (void)
224 /* Make sure we can relocate a CBNZ instruction.
232 CBNZ x0, set_ok ; tracepoint here.
239 can_relocate_cbnz (void)
262 /* Make sure we can relocate a TBZ instruction.
265 MVN x0, x0 ; Clear bit 3.
271 TBZ x0, #3, set_ok ; tracepoint here.
278 can_relocate_tbz (void)
302 /* Make sure we can relocate a TBNZ instruction.
304 MOV x0, #8 ; Set bit 3.
310 TBNZ x0, #3, set_ok ; tracepoint here.
317 can_relocate_tbnz (void)
340 /* Make sure we can relocate an ADR instruction with a positive offset.
343 ADR x0, target ; tracepoint here.
344 BR x0 ; jump to target
354 can_relocate_adr_forward (void)
376 /* Make sure we can relocate an ADR instruction with a negative offset.
383 ADR x0, target ; tracepoint here.
384 BR x0 ; jump to target
391 can_relocate_adr_backward (void)
395 asm ("b set_point7\n"
414 /* Make sure we can relocate an ADRP instruction.
417 ADRP %[addr], set_point8 ; tracepoint here.
418 ADR %[pc], set_point8
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.
428 can_relocate_adrp (void)
434 " adrp %[page], set_point8\n"
435 " adr %[pc], set_point8\n"
436 : [page
] "=r" (page
), [pc
] "=r" (pc
));
438 if (page
== (pc
& ~0xfff))
444 /* Make sure we can relocate an LDR instruction, where the memory to
445 read is an offset from the current PC.
451 LDR %[result], data ; tracepoint here.
456 can_relocate_ldr (void)
460 asm ("b set_point9\n"
462 " .word 0x0cabba9e\n"
464 " ldr %w[result], 0b\n"
465 : [result
] "=r" (result
));
467 if (result
== 0x0cabba9e)
473 /* Make sure we can relocate a B.cond instruction and condition is false. */
476 can_relocate_bcond_false (void)
481 " tst x0, #8\n" /* Clear the Z flag. */
482 "set_point10:\n" /* Set tracepoint here. */
483 " b.eq 0b\n" /* Condition is false. */
504 /* Make sure we can relocate a BL instruction. */
507 can_relocate_bl (void)
509 asm ("set_point11:\n"
512 : : : "x30"); /* Test that LR is updated correctly. */
515 /* Make sure we can relocate a BR instruction.
519 BR x0 ; jump to target (tracepoint here).
529 can_relocate_br (void)
533 asm goto (" adr x0, %l0\n"
547 /* Make sure we can relocate a BLR instruction.
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.
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.
557 -- can_relocate_blr_jumps
560 BLR x0 ; jump to pass (tracepoint here).
562 -- can_relocate_blr_sets_lr
565 BLR x0 ; jumps somewhere else (tracepoint here).
566 BL pass ; ensures the LR was set correctly by the BLR.
571 can_relocate_blr_jumps (void)
575 /* Test BLR indeed jumps to the target. */
576 asm ("set_point13:\n"
578 : : [address
] "r" (&pass
) : "x30");
582 can_relocate_blr_sets_lr (void)
586 /* Test BLR sets the LR correctly. */
587 asm ("set_point14:\n"
590 : : [address
] "r" (&foo
) : "x30");
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. */
600 static testcase_ftype testcases
[] = {
601 #if (defined __x86_64__ || defined __i386__)
604 #elif (defined __aarch64__)
606 can_relocate_bcond_true
,
611 can_relocate_adr_forward
,
612 can_relocate_adr_backward
,
615 can_relocate_bcond_false
,
618 can_relocate_blr_jumps
,
619 can_relocate_blr_sets_lr
,
623 static size_t n_testcases
= (sizeof (testcases
) / sizeof (testcase_ftype
));
630 for (i
= 0; i
< n_testcases
; i
++)