blob: b65b0251c6bbeb231c0be688b5a5aa4e76d9d139 [file] [log] [blame]
hp.com!davidme9e4e5f2003-01-28 03:40:06 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2003 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#include <errno.h>
27#include <fcntl.h>
28#include <libunwind.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32
33#include <sys/ptrace.h>
34#include <sys/wait.h>
35
36int nerrors;
37int verbose = 1;
38
39#define panic(args...) \
40 do { fprintf (stderr, args); ++nerrors; } while (0)
41
42static unw_addr_space_t as;
43
44void
45do_backtrace (pid_t target_pid)
46{
47 unw_proc_info_t pi;
48 unw_word_t ip, sp;
49 unw_cursor_t c;
50 char buf[512];
51 int ret;
52 struct UPT_info *ui;
53
54 ui = _UPT_create (target_pid);
55 ret = unw_init_remote (&c, as, ui);
56 if (ret < 0)
57 panic ("unw_init_remote() failed: ret=%d\n", ret);
58
59 do
60 {
61 unw_get_reg (&c, UNW_REG_IP, &ip);
62 unw_get_reg (&c, UNW_REG_SP, &sp);
63 unw_get_proc_name (&c, buf, sizeof (buf));
64
65 printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
66
67 unw_get_proc_info (&c, &pi);
68 printf ("\tproc=%016lx-%016lx\n\thandler=%lx lsda=%lx",
69 (long) pi.start_ip, (long) pi.end_ip,
70 (long) pi.handler, (long) pi.lsda);
71
72#if UNW_TARGET_IA64
73 {
74 unw_word_t bsp;
75
76 unw_get_reg (&c, UNW_IA64_BSP, &bsp);
77 printf (" bsp=%lx", bsp);
78 }
79#endif
80 printf ("\n");
81
82 ret = unw_step (&c);
83 if (ret < 0)
84 {
85 unw_get_reg (&c, UNW_REG_IP, &ip);
86 printf ("FAILURE: unw_step() returned %d for ip=%lx\n",
87 ret, (long) ip);
88 }
89 }
90 while (ret > 0);
91
92 _UPT_destroy (ui);
93
94 if (ret < 0)
95 panic ("unwind failed with ret=%d\n", ret);
96
97 printf ("================\n\n");
98}
99
100int
101main (int argc, char **argv)
102{
103 int status, pid, state = 1;
104 pid_t target_pid;
105
106 as = unw_create_addr_space (&_UPT_accessors, 0);
107 if (!as)
108 panic ("unw_create_addr_space() failed");
109
110 if (argc == 1)
111 {
112 char *args[] = { "self", "/bin/ls", "/usr", NULL };
113
114 /* automated test case */
115 verbose = 0;
116 argv = args;
117 }
118
119 target_pid = fork ();
120 if (!target_pid)
121 {
122 /* child */
123
124 if (!verbose)
125 dup2 (open ("/dev/null", O_WRONLY), 1);
126
127 ptrace (PTRACE_TRACEME, 0, 0, 0);
128 execve (argv[1], argv + 1, environ);
129 _exit (-1);
130 }
131
132 while (1)
133 {
134 pid = wait4 (-1, &status, 0, 0);
135 if (pid == -1)
136 {
137 if (errno == EINTR)
138 continue;
139
140 panic ("wait4() failed (errno=%d)\n", errno);
141 }
142 if (WIFSIGNALED (status) || WIFEXITED (status)
143 || (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP))
144 {
145 if (WIFEXITED (status))
146 {
147 if (WEXITSTATUS (status) != 0)
148 panic ("child's exit status %d\n", WEXITSTATUS (status));
149 break;
150 }
151 else if (WIFSIGNALED (status))
152 panic ("child terminated by signal %d\n", WTERMSIG (status));
153 else
154 panic ("child got signal %d\n", WSTOPSIG (status));
155 }
156
157#if 1
158 if (!state)
159 do_backtrace (target_pid);
160
161 state ^= 1;
162 ptrace (PTRACE_SYSCALL, target_pid, 0, 0); /* continue */
163#else
164 do_backtrace (target_pid);
165 ptrace (PTRACE_SINGLESTEP, target_pid, 0, 0); /* continue */
166#endif
167 }
168
169 if (nerrors)
170 {
171 printf ("FAILURE: detected %d errors\n", nerrors);
172 exit (-1);
173 }
174 if (verbose)
175 printf ("SUCCESS\n");
176
177 return 0;
178}