1f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm/* libunwind - a platform-independent unwind library
230dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm   Copyright (C) 2001-2004 Hewlett-Packard Co
3f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
5f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
6f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidma copy of this software and associated documentation files (the
7f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm"Software"), to deal in the Software without restriction, including
8f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
9f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
10f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
11f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmthe following conditions:
12f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
13f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmThe above copyright notice and this permission notice shall be
14f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmincluded in all copies or substantial portions of the Software.
15f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
16f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
23f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
24f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm/* This illustrates the basics of using the unwind interface for
25f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm   exception handling.  */
26f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
2730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#ifdef HAVE_CONFIG_H
2830dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm# include "config.h"
2930dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#endif
3030dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm
31f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#include <stdio.h>
32f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#include <stdlib.h>
33f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#include <unistd.h>
34f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
35f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#include <libunwind.h>
36f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
3730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#ifdef HAVE_IA64INTRIN_H
3830dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm# include <ia64intrin.h>
3930dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#endif
4030dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm
41f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#define panic(args...)				\
42f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm	{ ++nerrors; fprintf (stderr, args); }
43f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
44f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmint nerrors = 0;
45f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmint verbose = 0;
469fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmint depth = 13;
4730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidmvolatile int got_here = 0;
48f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
499fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmextern void b (int);
50f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
519fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmvoid
529fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmraise_exception (void)
53f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm{
54f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  unw_cursor_t cursor;
55f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  unw_context_t uc;
569fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm  int i;
57f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
58f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  unw_getcontext (&uc);
59f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  if (unw_init_local (&cursor, &uc) < 0)
60f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    {
61f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm      panic ("unw_init_local() failed!\n");
62f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm      return;
63f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    }
64f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
6530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  /* unwind to top-most frame a(), skipping over b() and raise_exception(): */
6630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  for (i = 0; i < depth + 2; ++i)
679fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm    if (unw_step (&cursor) < 0)
689fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      {
699fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm	panic ("unw_step() failed!\n");
709fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm	return;
719fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      }
72f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  unw_resume (&cursor);	/* transfer control to exception handler */
73f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm}
74f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
7530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidmuintptr_t
7630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidmget_bsp (void)
77f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm{
7830dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#if UNW_TARGET_IA64
7930dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm# ifdef __INTEL_COMPILER
8030dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  return __getReg (_IA64_REG_AR_BSP);
8130dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm# else
8230dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  return (uintptr_t) __builtin_ia64_bsp ();
8330dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm# endif
8430dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm#else
8530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  return 0;
86f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm#endif
8730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm}
88f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
899fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmint
909fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidma (int n)
91f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm{
92f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  long stack;
9330dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  int result = 99;
94f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
959fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm  if (verbose)
9630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm    printf ("a(n=%d): sp=%p bsp=0x%lx\n",
9730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	    n, &stack, (unsigned long) get_bsp ());
989fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm
999fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm  if (n > 0)
1005fedf3407c7c161d12ba4f600cbce12fef780ad7Tommi Rantala    a (n - 1);
10130dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  else
10230dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm    b (16);
1039fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm
104f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  if (verbose)
105f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    {
10630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm      printf ("exception handler: here we go (sp=%p, bsp=0x%lx)...\n",
10730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	      &stack, (unsigned long) get_bsp ());
108f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm      /* This call works around a bug in gcc (up-to pre3.4) which
109f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm	 causes invalid assembly code to be generated when
110f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm	 __builtin_ia64_bsp() gets predicated.  */
111f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm      getpid ();
112f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    }
11330dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  if (n == depth)
11430dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm    {
11530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm      result = 0;
11630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm      got_here = 1;
11730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm    }
11830dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  return result;
119f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm}
120f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
1219fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmvoid
1229fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidmb (int n)
123f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm{
1249fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm  if ((n & 1) == 0)
1259fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm    {
1269fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      if (verbose)
1279fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm	printf ("b(n=%d) calling raise_exception()\n", n);
1289fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      raise_exception ();
1299fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm    }
130f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  panic ("FAILURE: b() returned from raise_exception()!!\n");
131f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm}
132f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
133f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmint
134f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidmmain (int argc, char **argv)
135f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm{
13630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  int result;
13730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm
138f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  if (argc > 1)
1399fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm    {
1409fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      ++verbose;
1419fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm      depth = atol (argv[1]);
14230dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm      if (depth < 1)
14330dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	{
14430dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	  fprintf (stderr, "Usage: %s depth\n"
14530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm		   "  depth must be >= 1\n", argv[0]);
14630dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	  exit (-1);
14730dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	}
1489fb355e096eef9a2f005e896727d25a5d4ed0141hp.com!davidm    }
149f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
15030dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  result = a (depth);
15130dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm  if (result != 0 || !got_here || nerrors > 0)
152f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    {
15330dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm      fprintf (stderr,
15430dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	       "FAILURE: test failed: result=%d got_here=%d nerrors=%d\n",
15530dec34c3a0bf851cdf41153528659ad347c0ccbhp.com!davidm	       result, got_here, nerrors);
156f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm      exit (-1);
157f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    }
158f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm
159f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  if (verbose)
160f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm    printf ("SUCCESS!\n");
161f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm  return 0;
162f77ee147ace13e3d500dc3d4468cb1b0dec2b0a4hp.com!davidm}
163