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
pingpongmonitor.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 "common.h"
32 #include "log.h"
33 #include "dwdebug.h"
34 #include "target_api.h"
35 #include "target.h"
36 #include "probe_api.h"
37 #include "target_os_process.h"
38 
65 struct tgt_sym {
66  int tgtid;
67  char *file_name;
68  char *sym_name;
69  int line;
70 };
71 struct handler_data {
73 };
74 struct dt_argp_state {
75  int do_post;
76  int quiet;
77  int argc;
78  char **argv;
79  int line_num;
80  char *val;
81  unsigned int ospecs_len;
82 };
83 
84 result_t handler_line(struct probe *probe, tid_t tid, void *data,
85  struct probe *trigger, struct probe *base);
86 
87 /* Extract arguments into an table. */
88 void extract_args(int argc, char **argv, struct tgt_sym *task2sym);
89 
90 /* This is the argp parsing function */
91 error_t dt_argp_parse_opt(int key, char *arg, struct argp_state *state);
92 
93 struct argp_option dt_argp_opts[] = {
94  {"post", 'P', 0, 0, "Enable post handlers.", 0},
95  {"quiet", 'q', 0, 0, "Silent but deadly.", 0},
96  {0, 0, 0, 0, 0, 0},
97 };
98 
99 struct argp dt_argp = {
100  dt_argp_opts, dt_argp_parse_opt, NULL, NULL, NULL, NULL, NULL,
101 };
102 
104 
105 int main(int argc, char **argv) {
106  int i;
107  struct probe *probe;
108  struct target_spec *primary_target_spec = NULL;
109  GList *base_target_specs = NULL;
110  GList *overlay_target_specs = NULL;
111  GList *targets;
112  int rc;
113  struct evloop *evloop;
114  GList *t1;
115  struct target *target;
116  struct bsymbol *bsymbol;
117  struct tgt_sym *task2sym;
118  char filename[1024];
119  struct handler_data *fdata;
120 
121  target_init();
122  atexit(target_fini);
123  memset(&opts, 0, sizeof(opts));
124 
125  /*
126  * After we prepare the necessary data structure and parsing function,
127  * we call this function to put the arguments into opts.
128  */
129  rc = target_argp_driver_parse(&dt_argp, &opts, argc, argv,
131  | TARGET_TYPE_GDB, 1,
132  &primary_target_spec, &base_target_specs,
133  &overlay_target_specs);
134  if (rc) {
135  verror("could not parse target arguments!\n");
136  exit(-1);
137  }
138 
140 
141  /* Create the evloop structure */
142  evloop = evloop_create(NULL);
143 
144  /* instantiate and open the targets */
145  targets = target_instantiate_and_open(primary_target_spec,
146  base_target_specs,
147  overlay_target_specs, evloop, NULL);
148  if (!targets) {
149  verror("could not instantiate and open targets!\n");
150  exit(-1);
151  }
152  task2sym = (struct tgt_sym *) calloc(argc, sizeof(struct tgt_sym));
153 
154  /* extract the arguments into the task2sym table */
155  extract_args(opts.argc, opts.argv, task2sym);
156 
157  for (i = 0; i < opts.argc; ++i) {
158  target = target_lookup_target_id(task2sym[i].tgtid);
159  if (!target) {
160  fprintf(stderr,
161  "Could not lookup target %d for symbol %s; aborting!\n",
162  task2sym[i].tgtid, task2sym[i].sym_name);
164  exit(-3);
165  }
166  bsymbol = target_lookup_sym(target, task2sym[i].sym_name, NULL, NULL,
168  if (!bsymbol) {
169  fprintf(stderr, "could not lookup symbol %s; aborting!\n",
170  task2sym[i].sym_name);
172  exit(-3);
173  }
174 
175  /* We use fdata to transfer the task2sym table to the probe handler */
176  fdata = (struct handler_data *) calloc(1, sizeof(*fdata));
177  fdata->task2sym_entry = task2sym[i];
178 
179  /* Create a probe for a target with a name and a handler */
180  probe =
181  probe_create(target, TID_GLOBAL, NULL,
182  task2sym[i].file_name, handler_line, handler_line,
183  fdata, 0, 0);
184  if (!probe) {
185  fprintf(stderr, "creating probe failed; aborting!\n");
187  exit(-3);
188  }
189 
190  /* Insert a probe point (break point here) in action */
191  memset(filename, 0, 1024);
192  strcat(filename, task2sym[i].file_name);
193  fprintf(stderr,"filename == %s\n", filename);
194  probe =
195  probe_register_line(probe, filename, task2sym[i].line,
196  PROBEPOINT_SW, 0, 0);
197  if (!probe) {
198  fprintf(stderr, "probe register failed; aborting!\n");
200  exit(-3);
201  }
202  bsymbol_release(bsymbol);
203  }
204 
205  /*
206  * The target is paused after the attach; we have to resume it now
207  * that we've registered probes (or hit the at_symbol).
208  */
209  v_g_list_foreach(targets, t1, target) {
210  target_resume(target);
211  }
212 
213  fprintf(stderr, "Starting main debugging loop!\n");
214  //fflush(stdout);
215 
216  while (1) {
217  tid_t tid = 0;
218  struct target *t;
219  target_status_t tstat;
220  char *tname;
221 
222  rc = target_monitor_evloop(evloop, NULL, &t, &tstat);
223 
224  /* Did we get interrupted safely? */
226  /* Did we experience an error in select() or in evloop? */
227  else if (rc < 0) {
228  fprintf(stderr, "error in target_monitor_evloop (%d): %s;"
229  " attempting to continue!\n", rc, strerror(errno));
230  continue;
231  }
232  /* Did we experience a significant event on a target? */
233  else if (rc == 0 && evloop_maxsize(evloop) < 0) {
234  break;
235  }
236  else if (rc == 0) {
237  tid = target_gettid(t);
238  tname = target_name(t);
239  if (tstat == TSTATUS_ERROR) {
240  fprintf(stderr,
241  "Error handling target '%s'; closing and finalizing!\n",
242  tname);
243 
244  target_close(t);
245  target_finalize(t);
246  targets = g_list_remove(targets, t);
247  }
248  else if (tstat == TSTATUS_DONE) {
249  fprintf(stderr, "Target '%s' finished; finalizing!\n", tname);
250 
251  target_close(t);
252  target_finalize(t);
253  targets = g_list_remove(targets, t);
254  }
255  else if (tstat == TSTATUS_EXITING) {
256  fprintf(stderr, "Target '%s' exiting...\n", tname);
257  }
258  else if (tstat == TSTATUS_INTERRUPTED) {
259  fprintf(stderr, "Target '%s' interrupted, resuming...\n",
260  tname);
261  if (target_resume(t)) {
262  fprintf(stderr,
263  "Could not resume target %s tid %" PRIiTID "\n",
264  tname, tid);
265 
266  target_close(t);
267  target_finalize(t);
268  targets = g_list_remove(targets, t);
269  }
270  }
271  else {
272  fprintf(stderr,
273  "Target '%s' tid %d received unexpected status '%s'"
274  " at 0x%" PRIxADDR "; attempting to continue!\n",
275  tname, tid, TSTATUS(tstat), target_read_reg(t, tid,
276  CREG_IP));
277  if (target_resume(t)) {
278  fprintf(stderr,
279  "Could not resume target %s tid %" PRIiTID "\n",
280  tname, tid);
281 
282  target_close(t);
283  target_finalize(t);
284  targets = g_list_remove(targets, t);
285  }
286  }
287  }
288  }
289  fprintf(stderr,"Monitoring completed; exiting!\n");
290 
291  exit(0);
292 }
293 
294 error_t dt_argp_parse_opt(int key, char *arg, struct argp_state *state) {
295  struct dt_argp_state *opts =
296  (struct dt_argp_state *) target_argp_driver_state(state);
297 
298  switch (key) {
299  case ARGP_KEY_ARG:
300  /*
301  * We want to process all the remaining args, so bounce to the
302  * next case by returning this value.
303  */
304  return ARGP_ERR_UNKNOWN;
305  case ARGP_KEY_ARGS:
306  /* Eat all the remaining args. */
307  if (state->quoted > 0)
308  opts->argc = state->quoted - state->next;
309  else
310  opts->argc = state->argc - state->next;
311  if (opts->argc > 0) {
312  opts->argv = calloc(opts->argc, sizeof(char *));
313  memcpy(opts->argv, &state->argv[state->next],
314  opts->argc * sizeof(char *));
315  state->next += opts->argc;
316  }
317  return 0;
318  case ARGP_KEY_INIT:
320  return 0;
321  case ARGP_KEY_END:
322  case ARGP_KEY_NO_ARGS:
323  case ARGP_KEY_SUCCESS:
324  return 0;
325  case ARGP_KEY_ERROR:
326  case ARGP_KEY_FINI:
327  return 0;
328  case 'P':
329  opts->do_post = 1;
330  break;
331  case 'q':
332  opts->quiet = 1;
333  break;
334  default:
335  return ARGP_ERR_UNKNOWN;
336  }
337 
338  return 0;
339 }
340 
341 result_t handler_line(struct probe * probe, tid_t tid, void *data,
342  struct probe * trigger, struct probe * base) {
343  struct value *value;
344  char buf[1024];
345  char outbuf[2048];
346  memset(outbuf, 0, 2048);
347  struct bsymbol *psym;
348  struct target *target;
349  struct target_location_ctxt *tlctxt;
350  REGVAL ipval;
351  struct bsymbol *function;
352 
353  target = probe_target(probe);
354  psym = target_lookup_sym(target,
355  ((struct handler_data *) data)->task2sym_entry.
356  sym_name, NULL, NULL, SYMBOL_TYPE_FLAG_NONE);
357  if (!psym) {
358  printf("Could not get any symbol!\n");
359  exit(-1);
360  }
361  tlctxt = target_location_ctxt_create_from_bsymbol(target, tid, psym);
362  value = target_load_symbol(target, tlctxt, psym, LOAD_FLAG_NONE);
363  if (value) {
364  value_snprintf(value, buf, sizeof(buf));
365  snprintf(outbuf,sizeof(bsymbol_get_name(psym))+sizeof(buf)+21,
366  "Value of %s is now '%s'", bsymbol_get_name(psym), buf);
367  // I just print out the required format but do make use of most of the
368  // fields, because in this example I just want to print out values I get
369  fprintf(stdout,"RESULT:: (%c:%d) %s (%d) %s \"%s\" () ::RESULT\n",
370  'r',1,"--",1,"--", outbuf);
371  }
372  ipval = target_read_creg(target, tid, CREG_IP);
373  if (ipval && errno) {
374  fprintf(stderr, "ERROR: could not read IP register!\n");
375  }
376  else {
377  function = target_lookup_sym_addr(target, ipval);
378  if (function) {
379  //printf("Hit in function '%s' at IP 0x%" PRIxREGVAL
380  // "\n", bsymbol_get_name(function) ? : "", ipval);
381  bsymbol_release(function);
382  }
383  else {
384  printf("In unknown function at IP 0x%" PRIxREGVAL "\n", ipval);
385  }
386  }
387  fflush(stdout);
388 
390 
391  return RESULT_SUCCESS;
392 }
393 
394 void extract_args(int argc, char **argv, struct tgt_sym *task2sym) {
395  char *tmpfile, *tmpline, *tmpval;
396  int i;
397  char **argv_tmp;
398 
399  argv_tmp = (char **) malloc(sizeof(char *) * argc);
400  for (i = 0; i < argc; i++) {
401  argv_tmp[i] = (char *) malloc(128);
402  memset(argv_tmp[i], 0, 128);
403  fprintf(stderr,"argc %d,argv[%d]==%s\n", argc, i, argv[i]);
404  strcpy(argv_tmp[i], argv[i]);
405  }
406  for (i = 0; i < argc; i++) {
407  /* Get the target id */
408  tmpfile = index(argv_tmp[i], ':');
409  *tmpfile = '\0';
410  task2sym[i].tgtid = atoi(argv_tmp[i]);
411  fprintf(stderr,"tgtid = %d\n", task2sym[i].tgtid);
412 
413  /* Get the file name */
414  tmpline = index(tmpfile + 1, ':');
415  *tmpline = '\0';
416  task2sym[i].file_name = tmpfile + 1;
417  fprintf(stderr,"task name = %s\n", task2sym[i].file_name);
418 
419  /* Get the line number */
420  tmpval = index(tmpline + 1, ':');
421  *tmpval = '\0';
422  task2sym[i].line = atoi(tmpline + 1);
423  fprintf(stderr,"line = %d\n", task2sym[i].line);
424 
425  /* Get the valuable name */
426  task2sym[i].sym_name = tmpval + 1;
427  fprintf(stderr,"sym_name = %s\n", task2sym[i].sym_name);
428  }
429  for (i = 0; i < argc; i++) {
430  fprintf(stderr,"the tgtid == %d file_name == %s, line == %d, \
431  sym_name == %s \n",
432  task2sym[i].tgtid, task2sym[i].file_name, task2sym[i].line,
433  task2sym[i].sym_name);
434  }
435 
436  return;
437 }
struct value * target_load_symbol(struct target *target, struct target_location_ctxt *tlctxt, struct bsymbol *bsymbol, load_flags_t flags)
Definition: target.c:3270
struct dt_argp_state opts
struct argp_option dt_argp_opts[]
void * state
Definition: target_api.h:2526
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
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
void extract_args(int argc, char **argv, struct tgt_sym *task2sym)
int target_resume(struct target *target)
Definition: target_api.c:1012
#define v_g_list_foreach(glhead, glcur, elm)
Definition: glib_wrapper.h:34
struct target_location_ctxt * target_location_ctxt_create_from_bsymbol(struct target *target, tid_t tid, struct bsymbol *bsymbol)
Definition: target.c:5325
tid_t target_gettid(struct target *target)
Definition: target_api.c:1918
char * bsymbol_get_name(struct bsymbol *bsymbol)
Definition: symbol.c:62
result_t handler_line(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
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
char * file_name
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
struct tgt_sym task2sym_entry
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 argp dt_argp
char * buf
Definition: target_api.h:3298
#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
struct bsymbol * target_lookup_sym_addr(struct target *target, ADDR addr)
Definition: target.c:2093
error_t dt_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: probe.h:308
struct probe * probe_create(struct target *target, tid_t tid, struct probe_ops *pops, const char *name, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data, int autofree, int tracked)
Definition: probe.c:729
struct target * probe_target(struct probe *probe)
Definition: probe.c:1943
REGVAL target_read_creg(struct target *target, tid_t tid, common_reg_t reg)
Definition: target_api.c:1178
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
uint32_t REGVAL
Definition: common.h:66
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
char * sym_name
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
void target_location_ctxt_free(struct target_location_ctxt *tlctxt)
Definition: target.c:5348
unsigned int ospecs_len
Definition: dumptarget.c:87
int main(int argc, char **argv)
struct probe * probe_register_line(struct probe *probe, char *filename, int line, probepoint_style_t style, probepoint_whence_t whence, probepoint_watchsize_t watchsize)
Definition: probe.c:1403
void * malloc(size_t size)
Definition: debugserver.c:214
#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
#define PRIxREGVAL
Definition: common.h:72