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
dumpthreads.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 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 "alist.h"
35 #include "list.h"
36 #include "dwdebug.h"
37 #include "target_api.h"
38 #include "target.h"
39 #include "probe_api.h"
40 #include "probe.h"
41 
42 GList *targets;
43 
44 struct dt_argp_state {
45  int loopint;
46  int detail;
47 };
48 
50 
51 void sigu(siginfo_t *siginfo) {
52  struct target *target;
53  target_status_t tstat;
54  GList *t1;
55 
56  if (siginfo->si_signo != SIGALRM)
57  return;
58 
59  v_g_list_foreach(targets,t1,target) {
60  tstat = target_status(target);
61  if (tstat != TSTATUS_PAUSED)
62  target_pause(target);
63  }
64 
65  v_g_list_foreach(targets,t1,target) {
67  fprintf(stdout,"Cannot examine target %s; handling an exception!\n",
68  target->name);
69  continue;
70  }
71  else {
72  fprintf(stdout,"Current threads in target %s:\n",target->name);
74  target_dump_all_threads(target,stdout,opts.detail);
75  }
76  }
77 
78  v_g_list_foreach(targets,t1,target) {
79  tstat = target_status(target);
80  if (tstat == TSTATUS_PAUSED)
81  target_resume(target);
82  }
83 
84  alarm(opts.loopint);
85 }
86 
87 #define DT_ARGP_INTERVAL 0x444443
88 #define DT_ARGP_DETAIL 0x444444
89 
90 struct argp_option dt_argp_opts[] = {
91  { "loop-interval",DT_ARGP_INTERVAL,"INTERVAL",0,"Loop infinitely using the given interval.",0 },
92  { "dump-detail",DT_ARGP_DETAIL,"DETAIL",0,"Thread detail level (default 0).",0 },
93  { 0,0,0,0,0,0 },
94 };
95 
96 error_t dt_argp_parse_opt(int key, char *arg,struct argp_state *state) {
97  struct dt_argp_state *opts = \
98  (struct dt_argp_state *)target_argp_driver_state(state);
99 
100  switch (key) {
101  case ARGP_KEY_ARG:
102  return ARGP_ERR_UNKNOWN;
103  case ARGP_KEY_ARGS:
104  return 0;
105  case ARGP_KEY_INIT:
107  return 0;
108  case ARGP_KEY_END:
109  case ARGP_KEY_NO_ARGS:
110  case ARGP_KEY_SUCCESS:
111  return 0;
112  case ARGP_KEY_ERROR:
113  case ARGP_KEY_FINI:
114  return 0;
115 
116  case DT_ARGP_INTERVAL:
117  opts->loopint = atoi(arg);
118  break;
119  case DT_ARGP_DETAIL:
120  opts->detail = atoi(arg);
121  break;
122 
123  default:
124  return ARGP_ERR_UNKNOWN;
125  }
126 
127  return 0;
128 }
129 
130 struct argp dt_argp = {
131  dt_argp_opts,dt_argp_parse_opt,NULL,NULL,NULL,NULL,NULL,
132 };
133 
134 int main(int argc,char **argv) {
135  struct target_spec *primary_target_spec = NULL;
136  GList *base_target_specs = NULL;
137  GList *overlay_target_specs = NULL;
138  struct target *target;
139  int rc;
140  struct evloop *evloop;
141  GList *t1;
142  sigset_t ignored,interrupt,exitset;
143 
144  target_init();
145  atexit(target_fini);
146 
147  /*
148  * We need to handle SIGALRM specially so we can loop.
149  */
150  sigemptyset(&ignored);
151  sigemptyset(&exitset);
152  sigemptyset(&interrupt);
153 
154  sigaddset(&exitset,SIGHUP);
155  sigaddset(&exitset,SIGINT);
156  sigaddset(&exitset,SIGQUIT);
157  sigaddset(&exitset,SIGILL);
158  sigaddset(&exitset,SIGABRT);
159  sigaddset(&exitset,SIGFPE);
160  sigaddset(&exitset,SIGSEGV);
161  sigaddset(&exitset,SIGPIPE);
162  sigaddset(&exitset,SIGTERM);
163  sigaddset(&exitset,SIGBUS);
164  sigaddset(&exitset,SIGXCPU);
165  sigaddset(&exitset,SIGXFSZ);
166 
167  sigaddset(&ignored,SIGUSR1);
168  sigaddset(&ignored,SIGUSR2);
169 
170  sigaddset(&interrupt,SIGALRM);
171 
172  target_install_custom_sighandlers(&ignored,&interrupt,&exitset,NULL);
173 
174  memset(&opts,0,sizeof(opts));
175  rc = target_argp_driver_parse(&dt_argp,&opts,argc,argv,
177  | TARGET_TYPE_GDB,1,
178  &primary_target_spec,&base_target_specs,
179  &overlay_target_specs);
180 
181  if (rc) {
182  verror("could not parse target arguments!\n");
183  exit(-1);
184  }
185 
186  evloop = evloop_create(NULL);
187 
188  targets = target_instantiate_and_open(primary_target_spec,
189  base_target_specs,overlay_target_specs,
190  evloop,NULL);
191  if (!targets) {
192  verror("could not instantiate and open targets!\n");
193  exit(-1);
194  }
195 
196  v_g_list_foreach(targets,t1,target) {
197  fprintf(stdout,"Threads in target %s:\n",target->name);
198  fflush(stderr);
199  fflush(stdout);
201  target_dump_all_threads(target,stdout,opts.detail);
202  fflush(stderr);
203  fflush(stdout);
204  }
205 
206  /*
207  * The targets are paused after the open; we have to resume them now
208  * that we've dumped its threads.
209  */
210  v_g_list_foreach(targets,t1,target) {
211  target_resume(target);
212  }
213 
214  if (!opts.loopint) {
215  rc = 0;
216  goto exit;
217  }
218 
219  alarm(opts.loopint);
220 
221  fprintf(stdout,"Starting thread watch loop!\n");
222  fflush(stdout);
223 
224  while (1) {
225  tid_t tid = 0;
226  struct target *t;
227  target_status_t tstat;
228  char *tname;
229  siginfo_t siginfo;
230 
231  rc = target_monitor_evloop(evloop,NULL,&t,&tstat);
232 
233  /* Did we get interrupted safely? */
234  if (target_monitor_was_interrupted(&siginfo))
235  sigu(&siginfo);
236  /* Did we experience an error in select() or in evloop? */
237  else if (rc < 0) {
238  fprintf(stderr,"error in target_monitor_evloop (%d): %s; aborting!\n",
239  rc,strerror(errno));
241  exit(-3);
242  }
243  /* Did we experience a significant event on a target? */
244  else if (rc == 0 && evloop_maxsize(evloop) < 0) {
245  break;
246  }
247  else if (rc == 0) {
248  tid = target_gettid(t);
249  tname = target_name(t);
250 
251  if (tstat == TSTATUS_ERROR) {
252  fprintf(stderr,
253  "Error handling target '%s'; closing and finalizing!\n",
254  tname);
255 
256  target_close(t);
257  target_finalize(t);
258  targets = g_list_remove(targets,t);
259  }
260  else if (tstat == TSTATUS_DONE) {
261  fprintf(stderr,
262  "Target '%s' finished; finalizing!\n",
263  tname);
264 
265  target_close(t);
266  target_finalize(t);
267  targets = g_list_remove(targets,t);
268  }
269  else if (tstat == TSTATUS_EXITING) {
270  fprintf(stderr,"Target '%s' exiting...\n",tname);
271  }
272  else if (tstat == TSTATUS_INTERRUPTED) {
273  fprintf(stderr,"Target '%s' interrupted, resuming...\n",tname);
274  if (target_resume(t)) {
275  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
276  tname,tid);
277 
278  target_close(t);
279  target_finalize(t);
280  targets = g_list_remove(targets,t);
281  }
282  }
283  else {
284  fprintf(stderr,
285  "Target '%s' tid %d received unexpected status '%s'"
286  " at 0x%"PRIxADDR"; attempting to continue!\n",
287  tname,tid,TSTATUS(tstat),target_read_reg(t,tid,CREG_IP));
288  if (target_resume(t)) {
289  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
290  tname,tid);
291 
292  target_close(t);
293  target_finalize(t);
294  targets = g_list_remove(targets,t);
295  }
296  }
297  }
298  }
299 
300  exit:
301  fflush(stderr);
302  fflush(stdout);
304  exit(rc);
305 }
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_load_available_threads(struct target *target, int force)
Definition: target_api.c:1300
sigset_t interrupt
Definition: spf.c:211
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
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
tid_t target_gettid(struct target *target)
Definition: target_api.c:1918
void sigu(siginfo_t *siginfo)
Definition: dumpthreads.c:51
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
GList * targets
Definition: dumpthreads.c:42
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
struct argp_option dt_argp_opts[]
Definition: dumpthreads.c:90
int target_monitor_was_interrupted(siginfo_t *last_siginfo)
Definition: target.c:226
struct dt_argp_state opts
Definition: dumpthreads.c:49
#define TSTATUS(n)
Definition: target_api.h:252
char * target_name(struct target *target)
Definition: target_api.c:505
#define DT_ARGP_DETAIL
Definition: dumpthreads.c:88
int main(int argc, char **argv)
Definition: dumpthreads.c:134
int evloop_maxsize(struct evloop *evloop)
Definition: evloop.c:191
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
int target_monitor_handling_exception(struct target *target)
Definition: target.c:317
error_t dt_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: dumpthreads.c:96
#define DT_ARGP_INTERVAL
Definition: dumpthreads.c:87
void target_driver_argp_init_children(struct argp_state *state)
Definition: target.c:1057
struct target * t
Definition: dumptarget.c:48
struct argp dt_argp
Definition: dumpthreads.c:130