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>
5 This file is part of libunwind.
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:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
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. */
26 /* This file tests corner-cases of NaT-bit handling. */
33 #include <libunwind.h>
36 #ifdef HAVE_SYS_UC_ACCESS_H
37 # include <sys/uc_access.h>
40 #include "tdep-ia64/rse.h"
44 #define MAX_CHECKS 1024
45 //#define MAX_CHECKS 2
46 #define MAX_VALUES_PER_FUNC 4
48 #define panic(args...) \
49 do { printf (args); ++nerrors; } while (0)
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);
54 extern void flushrs (void);
56 extern save_func_t save_static_to_stacked;
57 static check_func_t check_static_to_stacked;
59 extern save_func_t save_static_to_fr;
60 static check_func_t check_static_to_fr;
62 extern save_func_t save_static_to_br;
63 static check_func_t check_static_to_br;
65 extern save_func_t save_static_to_mem;
66 static check_func_t check_static_to_mem;
68 extern save_func_t save_static_to_mem2;
69 static check_func_t check_static_to_mem2;
71 extern save_func_t save_static_to_mem3;
72 static check_func_t check_static_to_mem3;
74 extern save_func_t save_static_to_mem4;
75 static check_func_t check_static_to_mem4;
77 extern save_func_t save_static_to_mem5;
78 static check_func_t check_static_to_mem5;
80 extern save_func_t save_static_to_scratch;
81 static check_func_t check_static_to_scratch;
83 extern save_func_t rotate_regs;
84 static check_func_t check_rotate_regs;
86 extern save_func_t save_pr;
87 static check_func_t check_pr;
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];
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 },
120 unw_word_t val = random ();
122 if (sizeof (unw_word_t) > 4)
123 val |= ((unw_word_t) random ()) << 32;
129 sighandler (int signal, void *siginfo, void *context)
131 unsigned long *bsp, *arg1;
133 ucontext_t *uc = context;
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);
146 #elif defined(__hpux)
147 if (__uc_get_ar (uc, UNW_IA64_AR_BSP - UNW_IA64_AR, &bsp) != 0)
149 panic ("%s: reading of ar.bsp failed, errno=%d", __FUNCTION__, errno);
155 arg0 = (save_func_t **) *bsp;
156 bsp = (unsigned long *) rse_skip_regs ((uint64_t) bsp, 1);
157 arg1 = (unsigned long *) *bsp;
159 (*arg0[0]) (arg0 + 1, arg1);
161 /* skip over the instruction which triggered sighandler() */
163 ++uc->uc_mcontext.sc_ip;
164 #elif defined(HAVE_SYS_UC_ACCESS_H)
168 if (__uc_get_ip (uc, &ip) != 0)
170 panic ("%s: reading of ip failed, errno=%d", __FUNCTION__, errno);
173 if (__uc_set_ip (uc, ip) != 0)
175 panic ("%s: writing of ip failed, errno=%d", __FUNCTION__, errno);
183 enable_sighandler (void)
185 struct sigaction act;
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));
195 disable_sighandler (void)
197 struct sigaction act;
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));
207 check_static_to_stacked (unw_cursor_t *c, unw_word_t *vals)
214 printf (" %s()\n", __FUNCTION__);
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);
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);
228 for (i = 0; i < 4; ++i)
231 printf (" r%d = %c%016lx (expected %c%016lx)\n",
232 4 + i, nat[i] ? '*' : ' ', r[i],
233 (vals[i] & 1) ? '*' : ' ', vals[i]);
238 panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
243 panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
245 panic ("%s: r%d=%lx instead of %lx!\n",
246 __FUNCTION__, 4 + i, r[i], vals[i]);
253 check_static_to_fr (unw_cursor_t *c, unw_word_t *vals)
260 printf (" %s()\n", __FUNCTION__);
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);
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);
271 printf (" r4 = %c%016lx (expected %c%016lx)\n",
272 nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
277 panic ("%s: r4 not a NaT!\n", __FUNCTION__);
282 panic ("%s: r4 a NaT!\n", __FUNCTION__);
284 panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
290 check_static_to_br (unw_cursor_t *c, unw_word_t *vals)
296 printf (" %s()\n", __FUNCTION__);
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);
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);
307 printf (" r4 = %c%016lx (expected %c%016lx)\n",
308 nat4 ? '*' : ' ', r4, (vals[0] & 1) ? '*' : ' ', vals[0]);
313 panic ("%s: r4 not a NaT!\n", __FUNCTION__);
318 panic ("%s: r4 a NaT!\n", __FUNCTION__);
320 panic ("%s: r4=%lx instead of %lx!\n", __FUNCTION__, r4, vals[0]);
326 check_static_to_mem (unw_cursor_t *c, unw_word_t *vals)
332 printf (" %s()\n", __FUNCTION__);
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);
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);
343 printf (" r5 = %c%016lx (expected %c%016lx)\n",
344 nat5 ? '*' : ' ', r5, (vals[0] & 1) ? '*' : ' ', vals[0]);
349 panic ("%s: r5 not a NaT!\n", __FUNCTION__);
354 panic ("%s: r5 a NaT!\n", __FUNCTION__);
356 panic ("%s: r5=%lx instead of %lx!\n", __FUNCTION__, r5, vals[0]);
362 check_static_to_memN (unw_cursor_t *c, unw_word_t *vals, const char *func)
368 printf (" %s()\n", func);
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);
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);
379 printf (" r6 = %c%016lx (expected %c%016lx)\n",
380 nat6 ? '*' : ' ', r6, (vals[0] & 1) ? '*' : ' ', vals[0]);
385 panic ("%s: r6 not a NaT!\n", __FUNCTION__);
390 panic ("%s: r6 a NaT!\n", __FUNCTION__);
392 panic ("%s: r6=%lx instead of %lx!\n", __FUNCTION__, r6, vals[0]);
398 check_static_to_mem2 (unw_cursor_t *c, unw_word_t *vals)
400 return check_static_to_memN (c, vals, __FUNCTION__);
404 check_static_to_mem3 (unw_cursor_t *c, unw_word_t *vals)
406 return check_static_to_memN (c, vals, __FUNCTION__);
410 check_static_to_mem4 (unw_cursor_t *c, unw_word_t *vals)
412 return check_static_to_memN (c, vals, __FUNCTION__);
416 check_static_to_mem5 (unw_cursor_t *c, unw_word_t *vals)
418 return check_static_to_memN (c, vals, __FUNCTION__);
422 check_static_to_scratch (unw_cursor_t *c, unw_word_t *vals)
424 unw_word_t r[4], nat[4], ec, expected;
429 printf (" %s()\n", __FUNCTION__);
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",
437 if ((ret = unw_step (c)) < 0)
438 panic ("%s: unw_step (ret=%d): Failed to skip over signal handler\n",
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);
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);
451 for (i = 0; i < 4; ++i)
454 printf (" r%d = %c%016lx (expected %c%016lx)\n",
455 4 + i, nat[i] ? '*' : ' ', r[i],
456 (vals[i] & 1) ? '*' : ' ', vals[i]);
461 panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i);
466 panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i);
468 panic ("%s: r%d=%lx instead of %lx!\n",
469 __FUNCTION__, 4 + i, r[i], vals[i]);
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);
475 /* These tests are little-endian specific: */
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]);
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]);
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);
492 expected = vals[0] & 0x3f;
494 panic ("%s: ar.ec=%016lx instead of %016lx!\n",
495 __FUNCTION__, ec, expected);
501 check_pr (unw_cursor_t *c, unw_word_t *vals)
503 unw_word_t pr, expected;
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))
510 printf (" %s()\n", __FUNCTION__);
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);
518 expected = (vals[0] & ~DONTCARE) | 1;
521 printf (" pr = %016lx (expected %016lx)\n", pr, expected);
524 panic ("%s: pr=%lx instead of %lx!\n", __FUNCTION__, pr, expected);
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);
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);
533 panic ("%s: secondary pr=%lx instead of %lx!\n",
534 __FUNCTION__, pr, vals[0]);
539 check_rotate_regs (unw_cursor_t *c, unw_word_t *vals)
542 printf (" %s()\n", __FUNCTION__);
543 return check_pr (c, vals - 1);
547 start_checks (void *funcs, unsigned long *vals)
553 disable_sighandler ();
555 unw_getcontext (&uc);
557 if ((ret = unw_init_local (&c, &uc)) < 0)
558 panic ("%s: unw_init_local (ret=%d)\n", __FUNCTION__, ret);
560 if ((ret = unw_step (&c)) < 0)
561 panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
563 for (i = 0; i < num_checks; ++i)
565 vals = (*checks[num_checks - 1 - i]) (&c, vals);
567 if ((ret = unw_step (&c)) < 0)
568 panic ("%s: unw_step (ret=%d)\n", __FUNCTION__, ret);
578 /* Make first test always go the full depth... */
579 num_checks = MAX_CHECKS;
581 num_checks = (random () % MAX_CHECKS) + 1;
583 for (i = 0; i < num_checks * MAX_VALUES_PER_FUNC; ++i)
584 values[i] = random_word ();
586 for (i = 0; i < num_checks; ++i)
589 /* Make first test once go through each test... */
590 index = i % (int) ARRAY_SIZE (all_funcs);
592 index = random () % (int) ARRAY_SIZE (all_funcs);
593 funcs[i] = all_funcs[index].func;
594 checks[i] = all_funcs[index].check;
597 funcs[num_checks] = start_checks;
599 enable_sighandler ();
600 (*funcs[0]) (funcs + 1, values);
604 main (int argc, char **argv)
611 for (i = 0; i < NUM_RUNS; ++i)
614 printf ("Run %d\n", i + 1);
620 fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
624 printf ("SUCCESS.\n");