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