Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
backtrace.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <argp.h>
25 
26 #include <sys/user.h>
27 #include <sys/ptrace.h>
28 #include <inttypes.h>
29 
30 #include <signal.h>
31 
32 #include "glib_wrapper.h"
33 #include "log.h"
34 #include "dwdebug.h"
35 #include "target_api.h"
36 #include "target.h"
37 #include "target_linux_userproc.h"
38 #ifdef ENABLE_XENACCESS
39 #include "target_xen_vm.h"
40 #endif
41 
42 #include "probe_api.h"
43 #include "probe.h"
44 #include "alist.h"
45 #include "list.h"
46 
47 GList *targets;
48 
49 struct bt_argp_state {
50  int loopint;
51  int detail;
52  int argc;
53  char **argv;
54 };
55 
57 
58 void sigu(siginfo_t *siginfo) {
59  struct target *target;
60  target_status_t tstat;
61  GList *t1;
62  int i,rc;
63  tid_t tid;
64  char buf[1024];
65 
66  if (siginfo->si_signo != SIGALRM)
67  return;
68 
69  v_g_list_foreach(targets,t1,target) {
70  tstat = target_status(target);
71  if (tstat != TSTATUS_PAUSED)
72  target_pause(target);
73  }
74 
75  v_g_list_foreach(targets,t1,target) {
77  fprintf(stdout,"Cannot examine target %s; handling an exception!\n",
78  target->name);
79  continue;
80  }
81  else {
82  fprintf(stdout,"Threads in target %s:\n",target->name);
83  fflush(stderr);
84  fflush(stdout);
86  target_dump_all_threads(target,stdout,opts.detail);
87  fflush(stderr);
88  fflush(stdout);
89 
90  struct array_list *tids = target_list_tids(target);
91  array_list_foreach_fakeptr_t(tids,i,tid,uintptr_t) {
92  fflush(stderr);
93  fflush(stdout);
94 
95  rc = target_unwind_snprintf(buf,sizeof(buf),target,tid,
96  TARGET_UNWIND_STYLE_GDB,"\n",",");
97  if (rc < 0)
98  fprintf(stdout,"\nthread %"PRIiTID": (error!)\n",tid);
99  else if (rc == 0)
100  fprintf(stdout,"\nthread %"PRIiTID": (nothing)\n",tid);
101  else
102  fprintf(stdout,"\nthread %"PRIiTID": \n%s\n",tid,buf);
103  }
104  if (tids)
105  array_list_free(tids);
106  }
107  }
108 
109  v_g_list_foreach(targets,t1,target) {
110  tstat = target_status(target);
111  if (tstat == TSTATUS_PAUSED)
112  target_resume(target);
113  }
114 
115  alarm(opts.loopint);
116 }
117 
118 #define BT_ARGP_INTERVAL 0x444443
119 #define BT_ARGP_DETAIL 0x444444
120 
121 struct argp_option bt_argp_opts[] = {
122  { "loop-interval",BT_ARGP_INTERVAL,"INTERVAL",0,"Loop infinitely using the given interval.",0 },
123  { "dump-detail",BT_ARGP_DETAIL,"DETAIL",0,"Thread detail level (default 0).",0 },
124 
125  { 0,0,0,0,0,0 },
126 };
127 
128 error_t bt_argp_parse_opt(int key, char *arg,struct argp_state *state) {
129  struct bt_argp_state *opts = \
130  (struct bt_argp_state *)target_argp_driver_state(state);
131 
132  switch (key) {
133  case ARGP_KEY_ARG:
134  return ARGP_ERR_UNKNOWN;
135  case ARGP_KEY_ARGS:
136  /* Eat all the remaining args. */
137  if (state->quoted > 0)
138  opts->argc = state->quoted - state->next;
139  else
140  opts->argc = state->argc - state->next;
141  if (opts->argc > 0) {
142  opts->argv = calloc(opts->argc,sizeof(char *));
143  memcpy(opts->argv,&state->argv[state->next],opts->argc*sizeof(char *));
144  state->next += opts->argc;
145  }
146  return 0;
147  case ARGP_KEY_INIT:
149  return 0;
150  case ARGP_KEY_END:
151  case ARGP_KEY_NO_ARGS:
152  case ARGP_KEY_SUCCESS:
153  return 0;
154  case ARGP_KEY_ERROR:
155  case ARGP_KEY_FINI:
156  return 0;
157 
158  case BT_ARGP_INTERVAL:
159  opts->loopint = atoi(arg);
160  break;
161  case BT_ARGP_DETAIL:
162  opts->detail = atoi(arg);
163  break;
164 
165  default:
166  return ARGP_ERR_UNKNOWN;
167  }
168 
169  return 0;
170 }
171 
172 struct argp bt_argp = {
173  bt_argp_opts,bt_argp_parse_opt,NULL,NULL,NULL,NULL,NULL,
174 };
175 
176 int main(int argc,char **argv) {
177  struct target_spec *primary_target_spec = NULL;
178  GList *base_target_specs = NULL;
179  GList *overlay_target_specs = NULL;
180  int rc;
181  struct evloop *evloop;
182  sigset_t ignored,interrupt,exitset;
183  siginfo_t siginfo;
184 
185  target_init();
186  atexit(target_fini);
187 
188  /*
189  * We need to handle SIGALRM specially so we can loop.
190  */
191  sigemptyset(&ignored);
192  sigemptyset(&exitset);
193  sigemptyset(&interrupt);
194 
195  sigaddset(&exitset,SIGHUP);
196  sigaddset(&exitset,SIGINT);
197  sigaddset(&exitset,SIGQUIT);
198  sigaddset(&exitset,SIGILL);
199  sigaddset(&exitset,SIGABRT);
200  sigaddset(&exitset,SIGFPE);
201  sigaddset(&exitset,SIGSEGV);
202  sigaddset(&exitset,SIGPIPE);
203  sigaddset(&exitset,SIGTERM);
204  sigaddset(&exitset,SIGBUS);
205  sigaddset(&exitset,SIGXCPU);
206  sigaddset(&exitset,SIGXFSZ);
207 
208  sigaddset(&ignored,SIGUSR1);
209  sigaddset(&ignored,SIGUSR2);
210  sigaddset(&interrupt,SIGALRM);
211 
212  target_install_custom_sighandlers(&ignored,&interrupt,&exitset,NULL);
213 
214  memset(&opts,0,sizeof(opts));
215  rc = target_argp_driver_parse(&bt_argp,&opts,argc,argv,
217  | TARGET_TYPE_GDB,1,
218  &primary_target_spec,&base_target_specs,
219  &overlay_target_specs);
220 
221  if (rc) {
222  verror("could not parse target arguments!\n");
223  exit(-1);
224  }
225 
226  evloop = evloop_create(NULL);
227 
228  targets = target_instantiate_and_open(primary_target_spec,
229  base_target_specs,overlay_target_specs,
230  evloop,NULL);
231  if (!targets) {
232  verror("could not instantiate and open targets!\n");
233  exit(-1);
234  }
235 
236  /* Do it the first time */
237  siginfo.si_signo = SIGALRM;
238  sigu(&siginfo);
239 
240  if (!opts.loopint) {
241  rc = 0;
242  goto exit;
243  }
244 
245  alarm(opts.loopint);
246 
247  fprintf(stdout,"Starting thread watch loop!\n");
248  fflush(stdout);
249 
250  while (1) {
251  tid_t tid = 0;
252  struct target *t;
253  target_status_t tstat;
254  char *tname;
255  siginfo_t siginfo;
256 
257  rc = target_monitor_evloop(evloop,NULL,&t,&tstat);
258 
259  /* Did we get interrupted safely? */
260  if (target_monitor_was_interrupted(&siginfo))
261  sigu(&siginfo);
262  /* Did we experience an error in select() or in evloop? */
263  else if (rc < 0) {
264  fprintf(stderr,"error in target_monitor_evloop (%d): %s; aborting!\n",
265  rc,strerror(errno));
267  exit(-3);
268  }
269  /* Did we experience a significant event on a target? */
270  else if (rc == 0 && evloop_maxsize(evloop) < 0) {
271  break;
272  }
273  else if (rc == 0) {
274  tid = target_gettid(t);
275  tname = target_name(t);
276 
277  if (tstat == TSTATUS_ERROR) {
278  fprintf(stderr,
279  "Error handling target '%s'; closing and finalizing!\n",
280  tname);
281 
282  target_close(t);
283  target_finalize(t);
284  targets = g_list_remove(targets,t);
285  }
286  else if (tstat == TSTATUS_DONE) {
287  fprintf(stderr,
288  "Target '%s' finished; finalizing!\n",
289  tname);
290 
291  target_close(t);
292  target_finalize(t);
293  targets = g_list_remove(targets,t);
294  }
295  else if (tstat == TSTATUS_EXITING) {
296  fprintf(stderr,"Target '%s' exiting...\n",tname);
297  }
298  else if (tstat == TSTATUS_INTERRUPTED) {
299  fprintf(stderr,"Target '%s' interrupted, resuming...\n",tname);
300  if (target_resume(t)) {
301  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
302  tname,tid);
303 
304  target_close(t);
305  target_finalize(t);
306  targets = g_list_remove(targets,t);
307  }
308  }
309  else {
310  fprintf(stderr,
311  "Target '%s' tid %d received unexpected status '%s'"
312  " at 0x%"PRIxADDR"; attempting to continue!\n",
313  tname,tid,TSTATUS(tstat),target_read_reg(t,tid,CREG_IP));
314  if (target_resume(t)) {
315  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
316  tname,tid);
317 
318  target_close(t);
319  target_finalize(t);
320  targets = g_list_remove(targets,t);
321  }
322  }
323  }
324  }
325 
326  exit:
327  fflush(stderr);
328  fflush(stdout);
330  exit(rc);
331 }
int main(int argc, char **argv)
Definition: backtrace.c:176
struct argp_option bt_argp_opts[]
Definition: backtrace.c:121
int32_t tid_t
Definition: common.h:36
void * target_argp_driver_state(struct argp_state *state)
Definition: target.c:716
target_status_t
Definition: target_api.h:197
int target_unwind_snprintf(char *buf, int buflen, struct target *target, tid_t tid, target_unwind_style_t fstyle, char *frame_sep, char *ksep)
Definition: target.c:5482
int target_load_available_threads(struct target *target, int force)
Definition: target_api.c:1300
sigset_t interrupt
Definition: spf.c:211
static uint64_t unsigned int i
int target_monitor_evloop(struct evloop *evloop, struct timeval *timeout, struct target **target, target_status_t *status)
Definition: target_api.c:880
void target_init(void)
Definition: target.c:69
Definition: arch.h:74
GList * targets
Definition: backtrace.c:47
int target_resume(struct target *target)
Definition: target_api.c:1012
#define v_g_list_foreach(glhead, glcur, elm)
Definition: glib_wrapper.h:34
int target_pause(struct target *target)
Definition: target_api.c:1027
struct bt_argp_state opts
Definition: backtrace.c:56
tid_t target_gettid(struct target *target)
Definition: target_api.c:1918
int target_close(struct target *target)
Definition: target_api.c:1511
#define verror(format,...)
Definition: log.h:30
int target_install_custom_sighandlers(sigset_t *ignored, sigset_t *interrupt, sigset_t *exit, void(*sighandler)(int signo, siginfo_t *siginfo, void *x))
Definition: target.c:270
Definition: evloop.h:66
void target_fini(void)
Definition: target.c:91
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1132
void target_default_cleanup()
Definition: target.c:128
int target_argp_driver_parse(struct argp *driver_parser, void *driver_state, int argc, char **argv, target_type_t target_types, int filter_quoted, struct target_spec **primary_target_spec, GList **base_target_specs, GList **overlay_target_specs)
Definition: target.c:913
int target_monitor_was_interrupted(siginfo_t *last_siginfo)
Definition: target.c:226
struct array_list * target_list_tids(struct target *target)
Definition: target_api.c:1210
#define BT_ARGP_DETAIL
Definition: backtrace.c:119
#define TSTATUS(n)
Definition: target_api.h:252
char * target_name(struct target *target)
Definition: target_api.c:505
char ** argv
Definition: backtrace.c:53
void sigu(siginfo_t *siginfo)
Definition: backtrace.c:58
int evloop_maxsize(struct evloop *evloop)
Definition: evloop.c:191
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
struct evloop * evloop_create(evloop_error_handler_t ehandler)
Definition: evloop.c:33
target_status_t target_status(struct target *target)
Definition: target_api.c:1046
#define PRIiTID
Definition: common.h:37
sigset_t ignored
Definition: spf.c:211
int target_finalize(struct target *target)
Definition: target.c:1955
char * name
Definition: target_api.h:2521
GList * target_instantiate_and_open(struct target_spec *primary_target_spec, GList *base_target_specs, GList *overlay_target_specs, struct evloop *evloop, GList **error_specs)
Definition: target_api.c:92
sigset_t exitset
Definition: spf.c:211
void target_dump_all_threads(struct target *target, FILE *stream, int detail)
Definition: target_api.c:1500
#define PRIxADDR
Definition: common.h:67
struct argp bt_argp
Definition: backtrace.c:172
#define array_list_foreach_fakeptr_t(alist, lpc, placeholder, intertype)
Definition: alist.h:381
int target_monitor_handling_exception(struct target *target)
Definition: target.c:317
#define BT_ARGP_INTERVAL
Definition: backtrace.c:118
void target_driver_argp_init_children(struct argp_state *state)
Definition: target.c:1057
struct target * t
Definition: dumptarget.c:48
error_t bt_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: backtrace.c:128