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
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH 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
51typedef void save_func_t (void *funcs, unsigned long *vals);
52typedef unw_word_t *check_func_t (unw_cursor_t *c, unsigned long *vals);
53
54extern void flushrs (void);
55
56extern save_func_t save_static_to_stacked;
57static check_func_t check_static_to_stacked;
58
59extern save_func_t save_static_to_fr;
60static check_func_t check_static_to_fr;
61
62extern save_func_t save_static_to_br;
63static check_func_t check_static_to_br;
64
65extern save_func_t save_static_to_mem;
66static check_func_t check_static_to_mem;
67
68extern save_func_t save_static_to_mem2;
69static check_func_t check_static_to_mem2;
70
71extern save_func_t save_static_to_mem3;
72static check_func_t check_static_to_mem3;
73
74extern save_func_t save_static_to_mem4;
75static check_func_t check_static_to_mem4;
76
77extern save_func_t save_static_to_mem5;
78static check_func_t check_static_to_mem5;
79
80extern save_func_t save_static_to_scratch;
81static check_func_t check_static_to_scratch;
82
83extern save_func_t rotate_regs;
84static check_func_t check_rotate_regs;
85
86extern save_func_t save_pr;
87static check_func_t check_pr;
88
89static int verbose;
90static int nerrors;
91
92static int num_checks;
93static save_func_t *funcs[MAX_CHECKS + 1];
94static check_func_t *checks[MAX_CHECKS];
95static unw_word_t values[MAX_CHECKS*MAX_VALUES_PER_FUNC];
96
97static struct
98  {
99    save_func_t *func;
100    check_func_t *check;
101  }
102all_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
117static unw_word_t
118random_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
128void
129sighandler (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
182static void
183enable_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
194static void
195disable_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
206static unw_word_t *
207check_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
252static unw_word_t *
253check_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
289static unw_word_t *
290check_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
325static unw_word_t *
326check_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
361static unw_word_t *
362check_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
397static unw_word_t *
398check_static_to_mem2 (unw_cursor_t *c, unw_word_t *vals)
399{
400  return check_static_to_memN (c, vals, __FUNCTION__);
401}
402
403static unw_word_t *
404check_static_to_mem3 (unw_cursor_t *c, unw_word_t *vals)
405{
406  return check_static_to_memN (c, vals, __FUNCTION__);
407}
408
409static unw_word_t *
410check_static_to_mem4 (unw_cursor_t *c, unw_word_t *vals)
411{
412  return check_static_to_memN (c, vals, __FUNCTION__);
413}
414
415static unw_word_t *
416check_static_to_mem5 (unw_cursor_t *c, unw_word_t *vals)
417{
418  return check_static_to_memN (c, vals, __FUNCTION__);
419}
420
421static unw_word_t *
422check_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
500static unw_word_t *
501check_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
538static unw_word_t *
539check_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
546static void
547start_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
572static void
573run_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
603int
604main (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