blob: 9b07ec470ffff86af62142dedc0ac01a980f79f5 [file] [log] [blame]
hp.com!davidm186cbb22004-09-15 11:37:04 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2001-2004 Hewlett-Packard Co
3 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#ifdef HAVE_CONFIG_H
25# include "config.h"
26#endif
27
28#include <errno.h>
29#if HAVE_EXECINFO_H
30# include <execinfo.h>
31#else
32 extern int backtrace (void **, int);
33#endif
34#include <signal.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include <libunwind.h>
40
hp.com!davidm186cbb22004-09-15 11:37:04 +000041#define panic(args...) \
42 { fprintf (stderr, args); exit (-1); }
43
44#ifndef HAVE_SIGHANDLER_T
45typedef RETSIGTYPE (*sighandler_t) (int);
46#endif
47
48int verbose;
49int num_errors;
50
51static void
52do_backtrace (void)
53{
54 char buf[512], name[256];
55 unw_word_t ip, sp, off;
56 unw_cursor_t cursor;
57 unw_proc_info_t pi;
58 unw_context_t uc;
59 int ret;
60
mostang.com!davidm1ee6b0a2005-05-03 09:13:17 +000061 if (verbose)
62 printf ("\texplicit backtrace:\n");
63
hp.com!davidm186cbb22004-09-15 11:37:04 +000064 unw_getcontext (&uc);
65 if (unw_init_local (&cursor, &uc) < 0)
66 panic ("unw_init_local failed!\n");
67
68 do
69 {
70 unw_get_reg (&cursor, UNW_REG_IP, &ip);
71 unw_get_reg (&cursor, UNW_REG_SP, &sp);
72 buf[0] = '\0';
73 if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0)
74 {
75 if (off)
76 snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off);
77 else
78 snprintf (buf, sizeof (buf), "<%s>", name);
79 }
80 if (verbose)
81 {
82 printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
83
84 unw_get_proc_info (&cursor, &pi);
85 printf ("\tproc=%lx-%lx\n\thandler=%lx lsda=%lx gp=%lx",
86 (long) pi.start_ip, (long) pi.end_ip,
87 (long) pi.handler, (long) pi.lsda, (long) pi.gp);
88
89#if UNW_TARGET_IA64
90 {
91 unw_word_t bsp;
92
93 unw_get_reg (&cursor, UNW_IA64_BSP, &bsp);
94 printf (" bsp=%lx", bsp);
95 }
96#endif
97 printf ("\n");
98 }
99
100 ret = unw_step (&cursor);
101 if (ret < 0)
102 {
103 unw_get_reg (&cursor, UNW_REG_IP, &ip);
104 printf ("FAILURE: unw_step() returned %d for ip=%lx\n",
105 ret, (long) ip);
106 ++num_errors;
107 }
108 }
109 while (ret > 0);
mostang.com!davidm1ee6b0a2005-05-03 09:13:17 +0000110
111 {
112 void *buffer[20];
113 int i, n;
114
115 if (verbose)
116 printf ("\n\tvia backtrace():\n");
117 n = backtrace (buffer, 20);
118 if (verbose)
119 for (i = 0; i < n; ++i)
120 printf ("[%d] ip=%p\n", i, buffer[i]);
121 }
hp.com!davidm186cbb22004-09-15 11:37:04 +0000122}
123
124void
125foo (long val)
126{
hp.com!davidm186cbb22004-09-15 11:37:04 +0000127 do_backtrace ();
hp.com!davidm186cbb22004-09-15 11:37:04 +0000128}
129
130void
131bar (long v)
132{
133 extern long f (long);
134 int arr[v];
135
136 /* This is a vain attempt to use up lots of registers to force
137 the frame-chain info to be saved on the memory stack on ia64.
138 It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps
139 not with any other compiler. */
140 foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
141 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
142 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
143 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
144 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
145 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
146 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
147 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
148 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
149 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
150 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
151 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
152 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
153 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
154 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
155 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
156 + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v))
157 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
158 )))))))))))))))))))))))))))))))))))))))))))))))))))))));
159}
160
161void
162sighandler (int signal, void *siginfo, void *context)
163{
164 ucontext_t *uc = context;
165 int sp;
166
167 if (verbose)
168 {
169 printf ("sighandler: got signal %d, sp=%p", signal, &sp);
170#if UNW_TARGET_IA64
171# if defined(__linux__)
172 printf (" @ %lx", uc->uc_mcontext.sc_ip);
173# else
174 {
175 uint16_t reason;
176 uint64_t ip;
177
178 __uc_get_reason (uc, &reason);
179 __uc_get_ip (uc, &ip);
180 printf (" @ %lx (reason=%d)", ip, reason);
181 }
182# endif
183#elif UNW_TARGET_X86
184 printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]);
185#endif
186 printf ("\n");
187 }
188 do_backtrace();
189}
190
191int
192main (int argc, char **argv)
193{
194 struct sigaction act;
195 stack_t stk;
196
197 verbose = (argc > 1);
198
199 if (verbose)
200 printf ("Normal backtrace:\n");
201
202 bar (1);
203
204 memset (&act, 0, sizeof (act));
205 act.sa_handler = (void (*)(int)) sighandler;
206 act.sa_flags = SA_SIGINFO;
207 if (sigaction (SIGTERM, &act, NULL) < 0)
208 panic ("sigaction: %s\n", strerror (errno));
209
210 if (verbose)
211 printf ("\nBacktrace across signal handler:\n");
212 kill (getpid (), SIGTERM);
213
214 if (verbose)
215 printf ("\nBacktrace across signal handler on alternate stack:\n");
Paul Pluzhnikovb56375e2009-10-07 12:51:03 -0700216 stk.ss_sp = malloc (SIGSTKSZ);
hp.com!davidm186cbb22004-09-15 11:37:04 +0000217 if (!stk.ss_sp)
218 panic ("failed to allocate SIGSTKSZ (%u) bytes\n", SIGSTKSZ);
Paul Pluzhnikovb56375e2009-10-07 12:51:03 -0700219 stk.ss_size = SIGSTKSZ;
hp.com!davidm186cbb22004-09-15 11:37:04 +0000220 stk.ss_flags = 0;
221 if (sigaltstack (&stk, NULL) < 0)
222 panic ("sigaltstack: %s\n", strerror (errno));
223
224 memset (&act, 0, sizeof (act));
225 act.sa_handler = (void (*)(int)) sighandler;
226 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
227 if (sigaction (SIGTERM, &act, NULL) < 0)
228 panic ("sigaction: %s\n", strerror (errno));
229 kill (getpid (), SIGTERM);
230
231 if (num_errors > 0)
232 {
233 fprintf (stderr, "FAILURE: detected %d errors\n", num_errors);
234 exit (-1);
235 }
236 if (verbose)
237 printf ("SUCCESS.\n");
238 return 0;
239}