blob: 1170bdd03fd981b43473aa65c7fdd5b059d4082f [file] [log] [blame]
hp.com!davidmf77ee142003-02-22 03:08:22 +00001/* libunwind - a platform-independent unwind library
hp.com!davidm30dec342005-05-03 09:13:17 +00002 Copyright (C) 2001-2004 Hewlett-Packard Co
hp.com!davidmf77ee142003-02-22 03:08:22 +00003 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24/* This illustrates the basics of using the unwind interface for
25 exception handling. */
26
hp.com!davidm30dec342005-05-03 09:13:17 +000027#ifdef HAVE_CONFIG_H
28# include "config.h"
29#endif
30
hp.com!davidmf77ee142003-02-22 03:08:22 +000031#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34
35#include <libunwind.h>
36
hp.com!davidm30dec342005-05-03 09:13:17 +000037#ifdef HAVE_IA64INTRIN_H
38# include <ia64intrin.h>
39#endif
40
hp.com!davidmf77ee142003-02-22 03:08:22 +000041#define panic(args...) \
42 { ++nerrors; fprintf (stderr, args); }
43
44int nerrors = 0;
45int verbose = 0;
hp.com!davidm9fb355e2004-05-06 21:11:29 +000046int depth = 13;
hp.com!davidm30dec342005-05-03 09:13:17 +000047volatile int got_here = 0;
hp.com!davidmf77ee142003-02-22 03:08:22 +000048
hp.com!davidm9fb355e2004-05-06 21:11:29 +000049extern void b (int);
hp.com!davidmf77ee142003-02-22 03:08:22 +000050
hp.com!davidm9fb355e2004-05-06 21:11:29 +000051void
52raise_exception (void)
hp.com!davidmf77ee142003-02-22 03:08:22 +000053{
54 unw_cursor_t cursor;
hp.com!davidmf77ee142003-02-22 03:08:22 +000055 unw_context_t uc;
hp.com!davidm9fb355e2004-05-06 21:11:29 +000056 int i;
hp.com!davidmf77ee142003-02-22 03:08:22 +000057
58 unw_getcontext (&uc);
59 if (unw_init_local (&cursor, &uc) < 0)
60 {
61 panic ("unw_init_local() failed!\n");
62 return;
63 }
64
hp.com!davidm30dec342005-05-03 09:13:17 +000065 /* unwind to top-most frame a(), skipping over b() and raise_exception(): */
66 for (i = 0; i < depth + 2; ++i)
hp.com!davidm9fb355e2004-05-06 21:11:29 +000067 if (unw_step (&cursor) < 0)
68 {
69 panic ("unw_step() failed!\n");
70 return;
71 }
hp.com!davidmf77ee142003-02-22 03:08:22 +000072 unw_resume (&cursor); /* transfer control to exception handler */
73}
74
hp.com!davidm30dec342005-05-03 09:13:17 +000075uintptr_t
76get_bsp (void)
hp.com!davidmf77ee142003-02-22 03:08:22 +000077{
hp.com!davidm30dec342005-05-03 09:13:17 +000078#if UNW_TARGET_IA64
79# ifdef __INTEL_COMPILER
80 return __getReg (_IA64_REG_AR_BSP);
81# else
82 return (uintptr_t) __builtin_ia64_bsp ();
83# endif
84#else
85 return 0;
hp.com!davidmf77ee142003-02-22 03:08:22 +000086#endif
hp.com!davidm30dec342005-05-03 09:13:17 +000087}
hp.com!davidmf77ee142003-02-22 03:08:22 +000088
hp.com!davidm9fb355e2004-05-06 21:11:29 +000089int
90a (int n)
hp.com!davidmf77ee142003-02-22 03:08:22 +000091{
92 long stack;
hp.com!davidm30dec342005-05-03 09:13:17 +000093 int result = 99;
hp.com!davidmf77ee142003-02-22 03:08:22 +000094
hp.com!davidm9fb355e2004-05-06 21:11:29 +000095 if (verbose)
hp.com!davidm30dec342005-05-03 09:13:17 +000096 printf ("a(n=%d): sp=%p bsp=0x%lx\n",
97 n, &stack, (unsigned long) get_bsp ());
hp.com!davidm9fb355e2004-05-06 21:11:29 +000098
99 if (n > 0)
Tommi Rantala5fedf342012-08-11 15:58:44 +0300100 a (n - 1);
hp.com!davidm30dec342005-05-03 09:13:17 +0000101 else
102 b (16);
hp.com!davidm9fb355e2004-05-06 21:11:29 +0000103
hp.com!davidmf77ee142003-02-22 03:08:22 +0000104 if (verbose)
105 {
hp.com!davidm30dec342005-05-03 09:13:17 +0000106 printf ("exception handler: here we go (sp=%p, bsp=0x%lx)...\n",
107 &stack, (unsigned long) get_bsp ());
hp.com!davidmf77ee142003-02-22 03:08:22 +0000108 /* This call works around a bug in gcc (up-to pre3.4) which
109 causes invalid assembly code to be generated when
110 __builtin_ia64_bsp() gets predicated. */
111 getpid ();
112 }
hp.com!davidm30dec342005-05-03 09:13:17 +0000113 if (n == depth)
114 {
115 result = 0;
116 got_here = 1;
117 }
118 return result;
hp.com!davidmf77ee142003-02-22 03:08:22 +0000119}
120
hp.com!davidm9fb355e2004-05-06 21:11:29 +0000121void
122b (int n)
hp.com!davidmf77ee142003-02-22 03:08:22 +0000123{
hp.com!davidm9fb355e2004-05-06 21:11:29 +0000124 if ((n & 1) == 0)
125 {
126 if (verbose)
127 printf ("b(n=%d) calling raise_exception()\n", n);
128 raise_exception ();
129 }
hp.com!davidmf77ee142003-02-22 03:08:22 +0000130 panic ("FAILURE: b() returned from raise_exception()!!\n");
131}
132
133int
134main (int argc, char **argv)
135{
hp.com!davidm30dec342005-05-03 09:13:17 +0000136 int result;
137
hp.com!davidmf77ee142003-02-22 03:08:22 +0000138 if (argc > 1)
hp.com!davidm9fb355e2004-05-06 21:11:29 +0000139 {
140 ++verbose;
141 depth = atol (argv[1]);
hp.com!davidm30dec342005-05-03 09:13:17 +0000142 if (depth < 1)
143 {
144 fprintf (stderr, "Usage: %s depth\n"
145 " depth must be >= 1\n", argv[0]);
146 exit (-1);
147 }
hp.com!davidm9fb355e2004-05-06 21:11:29 +0000148 }
hp.com!davidmf77ee142003-02-22 03:08:22 +0000149
hp.com!davidm30dec342005-05-03 09:13:17 +0000150 result = a (depth);
151 if (result != 0 || !got_here || nerrors > 0)
hp.com!davidmf77ee142003-02-22 03:08:22 +0000152 {
hp.com!davidm30dec342005-05-03 09:13:17 +0000153 fprintf (stderr,
154 "FAILURE: test failed: result=%d got_here=%d nerrors=%d\n",
155 result, got_here, nerrors);
hp.com!davidmf77ee142003-02-22 03:08:22 +0000156 exit (-1);
157 }
158
159 if (verbose)
160 printf ("SUCCESS!\n");
161 return 0;
162}