Add a gdb.trace test for instruction relocation
[external/binutils.git] / gdb / testsuite / gdb.arch / insn-reloc.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3    Copyright 2015 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 (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 #endif
473
474 /* Functions testing relocations need to be placed here.  GDB will read
475    n_testcases to know how many fast tracepoints to place.  It will look
476    for symbols in the form of 'set_point\[0-9\]+' so each functions
477    needs one, starting at 0.  */
478
479 static testcase_ftype testcases[] = {
480 #if (defined __x86_64__ || defined __i386__)
481   can_relocate_call,
482   can_relocate_jump
483 #elif (defined __aarch64__)
484   can_relocate_b,
485   can_relocate_bcond,
486   can_relocate_cbz,
487   can_relocate_cbnz,
488   can_relocate_tbz,
489   can_relocate_tbnz,
490   can_relocate_adr_forward,
491   can_relocate_adr_backward,
492   can_relocate_adrp,
493   can_relocate_ldr
494 #endif
495 };
496
497 static size_t n_testcases = (sizeof (testcases) / sizeof (testcase_ftype));
498
499 int
500 main ()
501 {
502   int i = 0;
503
504   for (i = 0; i < n_testcases; i++)
505     testcases[i] ();
506
507   return 0;
508 }