Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.arch / insn-reloc.c
CommitLineData
4f51c22a
PL
1/* This testcase is part of GDB, the GNU debugger.
2
88b9d363 3 Copyright 2015-2022 Free Software Foundation, Inc.
4f51c22a
PL
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
21typedef 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
28static void
29pass (void)
30{
31}
32
33static void
34fail (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
59static void
60can_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
90static void
91can_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
125static void
126can_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
161static void
8240f442 162can_relocate_bcond_true (void)
4f51c22a
PL
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
200static void
201can_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
238static void
239can_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
277static void
278can_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
316static void
317can_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
353static void
354can_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
390static void
391can_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
427static void
428can_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
455static void
456can_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}
8240f442
YQ
472
473/* Make sure we can relocate a B.cond instruction and condition is false. */
474
475static void
476can_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
499static void
500foo (void)
501{
502}
503
504/* Make sure we can relocate a BL instruction. */
505
506static void
507can_relocate_bl (void)
508{
509 asm ("set_point11:\n"
510 " bl foo\n"
bb11dd58
YQ
511 " bl pass\n"
512 : : : "x30"); /* Test that LR is updated correctly. */
8240f442
YQ
513}
514
807f647c
MM
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
528static void
529can_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;
543madejump:
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
570static void
571can_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
581static void
582can_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
4f51c22a
PL
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
600static 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,
8240f442 606 can_relocate_bcond_true,
4f51c22a
PL
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,
8240f442
YQ
614 can_relocate_ldr,
615 can_relocate_bcond_false,
616 can_relocate_bl,
807f647c
MM
617 can_relocate_br,
618 can_relocate_blr_jumps,
619 can_relocate_blr_sets_lr,
4f51c22a
PL
620#endif
621};
622
623static size_t n_testcases = (sizeof (testcases) / sizeof (testcase_ftype));
624
625int
626main ()
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 1.000932 seconds and 4 git commands to generate.