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
probetargets.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 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 <sys/user.h>
24 #include <sys/ptrace.h>
25 #include <inttypes.h>
26 #include <signal.h>
27 #include <argp.h>
28 #include <glib.h>
29 #include "glib_wrapper.h"
30 
31 #include "log.h"
32 #include "dwdebug.h"
33 #include "target_api.h"
34 #include "target.h"
35 #include "probe_api.h"
36 
37 struct dt_argp_state {
38  int do_post;
39  int quiet;
40  int argc;
41  char **argv;
42  unsigned int ospecs_len;
43 };
44 
45 error_t dt_argp_parse_opt(int key, char *arg,struct argp_state *state);
46 
47 struct argp_option dt_argp_opts[] = {
48  { "post",'P',0,0,"Enable post handlers.",0 },
49  { "quiet",'q',0,0,"Silent but deadly.",0 },
50  { 0,0,0,0,0,0 },
51 };
52 
53 struct argp dt_argp = {
54  dt_argp_opts,dt_argp_parse_opt,NULL,NULL,NULL,NULL,NULL,
55 };
56 
58 
59 result_t handler(struct probe *probe,tid_t tid,void *data,
60  struct probe *trigger,struct probe *base) {
61  GHashTableIter iter;
62  gpointer kp,vp;
63  char vstrbuf[1024];
64  struct value *v;
65  GHashTable *vt;
66  struct bsymbol *bsymbol;
67  struct symbol *symbol;
68  int i;
69  int rc;
70  result_t retval = RESULT_SUCCESS;
71  char buf[1024];
72  struct target *target;
73 
74  target = probe_target(probe);
75 
76  /* Grab the symbol associated with the probe. */
77  bsymbol = probe_symbol(probe);
78 
79  /* bsymbols are wrappers for the underlying symbol; get that. */
80  symbol = bsymbol_get_symbol(bsymbol);
81 
82  /* Get the current value table: the current values for this probe hit. */
83  vt = probe_value_get_table(probe,tid);
84  if (!vt) {
85  vwarn("probe %s: could not get values from probe %s"
86  " (tid %"PRIiTID")!\n",
87  probe_name(probe),probe_name(trigger),tid);
88  }
89 
90  fflush(stderr);
91  fflush(stdout);
92 
94  fprintf(stdout,"%s (",symbol_get_name(symbol));
95 
96  /* Loop through and print the values by stringifying them. */
97  if (vt) {
98  i = 0;
99  g_hash_table_iter_init(&iter,vt);
100  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
101  if (strcmp((char *)kp,PROBE_VALUE_NAME_RETURN) == 0)
102  continue;
103  if (i > 0)
104  fprintf(stdout,",");
105  v = (struct value *)vp;
106  if (v) {
107  rc = value_snprintf(v,vstrbuf,sizeof(vstrbuf));
108  if (rc > 0)
109  fprintf(stdout,"%s = %s",(char *)kp,vstrbuf);
110  else
111  fprintf(stdout,"%s = ?",(char *)kp);
112  }
113  else
114  fprintf(stdout,"%s = ?",(char *)kp);
115  ++i;
116  }
117  }
118  else {
120  fprintf(stdout,"?");
121  else
122  fprintf(stdout," = ?");
123  }
124 
125  /*
126  * Print the return value using the special name, the macro
127  * PROBE_VALUE_NAME_RETURN .
128  */
130  fprintf(stdout,")");
131  if (vt) {
132  v = (struct value *) \
133  g_hash_table_lookup(vt,PROBE_VALUE_NAME_RETURN);
134  if (v) {
135  rc = value_snprintf(v,vstrbuf,sizeof(vstrbuf));
136  if (rc > 0)
137  fprintf(stdout," = %s",vstrbuf);
138  else
139  fprintf(stdout," = ?");
140  }
141  }
142  }
143  fputs(" ",stdout);
144 
145  /* Print a dump of the current thread info, like registers. */
146  fputs("[",stdout);
147  if (target_thread_snprintf(target,tid,buf,sizeof(buf),
148  2,":","=") < 0)
149  fprintf(stdout,"tid=%"PRIiTID"",tid);
150  else
151  fprintf(stdout,"%s",buf);
152 
153  /* Unwind the current thread and print it too. */
154  rc = target_unwind_snprintf(buf,sizeof(buf),target,tid,
156  if (rc < 0)
157  fprintf(stdout," backtrace=[error!]");
158  else if (rc == 0)
159  fprintf(stdout," backtrace=[empty]");
160  else
161  fprintf(stdout," backtrace=[%s]",buf);
162 
163  fprintf(stdout,"]");
164 
165  fputs("\n",stdout);
166  fflush(stdout);
167 
168  /*
169  * Return! Be careful what you return from probe handlers -- some
170  * return values will cause the probe to be removed!!!
171  */
172  return retval;
173 }
174 
175 error_t dt_argp_parse_opt(int key, char *arg,struct argp_state *state) {
176  struct dt_argp_state *opts = \
177  (struct dt_argp_state *)target_argp_driver_state(state);
178 
179  switch (key) {
180  case ARGP_KEY_ARG:
181  /* We want to process all the remaining args, so bounce to the
182  * next case by returning this value.
183  */
184  return ARGP_ERR_UNKNOWN;
185  case ARGP_KEY_ARGS:
186  /* Eat all the remaining args. */
187  if (state->quoted > 0)
188  opts->argc = state->quoted - state->next;
189  else
190  opts->argc = state->argc - state->next;
191  if (opts->argc > 0) {
192  opts->argv = calloc(opts->argc,sizeof(char *));
193  memcpy(opts->argv,&state->argv[state->next],opts->argc*sizeof(char *));
194  state->next += opts->argc;
195  }
196  return 0;
197  case ARGP_KEY_INIT:
199  return 0;
200  case ARGP_KEY_END:
201  case ARGP_KEY_NO_ARGS:
202  case ARGP_KEY_SUCCESS:
203  return 0;
204  case ARGP_KEY_ERROR:
205  case ARGP_KEY_FINI:
206  return 0;
207 
208  case 'P':
209  opts->do_post = 1;
210  break;
211  case 'q':
212  opts->quiet = 1;
213  break;
214 
215  default:
216  return ARGP_ERR_UNKNOWN;
217  }
218 
219  return 0;
220 }
221 
222 int main(int argc,char **argv) {
223  int i;
224  struct probe *probe;
225  struct target_spec *primary_target_spec = NULL;
226  GList *base_target_specs = NULL;
227  GList *overlay_target_specs = NULL;
228  GList *targets;
229  int rc;
230  struct evloop *evloop;
231  char *name,*rname;
232  GList *t1;
233  struct target *target;
234  struct bsymbol *bsymbol;
235 
236  target_init();
237  atexit(target_fini);
238 
239  memset(&opts,0,sizeof(opts));
240  rc = target_argp_driver_parse(&dt_argp,&opts,argc,argv,
242  | TARGET_TYPE_GDB,1,
243  &primary_target_spec,&base_target_specs,
244  &overlay_target_specs);
245 
246  if (rc) {
247  verror("could not parse target arguments!\n");
248  exit(-1);
249  }
250 
252 
253  evloop = evloop_create(NULL);
254 
255  targets = target_instantiate_and_open(primary_target_spec,
256  base_target_specs,overlay_target_specs,
257  evloop,NULL);
258  if (!targets) {
259  verror("could not instantiate and open targets!\n");
260  exit(-1);
261  }
262 
263  /*
264  * Look up symbols!
265  */
266  for (i = 0; i < opts.argc; ++i) {
267  name = opts.argv[i];
268 
269  rname = index(name,':');
270  if (rname) {
271  *rname = '\0';
272  ++rname;
273  target = target_lookup_target_id(atoi(name));
274  if (!target) {
275  fprintf(stderr,
276  "Could not lookup target %s for symbol %s; aborting!\n",
277  name,rname);
279  exit(-3);
280  }
281  name = rname;
282  bsymbol = target_lookup_sym(target,name,NULL,NULL,
284  }
285  else {
286  v_g_list_foreach(targets,t1,target) {
287  bsymbol = target_lookup_sym(target,name,NULL,NULL,
289  if (bsymbol)
290  break;
291  }
292  }
293 
294  if (!bsymbol) {
295  fprintf(stderr,"could not lookup symbol %s; aborting!\n",name);
297  exit(-3);
298  }
299 
300  /*
301  * Place a value probe on the symbol. If this is a function,
302  * the value probe will collect the function arguments when the
303  * function is entered; and on return from the function, it will
304  * collect the return value. You can get all these values,
305  * stringified, in a GHashTable, like we do in our probe handler
306  * above!
307  */
308  probe = probe_value_symbol(target,TID_GLOBAL,bsymbol,
309  handler,handler,NULL);
310  if (!probe) {
311  fprintf(stderr,"could not place value probe on %s; aborting!\n",
312  name);
314  exit(-3);
315  }
316 
317  /*
318  * Currently, the target library's symbol wrappers are
319  * reference-counted. That means you have to release them when
320  * you are done with them.
321  */
322  bsymbol_release(bsymbol);
323  }
324 
325  /* The target is paused after the attach; we have to resume it now
326  * that we've registered probes (or hit the at_symbol).
327  */
328  v_g_list_foreach(targets,t1,target) {
329  target_resume(target);
330  }
331 
332  fprintf(stdout,"Starting main debugging loop!\n");
333  fflush(stdout);
334 
335  while (1) {
336  tid_t tid = 0;
337  struct target *t;
338  target_status_t tstat;
339  char *tname;
340 
341  rc = target_monitor_evloop(evloop,NULL,&t,&tstat);
342 
343  /* Did we get interrupted safely? */
345  ;
346  /* Did we experience an error in select() or in evloop? */
347  else if (rc < 0) {
348  fprintf(stderr,"error in target_monitor_evloop (%d): %s;"
349  " attempting to continue!\n",rc,strerror(errno));
350  continue;
351  }
352  /* Did we experience a significant event on a target? */
353  else if (rc == 0 && evloop_maxsize(evloop) < 0) {
354  break;
355  }
356  else if (rc == 0) {
357  tid = target_gettid(t);
358  tname = target_name(t);
359 
360  if (tstat == TSTATUS_ERROR) {
361  fprintf(stderr,
362  "Error handling target '%s'; closing and finalizing!\n",
363  tname);
364 
365  target_close(t);
366  target_finalize(t);
367  targets = g_list_remove(targets,t);
368  }
369  else if (tstat == TSTATUS_DONE) {
370  fprintf(stderr,
371  "Target '%s' finished; finalizing!\n",
372  tname);
373 
374  target_close(t);
375  target_finalize(t);
376  targets = g_list_remove(targets,t);
377  }
378  else if (tstat == TSTATUS_EXITING) {
379  fprintf(stderr,"Target '%s' exiting...\n",tname);
380  }
381  else if (tstat == TSTATUS_INTERRUPTED) {
382  fprintf(stderr,"Target '%s' interrupted, resuming...\n",tname);
383  if (target_resume(t)) {
384  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
385  tname,tid);
386 
387  target_close(t);
388  target_finalize(t);
389  targets = g_list_remove(targets,t);
390  }
391  }
392  else {
393  fprintf(stderr,
394  "Target '%s' tid %d received unexpected status '%s'"
395  " at 0x%"PRIxADDR"; attempting to continue!\n",
396  tname,tid,TSTATUS(tstat),target_read_reg(t,tid,CREG_IP));
397  if (target_resume(t)) {
398  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
399  tname,tid);
400 
401  target_close(t);
402  target_finalize(t);
403  targets = g_list_remove(targets,t);
404  }
405  }
406  }
407  }
408 
409  printf("Monitoring completed; exiting!\n");
410 
411  exit(0);
412 }
int target_thread_snprintf(struct target *target, tid_t tid, char *buf, int bufsiz, int detail, char *sep, char *kvsep)
Definition: target_api.c:1425
struct probe * probe_value_symbol(struct target *target, tid_t tid, struct bsymbol *bsymbol, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data)
Definition: probe_value.c:660
int value_snprintf(struct value *value, char *buf, int buflen)
Definition: value.c:639
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
struct bsymbol * probe_symbol(struct probe *probe)
Definition: probe.c:1939
result_t handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: probetargets.c:59
static uint64_t unsigned int i
struct bsymbol * target_lookup_sym(struct target *target, const char *name, const char *delim, char *srcfile, symbol_type_flag_t ftype)
Definition: target.c:2199
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
#define PROBE_VALUE_NAME_RETURN
Definition: probe_api.h:159
tid_t target_gettid(struct target *target)
Definition: target_api.c:1918
error_t dt_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: probetargets.c:175
GHashTable * probe_value_get_table(struct probe *probe, tid_t tid)
Definition: probe_value.c:618
int target_close(struct target *target)
Definition: target_api.c:1511
struct list_head probe
Definition: probe.h:379
#define verror(format,...)
Definition: log.h:30
int target_install_default_sighandlers(void(*sighandler)(int signo, siginfo_t *siginfo, void *x))
Definition: target.c:240
Definition: evloop.h:66
void target_fini(void)
Definition: target.c:91
#define vwarn(format,...)
Definition: log.h:33
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1132
struct argp dt_argp
Definition: probetargets.c:53
int main(int argc, char **argv)
Definition: probetargets.c:222
void target_default_cleanup()
Definition: target.c:128
REFCNT bsymbol_release(struct bsymbol *bsymbol)
Definition: symbol.c:90
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 dt_argp_state opts
Definition: probetargets.c:57
int symbol_type_flags_match(struct symbol *symbol, symbol_type_flag_t flags)
Definition: debug.c:3102
#define TSTATUS(n)
Definition: target_api.h:252
char * target_name(struct target *target)
Definition: target_api.c:505
char ** argv
Definition: dumptarget.c:86
Definition: probe.h:308
struct target * probe_target(struct probe *probe)
Definition: probe.c:1943
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
result_t
Definition: common.h:25
struct target * target_lookup_target_id(int id)
Definition: target.c:332
#define PRIiTID
Definition: common.h:37
int target_finalize(struct target *target)
Definition: target.c:1955
struct symbol * bsymbol_get_symbol(struct bsymbol *bsymbol)
Definition: symbol.c:66
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
#define PRIxADDR
Definition: common.h:67
struct argp_option dt_argp_opts[]
Definition: probetargets.c:47
unsigned int ospecs_len
Definition: dumptarget.c:87
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
char * probe_name(struct probe *probe)
Definition: probe.c:1935
#define TID_GLOBAL
Definition: target_api.h:145
void target_driver_argp_init_children(struct argp_state *state)
Definition: target.c:1057
struct target * t
Definition: dumptarget.c:48