1 /* libunwind - a platform-independent unwind library
2 Copyright (C) 2004-2005 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5 This file is part of libunwind.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25
26 /* This file tests corner-cases of NaT-bit handling. */
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <libunwind.h>
34 #include "compiler.h"
35
36 #ifdef HAVE_SYS_UC_ACCESS_H
37 # include <sys/uc_access.h>
38 #endif
39
40 #include "tdep-ia64/rse.h"
41
42 #define NUM_RUNS 1024
43 //#define NUM_RUNS 1
44 #define MAX_CHECKS 1024
45 //#define MAX_CHECKS 2
46 #define MAX_VALUES_PER_FUNC 4
47
48 #define panic(args...) \
49 do { printf (args); ++nerrors; } while (0)
50
51 typedef void save_func_t (void *funcs, unsigned long *vals);
52 typedef unw_word_t *check_func_t (unw_cursor_t *c, unsigned long *vals);
53
54 extern void flushrs (void);
55
56 extern save_func_t save_static_to_stacked;
57 static check_func_t check_static_to_stacked;
58
59 extern save_func_t save_static_to_fr;
60 static check_func_t check_static_to_fr;
61
62 extern save_func_t save_static_to_br;
63 static check_func_t check_static_to_br;
64
65 extern save_func_t save_static_to_mem;
66 static check_func_t check_static_to_mem;
67
68 extern save_func_t save_static_to_mem2;
69 static check_func_t check_static_to_mem2;
70
71 extern save_func_t save_static_to_mem3;
72 static check_func_t check_static_to_mem3;
73
74 extern save_func_t save_static_to_mem4;
75 static check_func_t check_static_to_mem4;
76
77 extern save_func_t save_static_to_mem5;
78 static check_func_t check_static_to_mem5;
79
80 extern save_func_t save_static_to_scratch;
81 static check_func_t check_static_to_scratch;
82
83 extern save_func_t rotate_regs;
84 static check_func_t check_rotate_regs;
85
86 extern save_func_t save_pr;
87 static check_func_t check_pr;
88
89 static int verbose;
90 static int nerrors;
91
92 static int num_checks;
93 static save_func_t *funcs[MAX_CHECKS + 1];
94 static check_func_t *checks[MAX_CHECKS];
95 static unw_word_t values[MAX_CHECKS*MAX_VALUES_PER_FUNC];
96
97 static struct
98 {
99 save_func_t *func;
100 check_func_t *check;
101 }
102 all_funcs[] =
103 {
104 { save_static_to_stacked, check_static_to_stacked },
105 { save_static_to_fr, check_static_to_fr },
106 { save_static_to_br, check_static_to_br },
107 { save_static_to_mem, check_static_to_mem },
108 { save_static_to_mem2, check_static_to_mem2 },
109 { save_static_to_mem3, check_static_to_mem3 },
110 { save_static_to_mem4, check_static_to_mem4 },
111 { save_static_to_mem5, check_static_to_mem5 },
112 { save_static_to_scratch, check_static_to_scratch },
113 { save_pr, check_pr },
114 { rotate_regs, check_rotate_regs },
115 };
116
117 static unw_word_t
random_word(void)118 random_word (void)
119 {
120 unw_word_t val = random ();
121
122 if (sizeof (unw_word_t) > 4)
123 val |= ((unw_word_t) random ()) << 32;
124
125 return val;
126 }
127
128 void
sighandler(int signal,void * siginfo,void * context)129 sighandler (int signal, void *siginfo, void *context)
130 {
131 unsigned long *bsp, *arg1;
132 save_func_t **arg0;
133 ucontext_t *uc = context;
134
135 #if defined(__linux)
136 {
137 long sof;
138 int sp;
139
140 if (verbose)
141 printf ("sighandler: signal %d sp=%p nat=%08lx pr=%lx\n",
142 signal, &sp, uc->uc_mcontext.sc_nat, uc->uc_mcontext.sc_pr);
143 sof = uc->uc_mcontext.sc_cfm & 0x7f;
144 bsp = (unsigned long *) rse_skip_regs (uc->uc_mcontext.sc_ar_bsp, -sof);
145 }
146 #elif defined(__hpux)
147 if (__uc_get_ar (uc, UNW_IA64_AR_BSP - UNW_IA64_AR, &bsp) != 0)
148 {
149 panic ("%s: reading of ar.bsp failed, errno=%d", __FUNCTION__, errno);
150 return;
151 }
152 #endif
153
154 flushrs ();
155 arg0 = (save_func_t **) *bsp;
156 bsp = (unsigned long *) rse_skip_regs ((uint64_t) bsp, 1);
157 arg1 = (unsigned long *) *bsp;
158
159 (*arg0[0]) (arg0 + 1, arg1);
160
161 /* skip over the instruction which triggered sighandler() */
162 #if defined(__linux)
163 ++uc->uc_mcontext.sc_ip;
164 #elif defined(HAVE_SYS_UC_ACCESS_H)
165 {
166 unsigned long ip;
167
168 if (__uc_get_ip (uc, &ip) != 0)
169 {
170 panic ("%s: reading of ip failed, errno=%d", __FUNCTION__, errno);
171 return;
172 }
173 if (__uc_set_ip (uc, ip) != 0)
174 {
175 panic ("%s: writing of ip failed, errno=%d", __FUNCTION__, errno);
176 return;
177 }
178 }
179 #endif
180 }
181
182 static void
enable_sighandler(void)183 enable_sighandler (void)
184 {
185 struct sigaction act;
186
187 memset (&act, 0, sizeof (act));
188 act.sa_handler = (void (*)(int)) sighandler;
189 act.sa_flags = SA_SIGINFO | SA_NODEFER;
190 if (sigaction (SIGSEGV, &act, NULL) < 0)
191 panic ("sigaction: %s\n", strerror (errno));
192 }
193
194 static void
disable_sighandler(void)195 disable_sighandler (void)
196 {
197 struct sigaction act;
198
199 memset (&act, 0, sizeof (act));
200 act.sa_handler = SIG_DFL;
201 act.sa_flags = SA_SIGINFO | SA_NODEFER;
202 if (sigaction (SIGSEGV, &act, NULL) < 0)
203 panic ("sigaction: %s\n", strerror (errno));
204 }
205
206 static unw_word_t *
check_static_to_stacked(unw_cursor_t * c,unw_word_t * vals)207 check_static_to_stacked (unw_cursor_t *c, unw_word_t *vals)
208 {
209 unw_word_t r[4];
210 unw_word_t nat[4];
211 int i, ret;
212
213 if (verbose)
214 printf (" %s()\n", __FUNCTION__);
215
216 vals -= 4;
217
218 for (i = 0; i < 4; ++i)
219 if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0)
220 panic ("%s: failed to read register r%d, error=%d\n",
221 __FUNCTION__, 4 + i, ret);
222
223 for (i = 0; i < 4; ++i)
224 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0)
225 panic ("%s: failed to read register nat%d, error=%d\n",
226 __FUNCTION__, 4 + i, ret);
227
228 for (i = 0; i < 4; ++i)
229 {
230 if (verbose)
231 printf (" r%d = %c%016lx (expected %c%016lx)\n",
232 4 + i, nat[i] ? '*' : ' ', r[i],
233 (vals[i] & 1) ? '*' : ' ', vals[i]);
234
235 if (vals[i] & 1)
236 {
237 if (!nat[i])
238 panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
239 }
240 else
241 {
242 if (nat[i])
243 panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
244 if (r[i] != vals[i])
245 panic ("%s: r%d=%lx instead of %lx!\n",
246 __FUNCTION__, 4 + i, r[i], vals[i]);
247 }
248 }
249 return vals;
250 }
251
252 static unw_word_t *
check_static_to_fr(unw_cursor_t * c,unw_word_t * vals)253 check_static_to_fr (unw_cursor_t *c, unw_word_t *vals)
254 {
255 unw_word_t r4;
256 unw_word_t nat4;
257 int ret;
258
259 if (verbose)
260 printf (" %s()\n", __FUNCTION__);
261
262 vals -= 1;
263
264 if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0)
265 panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret);
266
267 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0)
268 panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret);
269
270 if (verbose)
271 printf (" r4 = %c%016lx (expected %c%016lx)\n",
272 nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
273
274 if (vals[0] & 1)
275 {
276 if (!nat4)
277 panic ("%s: r4 not a NaT!\n", __FUNCTION__);
278 }
279 else
280 {
281 if (nat4)
282 panic ("%s: r4 a NaT!\n", __FUNCTION__);
283 if (r4 != vals[0])
284 panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
285 }
286 return vals;
287 }
288
289 static unw_word_t *
check_static_to_br(unw_cursor_t * c,unw_word_t * vals)290 check_static_to_br (unw_cursor_t *c, unw_word_t *vals)
291 {
292 unw_word_t r4, nat4;
293 int ret;
294
295 if (verbose)
296 printf (" %s()\n", __FUNCTION__);
297
298 vals -= 1;
299
300 if ((ret = unw_get_reg (c, UNW_IA64_GR + 4, &r4)) < 0)
301 panic ("%s: failed to read register r4, error=%d\n", __FUNCTION__, ret);
302
303 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4, &nat4)) < 0)
304 panic ("%s: failed to read register nat4, error=%d\n", __FUNCTION__, ret);
305
306 if (verbose)
307 printf (" r4 = %c%016lx (expected %c%016lx)\n",
308 nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
309
310 if (vals[0] & 1)
311 {
312 if (!nat4)
313 panic ("%s: r4 not a NaT!\n", __FUNCTION__);
314 }
315 else
316 {
317 if (nat4)
318 panic ("%s: r4 a NaT!\n", __FUNCTION__);
319 if (r4 != vals[0])
320 panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
321 }
322 return vals;
323 }
324
325 static unw_word_t *
check_static_to_mem(unw_cursor_t * c,unw_word_t * vals)326 check_static_to_mem (unw_cursor_t *c, unw_word_t *vals)
327 {
328 unw_word_t r5, nat5;
329 int ret;
330
331 if (verbose)
332 printf (" %s()\n", __FUNCTION__);
333
334 vals -= 1;
335
336 if ((ret = unw_get_reg (c, UNW_IA64_GR + 5, &r5)) < 0)
337 panic ("%s: failed to read register r5, error=%d\n", __FUNCTION__, ret);
338
339 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 5, &nat5)) < 0)
340 panic ("%s: failed to read register nat5, error=%d\n", __FUNCTION__, ret);
341
342 if (verbose)
343 printf (" r5 = %c%016lx (expected %c%016lx)\n",
344 nat5 ? '*' : ' ', r5, (vals[0] & 1) ? '*' : ' ', vals[0]);
345
346 if (vals[0] & 1)
347 {
348 if (!nat5)
349 panic ("%s: r5 not a NaT!\n", __FUNCTION__);
350 }
351 else
352 {
353 if (nat5)
354 panic ("%s: r5 a NaT!\n", __FUNCTION__);
355 if (r5 != vals[0])
356 panic ("%s: r5=%lx instead of %lx!\n", __FUNCTION__, r5, vals[0]);
357 }
358 return vals;
359 }
360
361 static unw_word_t *
check_static_to_memN(unw_cursor_t * c,unw_word_t * vals,const char * func)362 check_static_to_memN (unw_cursor_t *c, unw_word_t *vals, const char *func)
363 {
364 unw_word_t r6, nat6;
365 int ret;
366
367 if (verbose)
368 printf (" %s()\n", func);
369
370 vals -= 1;
371
372 if ((ret = unw_get_reg (c, UNW_IA64_GR + 6, &r6)) < 0)
373 panic ("%s: failed to read register r6, error=%d\n", __FUNCTION__, ret);
374
375 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 6, &nat6)) < 0)
376 panic ("%s: failed to read register nat6, error=%d\n", __FUNCTION__, ret);
377
378 if (verbose)
379 printf (" r6 = %c%016lx (expected %c%016lx)\n",
380 nat6 ? '*' : ' ', r6, (vals[0] & 1) ? '*' : ' ', vals[0]);
381
382 if (vals[0] & 1)
383 {
384 if (!nat6)
385 panic ("%s: r6 not a NaT!\n", __FUNCTION__);
386 }
387 else
388 {
389 if (nat6)
390 panic ("%s: r6 a NaT!\n", __FUNCTION__);
391 if (r6 != vals[0])
392 panic ("%s: r6=%lx instead of %lx!\n", __FUNCTION__, r6, vals[0]);
393 }
394 return vals;
395 }
396
397 static unw_word_t *
check_static_to_mem2(unw_cursor_t * c,unw_word_t * vals)398 check_static_to_mem2 (unw_cursor_t *c, unw_word_t *vals)
399 {
400 return check_static_to_memN (c, vals, __FUNCTION__);
401 }
402
403 static unw_word_t *
check_static_to_mem3(unw_cursor_t * c,unw_word_t * vals)404 check_static_to_mem3 (unw_cursor_t *c, unw_word_t *vals)
405 {
406 return check_static_to_memN (c, vals, __FUNCTION__);
407 }
408
409 static unw_word_t *
check_static_to_mem4(unw_cursor_t * c,unw_word_t * vals)410 check_static_to_mem4 (unw_cursor_t *c, unw_word_t *vals)
411 {
412 return check_static_to_memN (c, vals, __FUNCTION__);
413 }
414
415 static unw_word_t *
check_static_to_mem5(unw_cursor_t * c,unw_word_t * vals)416 check_static_to_mem5 (unw_cursor_t *c, unw_word_t *vals)
417 {
418 return check_static_to_memN (c, vals, __FUNCTION__);
419 }
420
421 static unw_word_t *
check_static_to_scratch(unw_cursor_t * c,unw_word_t * vals)422 check_static_to_scratch (unw_cursor_t *c, unw_word_t *vals)
423 {
424 unw_word_t r[4], nat[4], ec, expected;
425 unw_fpreg_t f4;
426 int i, ret;
427
428 if (verbose)
429 printf (" %s()\n", __FUNCTION__);
430
431 vals -= 4;
432
433 while (!unw_is_signal_frame (c))
434 if ((ret = unw_step (c)) < 0)
435 panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n",
436 __FUNCTION__, ret);
437 if ((ret = unw_step (c)) < 0)
438 panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n",
439 __FUNCTION__, ret);
440
441 for (i = 0; i < 4; ++i)
442 if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0)
443 panic ("%s: failed to read register r%d, error=%d\n",
444 __FUNCTION__, 4 + i, ret);
445
446 for (i = 0; i < 4; ++i)
447 if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0)
448 panic ("%s: failed to read register nat%d, error=%d\n",
449 __FUNCTION__, 4 + i, ret);
450
451 for (i = 0; i < 4; ++i)
452 {
453 if (verbose)
454 printf (" r%d = %c%016lx (expected %c%016lx)\n",
455 4 + i, nat[i] ? '*' : ' ', r[i],
456 (vals[i] & 1) ? '*' : ' ', vals[i]);
457
458 if (vals[i] & 1)
459 {
460 if (!nat[i])
461 panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
462 }
463 else
464 {
465 if (nat[i])
466 panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
467 if (r[i] != vals[i])
468 panic ("%s: r%d=%lx instead of %lx!\n",
469 __FUNCTION__, 4 + i, r[i], vals[i]);
470 }
471 }
472 if ((ret = unw_get_fpreg (c, UNW_IA64_FR + 4, &f4)) < 0)
473 panic ("%s: failed to read f4, error=%d\n", __FUNCTION__, ret);
474
475 /* These tests are little-endian specific: */
476 if (nat[0])
477 {
478 if (f4.raw.bits[0] != 0 || f4.raw.bits[1] != 0x1fffe)
479 panic ("%s: f4=%016lx.%016lx instead of NaTVal!\n",
480 __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0]);
481 }
482 else
483 {
484 if (f4.raw.bits[0] != r[0] || f4.raw.bits[1] != 0x1003e)
485 panic ("%s: f4=%016lx.%016lx instead of %lx!\n",
486 __FUNCTION__, f4.raw.bits[1], f4.raw.bits[0], r[0]);
487 }
488
489 if ((unw_get_reg (c, UNW_IA64_AR_EC, &ec)) < 0)
490 panic ("%s: failed to read register ar.ec, error=%d\n", __FUNCTION__, ret);
491
492 expected = vals[0] & 0x3f;
493 if (ec != expected)
494 panic ("%s: ar.ec=%016lx instead of %016lx!\n",
495 __FUNCTION__, ec, expected);
496
497 return vals;
498 }
499
500 static unw_word_t *
check_pr(unw_cursor_t * c,unw_word_t * vals)501 check_pr (unw_cursor_t *c, unw_word_t *vals)
502 {
503 unw_word_t pr, expected;
504 int ret;
505 # define BIT(n) ((unw_word_t) 1 << (n))
506 # define DONTCARE (BIT( 6) | BIT( 7) | BIT( 8) | BIT( 9) | BIT(10) \
507 | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15))
508
509 if (verbose)
510 printf (" %s()\n", __FUNCTION__);
511
512 vals -= 1;
513
514 if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0)
515 panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret);
516
517 pr &= ~DONTCARE;
518 expected = (vals[0] & ~DONTCARE) | 1;
519
520 if (verbose)
521 printf (" pr = %016lx (expected %016lx)\n", pr, expected);
522
523 if (pr != expected)
524 panic ("%s: pr=%lx instead of %lx!\n", __FUNCTION__, pr, expected);
525
526 if ((ret = unw_set_reg (c, UNW_IA64_PR, vals[0])) < 0)
527 panic ("%s: failed to write register pr, error=%d\n", __FUNCTION__, ret);
528
529 if ((ret = unw_get_reg (c, UNW_IA64_PR, &pr)) < 0)
530 panic ("%s: failed to read register pr, error=%d\n", __FUNCTION__, ret);
531
532 if (pr != vals[0])
533 panic ("%s: secondary pr=%lx instead of %lx!\n",
534 __FUNCTION__, pr, vals[0]);
535 return vals;
536 }
537
538 static unw_word_t *
check_rotate_regs(unw_cursor_t * c,unw_word_t * vals)539 check_rotate_regs (unw_cursor_t *c, unw_word_t *vals)
540 {
541 if (verbose)
542 printf (" %s()\n", __FUNCTION__);
543 return check_pr (c, vals - 1);
544 }
545
546 static void
start_checks(void * funcs,unsigned long * vals)547 start_checks (void *funcs, unsigned long *vals)
548 {
549 unw_context_t uc;
550 unw_cursor_t c;
551 int i, ret;
552
553 disable_sighandler ();
554
555 unw_getcontext (&uc);
556
557 if ((ret = unw_init_local (&c, &uc)) < 0)
558 panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret);
559
560 if ((ret = unw_step (&c)) < 0)
561 panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
562
563 for (i = 0; i < num_checks; ++i)
564 {
565 vals = (*checks[num_checks - 1 - i]) (&c, vals);
566
567 if ((ret = unw_step (&c)) < 0)
568 panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
569 }
570 }
571
572 static void
run_check(int test)573 run_check (int test)
574 {
575 int index, i;
576
577 if (test == 1)
578 /* Make first test always go the full depth... */
579 num_checks = MAX_CHECKS;
580 else
581 num_checks = (random () % MAX_CHECKS) + 1;
582
583 for (i = 0; i < num_checks * MAX_VALUES_PER_FUNC; ++i)
584 values[i] = random_word ();
585
586 for (i = 0; i < num_checks; ++i)
587 {
588 if (test == 1)
589 /* Make first test once go through each test... */
590 index = i % (int) ARRAY_SIZE (all_funcs);
591 else
592 index = random () % (int) ARRAY_SIZE (all_funcs);
593 funcs[i] = all_funcs[index].func;
594 checks[i] = all_funcs[index].check;
595 }
596
597 funcs[num_checks] = start_checks;
598
599 enable_sighandler ();
600 (*funcs[0]) (funcs + 1, values);
601 }
602
603 int
main(int argc,char ** argv)604 main (int argc, char **argv)
605 {
606 int i;
607
608 if (argc > 1)
609 verbose = 1;
610
611 for (i = 0; i < NUM_RUNS; ++i)
612 {
613 if (verbose)
614 printf ("Run %d\n", i + 1);
615 run_check (i + 1);
616 }
617
618 if (nerrors > 0)
619 {
620 fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
621 exit (-1);
622 }
623 if (verbose)
624 printf ("SUCCESS.\n");
625 return 0;
626 }
627