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
trace_task.c
Go to the documentation of this file.
1 /*
2  * Collect a branch trace of the traced guest over the indicated time frame.
3  *
4  * "Time frame" here is represented by start and end EIP+brctr values.
5  * Note that the EIP is actually a symbol and the branch counter value is
6  * optional. If the start location has no brctr, it is taken to mean the
7  * first time the symbol is hit. If the end location has no brctr, it is
8  * taken to mean the first time hit after the start has been reached.
9  *
10  * Once the trace has been completed, we extract it from the replay logfile
11  * and write it to a file.
12  */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <signal.h>
18 
19 #include <dwdebug.h>
20 #include <target_api.h>
21 #include <target.h>
22 #include <target_xen_vm.h>
23 
24 #include <probe_api.h>
25 #include <probe.h>
26 #include <alist.h>
27 
28 #include <xentt.h>
29 #include <bts.h>
30 
31 int debug = 0;
32 static struct xentt_replay_session *session;
33 static char *symfile;
34 static struct target *target;
35 static struct bsymbol ssymbol, esymbol;
36 static int xc = -1;
37 GHashTable *probes;
38 
39 static int check_symbols(char *statedir, char *ssym, char *esym);
40 static int register_probe(struct target *t, GHashTable *probes, char *symname,
41  struct bsymbol *sym);
42 static void unregister_probes(GHashTable *probes);
43 
44 static void
45 onexit(int sig)
46 {
47  if (target != NULL) {
48  target_pause(target);
49  unregister_probes(probes);
50  target_close(target);
51  }
52  if (session != NULL)
53  xentt_replay_destroy(session);
54  if (xc != -1)
55  xc_interface_close(xc);
56  exit(sig);
57 }
58 
59 static int
60 handler(struct probe *probe, void *handler_data, struct probe *trigger)
61 {
62  fprintf(stderr, "handler called\n");
63 
64  /* turn on BTS */
65  /* use VMI to put a probe on the end point and run til then */
66  /* turn off BTS */
67 
68  return 0;
69 }
70 
71 int
72 main(int argc, char **argv)
73 {
74  char *name, *statedir;
75  char *s_sym, *e_sym;
76  unsigned long long s_brctr, e_brctr;
77  target_status_t tstat;
78  char ch, *cp;
79  struct target_spec *tspec;
80 
81  while ((ch = getopt(argc, argv, "d")) != -1) {
82  switch(ch) {
83  case 'd':
84  debug++;
85  break;
86  }
87  }
88  argc -= optind;
89  argv += optind;
90 
91  if (argc < 3) {
92  fprintf(stderr, "Usage: trace_task statedir start-sym[:brctr] end-sym[:brctr]\n");
93  exit(1);
94  }
95  statedir = argv[0];
96  if ((cp = index(argv[1], ':')) != 0 && cp[1] != '\0') {
97  *cp = '\0';
98  s_sym = strdup(argv[1]);
99  s_brctr = strtoull(cp+1, NULL, 0);
100  *cp = ':';
101  } else {
102  s_sym = strdup(argv[1]);
103  s_brctr = 0;
104  }
105  if ((cp = index(argv[2], ':')) != 0 && cp[1] != '\0') {
106  *cp = '\0';
107  e_sym = strdup(argv[2]);
108  e_brctr = strtoull(cp+1, NULL, 0);
109  *cp = ':';
110  } else {
111  e_sym = strdup(argv[2]);
112  e_brctr = 0;
113  }
114  if (debug)
115  fprintf(stderr, "Start: %s:%llu, End: %s:%llu\n",
116  s_sym, s_brctr, e_sym, e_brctr);
117 
118  /*
119  * XXX heavily tied to the tt_record/tt_replay scripts right now.
120  * We use the last component of the state directory name as the
121  * domain name.
122  */
123  name = rindex(statedir, '/');
124  if (name == 0) {
125  fprintf(stderr, "Could not determine name from statedir %s\n",
126  statedir);
127  exit(1);
128  }
129  name++;
130 
131  /*
132  * Make sure the symbols are legit for the replay OS.
133  */
134  if (check_symbols(statedir, s_sym, e_sym)) {
135  fprintf(stderr, "Could not resolve start/end symbols\n");
136  exit(1);
137  }
138 
139  /*
140  * Don't leave behind unsightly domains.
141  */
142  signal(SIGINT, onexit);
143  signal(SIGTERM, onexit);
144  signal(SIGHUP, onexit);
145  signal(SIGQUIT, onexit);
146  signal(SIGABRT, onexit);
147  signal(SIGKILL, onexit);
148  signal(SIGSEGV, onexit);
149  signal(SIGPIPE, onexit);
150  signal(SIGALRM, onexit);
151  signal(SIGUSR1, onexit);
152  signal(SIGUSR2, onexit);
153 
154  /*
155  * Create a replay session.
156  */
157  if (debug)
158  fprintf(stderr, "Creating replay session %s from %s\n",
159  name, statedir);
160 
161  session = xentt_replay_create(name, statedir);
162  if (session == NULL) {
163  fprintf(stderr, "Could not create replay session %s from %s\n",
164  name, statedir);
165  exit(1);
166  }
167  if (xentt_replay_start(session, NULL) != 0) {
168  fprintf(stderr, "Could not start replay session %s\n", name);
169  onexit(1);
170  }
171 
172  dwdebug_init();
174  xa_set_debug_level(debug);
175 
177  ((struct xen_vm_spec *)tspec->backend_spec)->domain = name;
178 
179  if ((target = target_instantiate(tspec,NULL)) == NULL) {
180  fprintf(stderr, "xen_vm_attach failed for %s\n", name);
181  onexit(1);
182  }
183  if (target_open(target) != 0) {
184  fprintf(stderr, "cannot open target %s!\n", name);
185  onexit(1);
186  }
187 
188  /* use VMI to put a probe on the start point and run til then */
189  if (register_probe(target, probes, s_sym, &ssymbol) != 0) {
190  fprintf(stderr, "failed to register start probe\n");
191  exit(1);
192  }
193 
194  xc = xc_interface_open();
195  if (xc == -1) {
196  fprintf(stderr, "Could not get xc handle\n");
197  exit(1);
198  }
199 
200  target_resume(target);
201  while (1) {
202  tstat = target_monitor(target);
203  if (tstat != TSTATUS_PAUSED)
204  break;
205 
206  printf("domain %s interrupted at 0x%" PRIxREGVAL "\n", name,
207  target_read_reg(target, TID_GLOBAL, target->ipregno));
208  if (target_resume(target)) {
209  fprintf(stderr, "Can't resume target dom %s\n", name);
210  tstat = TSTATUS_ERROR;
211  break;
212  }
213  }
214 
215  if (tstat == TSTATUS_DONE) {
216  /* extract the branch trace from the replay log, dump to file */
217  onexit(0);
218  }
219 
220  onexit(-1);
221 }
222 
223 static int check_symbols(char *statedir, char *ssym, char *esym)
224 {
225  char buf[256], *bp;
226  FILE *fd;
227  struct symmap map[1];
228  struct lsymbol *s = 0, *e = 0;
229  int rv;
230 
231  snprintf(buf, sizeof buf, "%s/symfile", statedir);
232  if ((fd = fopen(buf, "r")) == NULL) {
233  perror(buf);
234  return -1;
235  }
236  rv = fscanf(fd, "%s", buf);
237  fclose(fd);
238  if (rv != 1) {
239  perror("fscanf");
240  return -1;
241  }
242 
243  if ((bp = index(buf, '\n')) != 0)
244  *bp = '\0';
245  symfile = strdup(buf);
246 
247  memset(map, 0, sizeof(struct symmap));
248  map[0].symfile = symfile;
249  if (symlist_init(map, 1))
250  return -1;
251 
252  if (debug)
253  fprintf(stderr, "Looking up symbols in '%s'\n", symfile);
254 
255  rv = 1;
256  s = symlist_lookup_name(ssym);
257  if (s) {
258  if (debug)
259  fprintf(stderr, "Found %s\n", ssym);
260  e = symlist_lookup_name(esym);
261  if (e) {
262  if (debug)
263  fprintf(stderr, "Found %s\n", esym);
264  rv = 0;
265  }
266  }
267  if (s) {
268  if (debug)
269  fprintf(stderr, "Releasing %s\n", ssym);
270  lsymbol_release(s);
271  }
272  if (e) {
273  if (debug)
274  fprintf(stderr, "Releasing %s\n", esym);
275  lsymbol_release(e);
276  }
277  symlist_deinit();
278 
279  return rv;
280 }
281 
282 static int
283 register_probe(struct target *target, GHashTable *probes, char *symname,
284  struct bsymbol *sym)
285 {
286  struct probe *probe;
287  struct bsymbol *bsymbol;
288 
289  bsymbol = target_lookup_sym(target, symname, ".", NULL,
291  if (!bsymbol) {
292  fprintf(stderr, "Could not find symbol %s!\n", symname);
293  return -1;
294  }
295 
296  //bsymbol_dump(bsymbol, &udn);
297 
298  /* Create a probe for the given EIP */
299  probe = probe_create(target, TID_GLOBAL, NULL, symname,
300  handler, NULL, NULL, 0, 0);
301  if (!probe) {
302  fprintf(stderr,
303  "could not create probe for '%s'\n", symname);
304  unregister_probes(probes);
305  return -1;
306  }
307 
308  if (!probe_register_symbol(probe,
309  bsymbol, PROBEPOINT_FASTEST,
311  fprintf(stderr, "could not register probe on '%s'\n",
312  bsymbol->lsymbol->symbol->name);
313  probe_free(probe, 1);
314  unregister_probes(probes);
315  return -1;
316  }
317  g_hash_table_insert(probes,
318  (gpointer)probe->probepoint->addr,
319  (gpointer)probe);
320 
321  return 0;
322 }
323 
324 static void unregister_probes(GHashTable *probes)
325 {
326  GHashTableIter iter;
327  gpointer key;
328  struct probe *probe;
329 
330  g_hash_table_iter_init(&iter, probes);
331  while (g_hash_table_iter_next(&iter, (gpointer)&key, (gpointer)&probe)) {
332  probe_unregister(probe,1);
333  }
334 }
335 
336 /*
337  * Local variables:
338  * mode: C
339  * c-set-style: "BSD"
340  * c-basic-offset: 4
341  * End:
342  */
int probe_unregister(struct probe *probe, int force)
Definition: probe.c:1137
void * backend_spec
Definition: target_api.h:2290
int optind
struct lsymbol * lsymbol
Definition: target.h:1017
REFCNT lsymbol_release(struct lsymbol *lsymbol)
Definition: debug.c:4805
target_status_t
Definition: target_api.h:197
struct target_spec * tspec
Definition: dumptarget.c:113
struct symbol * symbol
Definition: dwdebug.h:1010
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
ADDR addr
Definition: probe.h:218
int target_resume(struct target *target)
Definition: target_api.c:1012
int target_pause(struct target *target)
Definition: target_api.c:1027
int main(int argc, char **argv)
Definition: trace_task.c:72
int target_close(struct target *target)
Definition: target_api.c:1511
struct list_head probe
Definition: probe.h:379
void vmi_set_log_level(int level)
Definition: log.c:34
void dwdebug_init(void)
Definition: debug.c:83
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1132
int probe_free(struct probe *probe, int force)
Definition: probe.c:777
char * name
Definition: dwdebug_priv.h:788
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_spec * target_build_spec(target_type_t type, target_mode_t mode)
Definition: target_api.c:410
struct lsymbol * symlist_lookup_name(char *name)
Definition: symbol.c:338
int target_open(struct target *target)
Definition: target_api.c:513
target_status_t target_monitor(struct target *target)
Definition: target_api.c:869
int debug
Definition: trace_task.c:31
int symlist_init(struct symmap[], int)
Definition: symbol.c:20
Definition: bts.h:7
struct target * target_instantiate(struct target_spec *spec, struct evloop *evloop)
Definition: target_api.c:55
struct probe * probe_register_symbol(struct probe *probe, struct bsymbol *bsymbol, probepoint_style_t style, probepoint_whence_t whence, probepoint_watchsize_t watchsize)
Definition: probe.c:1470
REG ipregno
Definition: target_api.h:2508
#define TID_GLOBAL
Definition: target_api.h:145
GHashTable * probes
Definition: trace_task.c:37
struct probepoint * probepoint
Definition: probe.h:347
struct target * t
Definition: dumptarget.c:48
void symlist_deinit(void)
Definition: symbol.c:356
#define PRIxREGVAL
Definition: common.h:72