1e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm/* libunwind - a platform-independent unwind library
2f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm   Copyright (C) 2001-2004 Hewlett-Packard Co
3e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
5e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmPermission is hereby granted, free of charge, to any person obtaining
6e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidma copy of this software and associated documentation files (the
7e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm"Software"), to deal in the Software without restriction, including
8e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
9e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
10e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmpermit persons to whom the Software is furnished to do so, subject to
11e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmthe following conditions:
12e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
13e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmThe above copyright notice and this permission notice shall be
14e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmincluded in all copies or substantial portions of the Software.
15e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
16e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
23e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
24f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm/* This test uses the unwind interface to modify the IP in an ancestor
25e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm   frame while still returning to the parent frame.  */
26e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
27e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm#include <signal.h>
28e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm#include <stdio.h>
29e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm#include <stdlib.h>
30e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
31e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm#include <libunwind-ia64.h>
32e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
33e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm#define panic(args...)				\
34e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm	{ fprintf (stderr, args); exit (-1); }
35e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
36f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidmint verbose;
37f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm
38e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmstatic void
39e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmsighandler (int signal)
40e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm{
41e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  unw_cursor_t cursor, cursor2;
42e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  unw_word_t ip;
43e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  unw_context_t uc;
44e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
45f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm  if (verbose)
46f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm    printf ("caught signal %d\n", signal);
47e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
48e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  unw_getcontext (&uc);
49e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if (unw_init_local (&cursor, &uc) < 0)
50e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    panic ("unw_init() failed!\n");
51e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
52e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  /* get cursor for caller of sighandler: */
53e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if (unw_step (&cursor) < 0)
54e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    panic ("unw_step() failed!\n");
55e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
56e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  cursor2 = cursor;
57e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  while (!unw_is_signal_frame (&cursor2))
58e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    if (unw_step (&cursor2) < 0)
59e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm      panic ("failed to find signal frame!\n");
60e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
61e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if (unw_step (&cursor2) < 0)
62e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    panic ("unw_step() failed!\n");
63e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
64e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if (unw_get_reg (&cursor2, UNW_REG_IP, &ip) < 0)
65e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    panic ("failed to get IP!\n");
66e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
67e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  /* skip faulting instruction (doesn't handle MLX template) */
68e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  ++ip;
69e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if ((ip & 0x3) == 0x3)
70e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    ip += 13;
71e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
72e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  if (unw_set_reg (&cursor2, UNW_REG_IP, ip) < 0)
73e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm    panic ("failed to set IP!\n");
74e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
75e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  unw_resume (&cursor);	/* update context & return to caller of sighandler() */
76e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
77e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  panic ("unexpected return from unw_resume()!\n");
78e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm}
79e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
80e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmstatic void
81e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmdoit (volatile char *p)
82e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm{
83e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  int ch;
84e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
85e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  ch = *p;	/* trigger SIGSEGV */
86e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
87f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm  if (verbose)
88f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm    printf ("doit: finishing execution!\n");
89e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm}
90e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm
91e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmint
92e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidmmain (int argc, char **argv)
93e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm{
94f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm  if (argc > 1)
95f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm    verbose = 1;
96f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm
97e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  signal (SIGSEGV, sighandler);
98e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  doit (0);
99f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm  if (verbose)
100f789a1e1d19c9e1bee57269bde8436cea59e12bbhp.com!davidm    printf ("SUCCESS\n");
101e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm  return 0;
102e5b4f8a40dc15be7943b3a1996c33e1887e5735emostang.com!davidm}
103