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