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