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
spf.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 <inttypes.h>
24 #include <signal.h>
25 #include <argp.h>
26 
27 #include "log.h"
28 #include "glib_wrapper.h"
29 #include "dwdebug.h"
30 #include "target_api.h"
31 #include "target.h"
32 #include "target_os.h"
33 
34 #include "probe_api.h"
35 #include "probe.h"
36 #include "alist.h"
37 #include "list.h"
38 
39 /*
40  * Private vdebug flags for LA_USER for us.
41  */
42 #define LF_U_CFG 1 << 1
43 #define LF_U_PROBE 1 << 2
44 
45 /*
46  * Types.
47  */
48 typedef enum {
59 
60 struct spf_action {
62 
63  union {
64  struct {
65  char rt;
66  char *tn;
67  int tid;
68  char *rv;
69  char *msg;
70  int ttctx;
71  int ttdetail;
72  int bt;
75  } report;
76  struct {
77  int ttctx;
78  int ttdetail;
79  } print;
80  struct {
81  long int retval;
82  } abort;
83  struct {
84  long int retval;
85  } exit;
86  struct {
87  char *id;
88  } enable;
89  struct {
90  char *id;
91  } disable;
92  struct {
93  char *id;
94  } remove;
95  struct {
96  int tid;
97  char *thid;
98  int overlay_levels;
100  } bt;
101  struct {
102  int tid;
103  char *thid;
104  char *sigdesc;
105  } signal;
106  };
107 };
108 
109 #define WHEN_PRE 0
110 #define WHEN_POST 1
111 
112 struct spf_filter {
113  char *id;
114 
115  char *srcfile;
116  char *symbol;
117  struct bsymbol *bsymbol;
118  /* When it's applied; pre or post. */
119  int when;
120  uint8_t disable:1;
121  /*
122  * symbol value regexps
123  */
125  /*
126  * tid, ptid, tidhier^, uid, gid, name, namehier^...
127  */
129  GSList *actions;
130 };
131 
132 struct spf_config {
134 };
135 
136 struct overlay_spec {
137  char *base_target_id;
139  struct target_spec *spec;
140 };
141 
143  int argc;
144  char **argv;
145  char *config_file;
150 };
151 
152 /*
153  * Globals.
154  */
155 GList *targets;
156 struct spf_config *config = NULL;
158 
159 GHashTable *sprobes = NULL;
160 GHashTable *fprobes = NULL;
161 
162 int needtodie = 0;
164 
166 
167 /* A few prototypes. */
168 struct spf_config *load_config_file(char *file);
169 int apply_config_file(struct spf_config *config);
170 void reload_config_file(void);
171 void spf_action_free(struct spf_action *spfa);
172 void spf_filter_free(struct spf_filter *spff);
173 void spf_config_free(struct spf_config *config);
174 
175 
177  GHashTableIter iter;
178  gpointer key;
179  struct probe *probe;
180  GList *t1;
181  struct target *target;
182 
183  v_g_list_foreach(targets,t1,target) {
184  target_pause(target);
185  }
186 
187  if (fprobes) {
188  g_hash_table_iter_init(&iter,fprobes);
189  while (g_hash_table_iter_next(&iter,
190  (gpointer)&key,
191  (gpointer)&probe)) {
192  probe_unregister(probe,1);
193  probe_free(probe,1);
194  }
195  g_hash_table_destroy(fprobes);
196  fprobes = NULL;
197  }
198  if (sprobes) {
199  g_hash_table_iter_init(&iter,sprobes);
200  while (g_hash_table_iter_next(&iter,
201  (gpointer)&key,
202  (gpointer)&probe)) {
203  probe_unregister(probe,1);
204  probe_free(probe,1);
205  }
206  g_hash_table_destroy(sprobes);
207  sprobes = NULL;
208  }
209 }
210 
212 
213 void sigh_cleanup_probes(int signo,siginfo_t *siginfo,void *x) {
214  if (sigismember(&exitset,signo)) {
215  cleanup_probes();
216  }
217 }
218 
219 void print_thread_context(FILE *stream,struct target *target,tid_t tid,
220  int ttctx,int ttdetail,int bt,int overlay_levels,
221  char *overlay_debuginfo_prefix,char *sep,char *kvsep,
222  char *tprefix,char *tsep) {
223  struct target_thread *tthread;
224  char buf[4096];
225  struct array_list *tids;
226  int i,j;
227  int rc;
228  int didmaintid = 0;
229  tid_t ttid;
230  struct target *overlay;
231  struct array_list *otl;
232  struct target_spec *ospec;
233 
234  if (ttctx == 0)
235  return;
236  else if (ttctx == 1) {
237  tids = array_list_create(1);
238  array_list_append(tids,(void *)(uintptr_t)tid);
239  }
240  else if (ttctx == 2) {
241  tids = array_list_create(8);
242  /* Just walk up the parent hierarchy. */
243  ttid = tid;
244  while (1) {
245  tthread = target_lookup_thread(target,ttid);
246  if (!tthread)
247  break;
248  array_list_append(tids,(void *)(uintptr_t)ttid);
249  ttid = tthread->ptid;
250  }
251  }
252  else if (ttctx == 3) {
253  tids = target_list_available_tids(target);
254  /* Make sure selected tid is first; skip it later. */
255  if (!tids)
256  tids = array_list_create(1);
257  array_list_prepend(tids,(void *)(uintptr_t)tid);
258  }
259  else
260  return;
261 
262  array_list_foreach_fakeptr_t(tids,i,ttid,uintptr_t) {
263  tthread = target_lookup_thread(target,ttid);
264  if (!tthread)
265  continue;
266 
267  if (tthread->tid == tid && didmaintid)
268  continue;
269  else if (tthread->tid == tid)
270  didmaintid = 1;
271 
272  fprintf(stream,"%s",tsep);
273 
274  if (target_thread_snprintf(target,tthread->tid,buf,sizeof(buf),
275  ttdetail,sep,kvsep) < 0)
276  fprintf(stream,"%s[tid=%"PRIiTID"",tprefix,tthread->tid);
277  else
278  fprintf(stream,"%s[%s",tprefix,buf);
279 
280  if (bt) {
281  rc = target_unwind_snprintf(buf,sizeof(buf),target,tthread->tid,
283  if (rc < 0)
284  fprintf(stream,"%sbacktrace=[error!]",sep);
285  else if (rc == 0)
286  fprintf(stream,"%sbacktrace=[empty]",sep);
287  else
288  fprintf(stream,"%sbacktrace=[%s]",sep,buf);
289  }
290 
291  fprintf(stream,"]");
292 
293  /*
294  * Handle overlay levels! Woot!
295  */
296  otl = array_list_create(8);
297  overlay = target;
298  ttid = tthread->tid;
299  while (overlay_levels != 0) {
300  ospec = target_build_default_overlay_spec(overlay,ttid);
301  if (!ospec)
302  break;
303 
304  if (overlay_debuginfo_prefix)
305  ospec->debugfile_root_prefix = strdup(overlay_debuginfo_prefix);
306 
307  overlay = target_instantiate_overlay(overlay,ttid,ospec);
308  if (!overlay)
309  break;
310 
311  target_open(overlay);
312 
313  fprintf(stream,"%s",tsep);
314 
315  if (target_thread_snprintf(overlay,ttid,buf,sizeof(buf),
316  ttdetail,sep,kvsep) < 0)
317  fprintf(stream,"%s[overlay=%s%stid=%"PRIiTID"",
318  tprefix,overlay->name,sep,ttid);
319  else
320  fprintf(stream,"%s[overlay=%s%s%s",
321  tprefix,overlay->name,sep,buf);
322 
323  if (bt) {
324  rc = target_unwind_snprintf(buf,sizeof(buf),overlay,ttid,
326  "|",",");
327  if (rc < 0)
328  fprintf(stream,"%sbacktrace=[error!]",sep);
329  else if (rc == 0)
330  fprintf(stream,"%sbacktrace=[empty]",sep);
331  else
332  fprintf(stream,"%sbacktrace=[%s]",sep,buf);
333  }
334 
335  fprintf(stream,"]");
336 
337  --overlay_levels;
338 
339  array_list_prepend(otl,overlay);
340  }
341 
342  array_list_foreach(otl,j,overlay) {
343  target_close(overlay);
344  target_finalize(overlay);
345  }
346 
347  array_list_free(otl);
348  otl = NULL;
349  }
350 
351  array_list_free(tids);
352 }
353 
354 void spf_backtrace(struct target *t,tid_t ctid,char *tiddesc,
355  int overlay_levels,char *overlay_debuginfo_prefix) {
356  struct array_list *tids;
357  tid_t tid;
358  int i;
359  tid_t stid = -1;
360  struct target_thread *tthread;
361  char *endptr = NULL;
362  int rc;
363  char buf[4096];
364  struct target *overlay;
365  struct array_list *otl;
366  struct target_spec *ospec;
367 
368  if (tiddesc) {
369  stid = (int)strtol(tiddesc,&endptr,10);
370  if (tiddesc == endptr)
371  stid = -1;
372  else
373  tiddesc = NULL;
374  }
375  else
376  stid = -1;
377 
378  /*
379  * If stid == 0 or tiddesc, do them all.
380  *
381  * If it == -1 && !tiddesc, do ctid.
382  *
383  * If it >= 0, do that one.
384  */
385 
386  if (stid == -1 && !tiddesc) {
387  tids = array_list_create(1);
388  array_list_append(tids,(void *)(uintptr_t)ctid);
389 
390  printf("Backtracing target '%s' (current thread %d):\n\n",t->name,ctid);
391  }
392  else if (stid > 0) {
393  tids = array_list_create(1);
394  array_list_append(tids,(void *)(uintptr_t)stid);
395 
396  printf("Backtracing target '%s' (thread %d):\n\n",t->name,stid);
397  }
398  else if (tiddesc) {
399  tids = target_list_tids(t);
400 
401  printf("Backtracing target '%s' (thread name %s):\n\n",t->name,tiddesc);
402  }
403  else {
404  tids = target_list_tids(t);
405 
406  printf("Backtracing target '%s' (all threads):\n\n",t->name);
407  }
408 
409  array_list_foreach_fakeptr_t(tids,i,tid,uintptr_t) {
410  tthread = target_lookup_thread(t,tid);
411  if (!tthread)
412  continue;
413 
414  if ((tiddesc && !tthread->name)
415  || (tiddesc && strcmp(tiddesc,tthread->name)))
416  continue;
417 
418  rc = target_unwind_snprintf(buf,sizeof(buf),t,tid,
419  TARGET_UNWIND_STYLE_GDB,"\n",",");
420  if (rc < 0)
421  fprintf(stdout,"\ntarget %s thread %"PRIiTID": (error!)\n",
422  t->name,tid);
423  else if (rc == 0)
424  fprintf(stdout,"\ntarget %s thread %"PRIiTID": (nothing)\n",
425  t->name,tid);
426  else
427  fprintf(stdout,"\ntarget %s thread %"PRIiTID": \n%s\n",
428  t->name,tid,buf);
429 
430  if (overlay_levels == 0)
431  continue;
432 
433  /*
434  * Handle overlay levels!
435  */
436  otl = array_list_create(8);
437  overlay = t;
438  while (overlay_levels != 0) {
439  ospec = target_build_default_overlay_spec(overlay,tid);
440  if (!ospec)
441  break;
442 
443  if (overlay_debuginfo_prefix)
444  ospec->debugfile_root_prefix = strdup(overlay_debuginfo_prefix);
445 
446  overlay = target_instantiate_overlay(overlay,tid,ospec);
447  if (!overlay)
448  break;
449 
450  target_open(overlay);
451 
452  rc = target_unwind_snprintf(buf,sizeof(buf),overlay,tid,
453  TARGET_UNWIND_STYLE_GDB,"\n",",");
454  if (rc < 0)
455  fprintf(stdout,"\ntarget %s thread %"PRIiTID": (error!)\n",
456  overlay->name,tid);
457  else if (rc == 0)
458  fprintf(stdout,"\ntarget %s thread %"PRIiTID": (nothing)\n",
459  overlay->name,tid);
460  else
461  fprintf(stdout,"\ntarget %s thread %"PRIiTID": \n%s\n",
462  overlay->name,tid,buf);
463 
464  --overlay_levels;
465 
466  array_list_prepend(otl,overlay);
467  }
468 
469  array_list_foreach(otl,i,overlay) {
470  target_close(overlay);
471  target_finalize(overlay);
472  }
473 
474  array_list_free(otl);
475  otl = NULL;
476  }
477 
478  fputs("\n",stdout);
479  fflush(stdout);
480 }
481 
482 int spf_signal(struct target *t,tid_t ctid,char *tiddesc,char *sigdesc) {
483  struct array_list *tids;
484  tid_t tid;
485  int i;
486  tid_t stid = -1;
487  struct target_thread *tthread;
488  char *endptr = NULL;
489  int rc;
490  int signo;
491 
492  signo = target_os_signal_from_name(t,sigdesc);
493 
494  if (tiddesc) {
495  stid = (int)strtol(tiddesc,&endptr,10);
496  if (tiddesc == endptr)
497  stid = -1;
498  else
499  tiddesc = NULL;
500  }
501  else
502  stid = -1;
503 
504  /*
505  * If stid == 0 or tiddesc, do them all.
506  *
507  * If it == -1 && !tiddesc, do ctid.
508  *
509  * If it >= 0, do that one.
510  */
511 
512  if (stid == -1 && !tiddesc) {
513  tids = array_list_create(1);
514  array_list_append(tids,(void *)(uintptr_t)ctid);
515 
516  printf("Signaling target '%s' (current thread %d):\n\n",t->name,ctid);
517  }
518  else if (stid > 0) {
519  tids = array_list_create(1);
520  array_list_append(tids,(void *)(uintptr_t)stid);
521 
522  printf("Signaling target '%s' (thread %d):\n\n",t->name,stid);
523  }
524  else if (tiddesc) {
525  tids = target_list_tids(t);
526 
527  printf("Signaling target '%s' (thread name %s):\n\n",t->name,tiddesc);
528  }
529  else {
530  tids = target_list_tids(t);
531 
532  printf("Signaling target '%s' (all threads):\n\n",t->name);
533  }
534 
535  array_list_foreach_fakeptr_t(tids,i,tid,uintptr_t) {
536  tthread = target_lookup_thread(t,tid);
537  if (!tthread)
538  continue;
539 
540  if ((tiddesc && !tthread->name)
541  || (tiddesc && strcmp(tiddesc,tthread->name)))
542  continue;
543 
544  rc = target_os_signal_enqueue(t,tid,signo,NULL);
545  if (rc < 0)
546  fprintf(stdout,"thread %"PRIiTID": (error!)\n",tid);
547  else if (rc == 0)
548  fprintf(stdout,"thread %"PRIiTID": success\n",tid);
549  else
550  fprintf(stdout,"thread %"PRIiTID": unknown status %d\n",tid,rc);
551  }
552 
553  fflush(stdout);
554 
555  return 0;
556 }
557 
558 result_t handler(int when,struct probe *probe,tid_t tid,void *data,
559  struct probe *trigger,struct probe *base) {
560  GHashTableIter iter;
561  gpointer kp,vp;
562  char vstrbuf[1024];
563  struct value *v;
564  GHashTable *vt;
565  struct bsymbol *bsymbol;
566  struct symbol *symbol;
567  int i,j;
568  int rc;
569  struct spf_filter *spff = (struct spf_filter *)data;
570  GSList *gsltmp;
571  struct spf_action *spfa;
572  struct probe *fprobe;
573  result_t retval = RESULT_SUCCESS;
574  struct target *btt,*st;
575 
576  /*
577  * Do all the actions.
578  */
579  v_g_slist_foreach(spff->actions,gsltmp,spfa) {
580  if (spfa->atype == SPF_ACTION_ABORT) {
581  /*
582  * Action has to be registered on the base probe!!
583  */
584  struct action *action = action_return(spfa->abort.retval);
585  if (!action) {
586  verror("probe %s: could not create action on probe %s !\n",
587  probe_name(probe),probe_name(base));
588  }
589  else if (action_sched(base,action,ACTION_ONESHOT,NULL,NULL)) {
590  verror("probe %s: could not schedule action on probe %s!\n",
591  probe_name(probe),probe_name(base));
592  action_release(action);
593  }
594  else {
596  "probe %s: scheduled return action on probe %s\n",
597  probe_name(probe),probe_name(base));
598  action_release(action);
599  }
600  }
601  else if (spfa->atype == SPF_ACTION_ENABLE) {
602  /* Check if it's us. No need to waste a hashtable lookup. */
603  if (strcmp(spfa->enable.id,probe_name(probe)) == 0)
604  fprobe = probe;
605  else
606  fprobe = (struct probe *) \
607  g_hash_table_lookup(fprobes,spfa->enable.id);
608  if (!fprobe) {
609  vwarn("probe %s: cannot enable nonexisting filter probe %s!\n",
610  probe_name(probe),spfa->enable.id);
611  }
612  else {
613  probe_enable(fprobe);
615  "probe %s: enabled filter probe %s\n",
616  probe_name(probe),spfa->enable.id);
617  }
618  }
619  else if (spfa->atype == SPF_ACTION_DISABLE) {
620  /* Check if it's us. No need to waste a hashtable lookup. */
621  if (strcmp(spfa->disable.id,probe_name(probe)) == 0)
622  fprobe = probe;
623  else
624  fprobe = (struct probe *) \
625  g_hash_table_lookup(fprobes,spfa->disable.id);
626  if (!fprobe) {
627  vwarn("probe %s: cannot enable nonexisting filter probe %s!\n",
628  probe_name(probe),spfa->disable.id);
629  }
630  else {
631  probe_disable(fprobe);
632  vdebug(5,LA_USER,LF_U_PROBE,"probe %s: disabled probe %s\n",
633  probe_name(probe),spfa->disable.id);
634  }
635  }
636  else if (spfa->atype == SPF_ACTION_REMOVE) {
637  /* Check if it's us -- to remove self we have to return special! */
638  if (strcmp(spfa->remove.id,probe_name(probe)) == 0) {
639  vdebug(5,LA_USER,LF_U_PROBE,"probe %s: removing self!\n",
640  probe_name(probe));
641  retval = RESULT_ABORT;
642  }
643  else {
644  fprobe = (struct probe *) \
645  g_hash_table_lookup(fprobes,spfa->remove.id);
646  if (!fprobe) {
647  vwarn("probe %s: cannot remove nonexisting filter probe %s!\n",
648  probe_name(probe),spfa->remove.id);
649  }
650  else {
651  probe_free(fprobe,0);
652  vdebug(5,LA_USER,LF_U_PROBE,"probe %s: removed probe %s\n",
653  probe_name(probe),spfa->remove.id);
654  }
655  }
656  }
657  else if (spfa->atype == SPF_ACTION_EXIT) {
658  /*
659  * Have to schedule a monitor interrupt to exit!
660  */
661  if (spfa->exit.retval == -69) {
662  cleanup_probes();
663  exit(-69);
664  }
665 
666  /*
667  * We don't need to actually interrupt the monitor, though,
668  * because we're in a handler -- so some driver is handling
669  * us.
670  */
672  needtodie = 1;
673  needtodie_exitcode = spfa->exit.retval;
674  vdebug(5,LA_USER,LF_U_PROBE,"probe %s: scheduled exit with %d!\n",
675  probe_name(probe),spfa->exit.retval);
676  }
677  else if (spfa->atype == SPF_ACTION_REPORT) {
678  ++result_counter;
679 
680  bsymbol = probe->bsymbol;
681  symbol = bsymbol_get_symbol(bsymbol);
682 
683  vt = probe_value_get_table(trigger,tid);
684  if (!vt) {
685  vwarn("probe %s: could not get values from probe %s"
686  " (tid %"PRIiTID")!\n",
687  probe_name(probe),probe_name(trigger),tid);
688  }
689 
690  fflush(stderr);
691  fflush(stdout);
692 
693  fprintf(stdout,"RESULT:: (%c:%d) %s (%d) %s %s (",
694  spfa->report.rt,result_counter,
695  spfa->report.tn ? spfa->report.tn : "",
696  spfa->report.tid,spfa->report.rv ? spfa->report.rv : "",
697  spfa->report.msg ? spfa->report.msg : "\"\"");
698  /* Now print the values... */
699  if (vt) {
700  i = 0;
701  g_hash_table_iter_init(&iter,vt);
702  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
703  if (i > 0)
704  fprintf(stdout,",");
705  v = (struct value *)vp;
706  if (v) {
707  rc = value_snprintf(v,vstrbuf,sizeof(vstrbuf));
708  if (rc > 0) {
709  int unprintable = 0;
710  for (j = 0; vstrbuf[j] != '\0'; ++j) {
711  if (!isgraph(vstrbuf[j]) && !isspace(vstrbuf[j])) {
712  unprintable = 1;
713  break;
714  }
715  }
716 
717  if (unprintable) {
718  vwarn("unprintable raw value for key %s = 0x",
719  (char *)kp);
720  for (j = 0; vstrbuf[j] != '\0'; ++j) {
721  vwarnc("%hhx",vstrbuf[j]);
722  }
723  vwarnc("\n");
724 
725  fprintf(stdout,"%s=??",(char *)kp);
726  }
727  else {
728  fprintf(stdout,"%s=%s",(char *)kp,vstrbuf);
729  }
730  }
731  else
732  fprintf(stdout,"%s=?",(char *)kp);
733  }
734  else
735  fprintf(stdout,"%s=?",(char *)kp);
736  ++i;
737  }
738  }
739  fputs(",",stdout);
740  print_thread_context(stdout,bsymbol->region->space->target,tid,
741  spfa->report.ttctx,spfa->report.ttdetail,
742  spfa->report.bt,spfa->report.overlay_levels,
743  spfa->report.overlay_debuginfo_prefix,
744  ";",":","thread=",",");
745  fprintf(stdout,") ::RESULT\n");
746  fflush(stdout);
747  }
748  else if (spfa->atype == SPF_ACTION_PRINT) {
749  bsymbol = probe->bsymbol;
750  symbol = bsymbol_get_symbol(bsymbol);
751 
752  vt = probe_value_get_table(trigger,tid);
753  if (!vt) {
754  vwarn("probe %s: could not get values from probe %s"
755  " (tid %"PRIiTID")!\n",
756  probe_name(probe),probe_name(trigger),tid);
757  }
758 
759  fflush(stderr);
760  fflush(stdout);
761 
763  fprintf(stdout,"%s (",symbol_get_name(symbol));
764  if (vt) {
765  i = 0;
766  g_hash_table_iter_init(&iter,vt);
767  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
768  if (strcmp((char *)kp,PROBE_VALUE_NAME_RETURN) == 0)
769  continue;
770  if (i > 0)
771  fprintf(stdout,",");
772  v = (struct value *)vp;
773  if (v) {
774  rc = value_snprintf(v,vstrbuf,sizeof(vstrbuf));
775  if (rc > 0)
776  fprintf(stdout,"%s = %s",(char *)kp,vstrbuf);
777  else
778  fprintf(stdout,"%s = ?",(char *)kp);
779  }
780  else
781  fprintf(stdout,"%s = ?",(char *)kp);
782  ++i;
783  }
784  }
785  else {
787  fprintf(stdout,"?");
788  else
789  fprintf(stdout," = ?");
790  }
792  fprintf(stdout,")");
793  if (vt) {
794  v = (struct value *) \
795  g_hash_table_lookup(vt,PROBE_VALUE_NAME_RETURN);
796  if (v) {
797  rc = value_snprintf(v,vstrbuf,sizeof(vstrbuf));
798  if (rc > 0)
799  fprintf(stdout," = %s",vstrbuf);
800  else
801  fprintf(stdout," = ?");
802  }
803  }
804  }
805  fputs(" ",stdout);
806  print_thread_context(stdout,bsymbol->region->space->target,tid,
807  spfa->print.ttctx,spfa->print.ttdetail,
808  0,0,NULL,NULL,NULL,"",",");
809  fputs("\n",stdout);
810  fflush(stdout);
811  }
812  else if (spfa->atype == SPF_ACTION_BT) {
813  if (spfa->bt.tid > 1) {
814  btt = target_lookup_target_id(spfa->bt.tid);
815  if (!btt) {
816  verror("no existing target with id '%d'!\n",spfa->bt.tid);
817  return RESULT_SUCCESS;
818  }
819  }
820  else
821  btt = probe->target;
822 
823  spf_backtrace(btt,tid,spfa->bt.thid,spfa->bt.overlay_levels,
824  spfa->bt.overlay_debuginfo_prefix);
825  }
826  else if (spfa->atype == SPF_ACTION_SIGNAL) {
827  if (spfa->signal.tid > 1) {
828  st = target_lookup_target_id(spfa->signal.tid);
829  if (!st) {
830  verror("no existing target with id '%d'!\n",
831  spfa->signal.tid);
832  return RESULT_SUCCESS;
833  }
834  }
835  else
836  st = probe->target;
837 
838  spf_signal(st,tid,spfa->signal.thid,spfa->signal.sigdesc);
839  }
840  else {
841  verror("probe %s: bad action type %d -- BUG!\n",
842  probe_name(probe),spfa->atype);
843  }
844  }
845 
846  return retval;
847 }
848 
849 result_t pre_handler(struct probe *probe,tid_t tid,void *data,
850  struct probe *trigger,struct probe *base) {
851  return handler(WHEN_PRE,probe,tid,data,trigger,base);
852 }
853 
854 result_t post_handler(struct probe *probe,tid_t tid,void *data,
855  struct probe *trigger,struct probe *base) {
856  return handler(WHEN_POST,probe,tid,data,trigger,base);
857 }
858 
859 /*
860  * This just makes sure values get loaded at the appropriate phases of
861  * the value probes so they are always available even if the probe is
862  * pre/post.
863  */
864 result_t null_handler(struct probe *probe,tid_t tid,void *data,
865  struct probe *trigger,struct probe *base) {
866  probe_value_get_table(trigger,tid);
867  return RESULT_SUCCESS;
868 }
869 
870 #define __TARGET_OVERLAY 0x200000
871 #define SPF_CONFIGFILE_FATAL 0x200001
872 #define SPF_OS_SYSCALL_PROBES 0x200002
873 
874 struct argp_option spf_argp_opts[] = {
875  { "overlay",__TARGET_OVERLAY,"[<target_id>:]<thread_name_or_id>:<spec_opts>",0,"Lookup name or id as an overlay target once the main target is instantiated, and try to open it. All dumptarget options then apply to the overlay.",0 },
876  { "config-file",'C',"<FILE>",0,"An SPF config file.",0 },
877  { "config-file-fatal",SPF_CONFIGFILE_FATAL,NULL,0,
878  "Make errors while applying runtime updates (via USR2) to the config file fatal.",0 },
879  { "use-os-syscall-probes",SPF_OS_SYSCALL_PROBES,NULL,0,
880  "Try to use target_os_syscall probes if symbol is a syscall and target is an OS.",0 },
881  { 0,0,0,0,0,0 },
882 };
883 
884 error_t spf_argp_parse_opt(int key,char *arg,struct argp_state *state) {
885  struct spf_argp_state *opts = \
886  (struct spf_argp_state *)target_argp_driver_state(state);
887 
888  switch (key) {
889  case ARGP_KEY_ARG:
890  return ARGP_ERR_UNKNOWN;
891  case ARGP_KEY_ARGS:
892  /* Eat all the remaining args. */
893  if (state->quoted > 0)
894  opts->argc = state->quoted - state->next;
895  else
896  opts->argc = state->argc - state->next;
897  if (opts->argc > 0) {
898  opts->argv = calloc(opts->argc,sizeof(char *));
899  memcpy(opts->argv,&state->argv[state->next],opts->argc*sizeof(char *));
900  state->next += opts->argc;
901  }
902  return 0;
903  case ARGP_KEY_INIT:
905  return 0;
906  case ARGP_KEY_END:
907  case ARGP_KEY_NO_ARGS:
908  case ARGP_KEY_SUCCESS:
909  return 0;
910  case ARGP_KEY_ERROR:
911  case ARGP_KEY_FINI:
912  return 0;
914  opts->config_file_fatal = 1;
915  break;
917  opts->use_os_syscall_probes = 1;
918  break;
919  case 'C':
920  opts->config_file = arg;
921  break;
922 
923  default:
924  return ARGP_ERR_UNKNOWN;
925  }
926 
927  return 0;
928 }
929 
930 struct argp spf_argp = {
931  spf_argp_opts,spf_argp_parse_opt,NULL,NULL,NULL,NULL,NULL,
932 };
933 
934 int main(int argc,char **argv) {
935  int i;
936  struct bsymbol *bsymbol;
937  struct probe *sprobe, *fprobe;
938  char *name, *context;
939  char *str;
940  char namebuf[128];
941  struct target_nv_filter *pre_pf, *post_pf;
942  char *pre_filter, *post_filter;
943  struct target_os_syscall *syscall;
944 
945  struct target_spec *primary_target_spec = NULL;
946  GList *base_target_specs = NULL;
947  GList *overlay_target_specs = NULL;
948  struct target *target;
949  int rc;
950  struct evloop *evloop;
951  GList *t1;
952 
953  target_init();
954  atexit(target_fini);
955 
956  /*
957  * We need to handle SIGUSR1, SIGUSR2, and SIGHUP specially so we
958  * can reload our config file as necessary.
959  */
960  sigemptyset(&ignored);
961  sigemptyset(&exitset);
962  sigemptyset(&interrupt);
963 
964  sigaddset(&exitset,SIGINT);
965  sigaddset(&exitset,SIGALRM);
966  sigaddset(&exitset,SIGQUIT);
967  sigaddset(&exitset,SIGILL);
968  sigaddset(&exitset,SIGABRT);
969  sigaddset(&exitset,SIGFPE);
970  sigaddset(&exitset,SIGSEGV);
971  sigaddset(&exitset,SIGPIPE);
972  sigaddset(&exitset,SIGTERM);
973  sigaddset(&exitset,SIGBUS);
974  sigaddset(&exitset,SIGXCPU);
975  sigaddset(&exitset,SIGXFSZ);
976 
977  sigaddset(&interrupt,SIGUSR1);
978  sigaddset(&interrupt,SIGUSR2);
979  sigaddset(&interrupt,SIGHUP);
980 
983 
984  memset(&opts,0,sizeof(opts));
985  rc = target_argp_driver_parse(&spf_argp,&opts,argc,argv,
988  &primary_target_spec,&base_target_specs,
989  &overlay_target_specs);
990 
991  if (rc) {
992  verror("could not parse target arguments!\n");
993  exit(-1);
994  }
995 
996  if (opts.config_file) {
997  config = load_config_file(opts.config_file);
998  if (!config) {
999  verror("could not read config file %s!\n",opts.config_file);
1000  exit(-11);
1001  }
1002  }
1003 
1004  evloop = evloop_create(NULL);
1005 
1006  targets = target_instantiate_and_open(primary_target_spec,
1007  base_target_specs,overlay_target_specs,
1008  evloop,NULL);
1009  if (!targets) {
1010  verror("could not instantiate and open targets!\n");
1011  exit(-1);
1012  }
1013 
1014  /*
1015  * Setup probes from command line or load config file.
1016  */
1017  sprobes = g_hash_table_new(g_direct_hash,g_direct_equal);
1018  fprobes = g_hash_table_new(g_direct_hash,g_direct_equal);
1019 
1020  if (opts.use_os_syscall_probes) {
1021  v_g_list_foreach(targets,t1,target) {
1022  if (target->personality != TARGET_PERSONALITY_OS)
1023  continue;
1024 
1025  if (target_os_syscall_table_load(target))
1026  vwarn("could not load the syscall table for target %s;"
1027  " target_os_syscall probes will not be available!\n",
1028  target->name);
1029  }
1030  }
1031 
1032  if (opts.argc > 0) {
1033  for (i = 0; i < opts.argc; ++i) {
1034  pre_filter = post_filter = context = NULL;
1035  name = str = opts.argv[i];
1036  while (*str != '\0') {
1037  if (*str == ':' && *(str+1) == ':') {
1038  *str = '\0';
1039  str += 2;
1040  break;
1041  }
1042  ++str;
1043  }
1044  if (*str != '\0') {
1045  if (*str == ':')
1046  pre_filter = NULL;
1047  else
1048  pre_filter = str;
1049  }
1050  while (*str != '\0') {
1051  if (*str == ':' && *(str+1) == ':') {
1052  *str = '\0';
1053  str += 2;
1054  break;
1055  }
1056  ++str;
1057  }
1058  if (*str != '\0') {
1059  if (*str == ':')
1060  post_filter = NULL;
1061  else
1062  post_filter = str;
1063  }
1064  while (*str != '\0') {
1065  if (*str == ':' && *(str+1) == ':') {
1066  *str = '\0';
1067  str += 2;
1068  break;
1069  }
1070  ++str;
1071  }
1072  if (*str != '\0')
1073  context = str;
1074 
1075  sprobe = (struct probe *)g_hash_table_lookup(sprobes,name);
1076  if (!sprobe) {
1077  /*
1078  * Create a probe on that symbol:
1079  */
1080 
1081  bsymbol = NULL;
1082  v_g_list_foreach(targets,t1,target) {
1083  if (opts.use_os_syscall_probes
1084  && target->personality == TARGET_PERSONALITY_OS)
1085  syscall = target_os_syscall_lookup_name(target,name);
1086  else
1087  syscall = NULL;
1088  if (syscall) {
1089  sprobe = \
1090  target_os_syscall_probe(target,TID_GLOBAL,syscall,
1093  NULL);
1094  if (!sprobe) {
1095  verror("could not place syscall value probe on %s;"
1096  " aborting!\n",name);
1097  rc = -5;
1098  goto exit;
1099  }
1100  else
1101  break;
1102  }
1103  else {
1104  bsymbol = target_lookup_sym(target,name,NULL,NULL,
1106  if (!bsymbol)
1107  continue;
1108 
1109  sprobe =
1111  TID_GLOBAL,bsymbol,
1114  NULL);
1115  if (!sprobe) {
1116  verror("could not place value probe on %s;"
1117  " aborting!\n",name);
1118  rc = -3;
1119  goto exit;
1120  }
1121  else
1122  break;
1123  }
1124  }
1125 
1126  if (!sprobe) {
1127  verror("could not probe symbol %s; aborting!\n",name);
1128  rc = -3;
1129  goto exit;
1130  }
1131  else
1132  g_hash_table_insert(sprobes,name,sprobe);
1133  }
1134 
1135  /* Create either an empty filter probe or parse the filter! */
1136  if (pre_filter) {
1137  pre_pf = target_nv_filter_parse(pre_filter);
1138  if (!pre_pf) {
1139  verror("could not parse pre_filter '%s'!\n",pre_filter);
1140  rc = -4;
1141  goto exit;
1142  }
1143  }
1144  else
1145  pre_pf = NULL;
1146  if (post_filter) {
1147  post_pf = target_nv_filter_parse(post_filter);
1148  if (!post_pf) {
1149  verror("could not parse post_filter '%s'!\n",post_filter);
1150  rc = -4;
1151  goto exit;
1152  }
1153  }
1154  else
1155  post_pf = NULL;
1156 
1157  snprintf(namebuf,sizeof(namebuf),"filter_%s_%d",name,i);
1158  fprobe = probe_create_filtered(sprobe->target,TID_GLOBAL,NULL,namebuf,
1159  pre_handler,pre_pf,
1160  post_handler,post_pf,NULL,NULL,0,1);
1161 
1162  probe_register_source(fprobe,sprobe);
1163 
1164  g_hash_table_insert(fprobes,namebuf,fprobe);
1165  }
1166  }
1167  else if (!opts.config_file) {
1168  /* Try the default config file. */
1169  if (access("spf.conf",R_OK)) {
1170  verror("Must supply some symbols to probe!\n");
1171  rc = -5;
1172  goto exit;
1173  }
1174  else {
1175  opts.config_file = strdup("spf.conf");
1176 
1177  config = load_config_file(opts.config_file);
1178  if (!config) {
1179  verror("could not read default config file %s!\n",
1180  opts.config_file);
1181  rc = -11;
1182  goto exit;
1183  }
1184  }
1185  }
1186 
1187  /* Now apply the config file. Always make the first application fatal. */
1188  int oldfatal = opts.config_file_fatal;
1189  opts.config_file_fatal = 1;
1190  if (apply_config_file(config)) {
1191  verror("could not install config file %s!\n",opts.config_file);
1192  rc = -12;
1193  goto exit;
1194  }
1195  opts.config_file_fatal = oldfatal;
1196 
1197  if (g_hash_table_size(sprobes) == 0) {
1198  verror("No symbols to probe; exiting!\n");
1199  rc = -1;
1200  goto exit;
1201  }
1202 
1203  /*
1204  * The targets were paused after instantiation; we have to resume them
1205  * now that we've registered probes.
1206  */
1207  v_g_list_foreach(targets,t1,target) {
1208  target_resume(target);
1209  }
1210 
1211  fprintf(stdout,"Starting Symbol Probe Filtering!\n");
1212  fflush(stdout);
1213 
1214  fprintf(stdout,"Starting thread watch loop!\n");
1215  fflush(stdout);
1216 
1217  while (1) {
1218  tid_t tid = 0;
1219  struct target *t;
1220  target_status_t tstat;
1221  char *tname;
1222  siginfo_t siginfo;
1223 
1224  rc = target_monitor_evloop(evloop,NULL,&t,&tstat);
1225 
1226  /*
1227  * Did we get interrupted safely? We need to check if we were
1228  * told to either die, or if we need to reload the config file.
1229  */
1230  if (target_monitor_was_interrupted(&siginfo)) {
1231  if (needtodie) {
1232  rc = 0;
1233  goto exit;
1234  }
1235  else if (siginfo.si_signo == SIGUSR1
1236  || siginfo.si_signo == SIGUSR2
1237  || siginfo.si_signo == SIGHUP) {
1239  }
1240 
1242 
1243  v_g_list_foreach(targets,t1,target) {
1244  target_resume(target);
1245  }
1246  }
1247  /* Did we experience an error in select() or in evloop? */
1248  else if (rc < 0) {
1249  fprintf(stderr,"error in target_monitor_evloop (%d): %s; aborting!\n",
1250  rc,strerror(errno));
1251  rc = -3;
1252  goto exit;
1253  }
1254  /* Did we experience a significant event on a target? */
1255  else if (rc == 0 && evloop_maxsize(evloop) < 0) {
1256  break;
1257  }
1258  else if (rc == 0) {
1259  tid = target_gettid(t);
1260  tname = target_name(t);
1261 
1262  if (tstat == TSTATUS_ERROR) {
1263  fprintf(stderr,
1264  "Error handling target '%s'; closing and finalizing!\n",
1265  tname);
1266 
1267  target_close(t);
1268  target_finalize(t);
1269  targets = g_list_remove(targets,t);
1270  }
1271  else if (tstat == TSTATUS_DONE) {
1272  fprintf(stderr,
1273  "Target '%s' finished; finalizing!\n",
1274  tname);
1275 
1276  target_close(t);
1277  target_finalize(t);
1278  targets = g_list_remove(targets,t);
1279  }
1280  else if (tstat == TSTATUS_EXITING) {
1281  fprintf(stderr,"Target '%s' exiting...\n",tname);
1282  }
1283  else if (tstat == TSTATUS_INTERRUPTED) {
1284  fprintf(stderr,"Target '%s' interrupted, resuming...\n",tname);
1285  if (target_resume(t)) {
1286  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
1287  tname,tid);
1288 
1289  target_close(t);
1290  target_finalize(t);
1291  targets = g_list_remove(targets,t);
1292  }
1293  }
1294  else {
1295  fprintf(stderr,
1296  "Target '%s' tid %d received unexpected status '%s'"
1297  " at 0x%"PRIxADDR"; attempting to continue!\n",
1298  tname,tid,TSTATUS(tstat),target_read_reg(t,tid,CREG_IP));
1299  if (target_resume(t)) {
1300  fprintf(stderr,"Could not resume target %s tid %"PRIiTID"\n",
1301  tname,tid);
1302 
1303  target_close(t);
1304  target_finalize(t);
1305  targets = g_list_remove(targets,t);
1306  }
1307  }
1308  }
1309  }
1310 
1311  rc = 0;
1312 
1313  exit:
1314  fflush(stderr);
1315  fflush(stdout);
1316  cleanup_probes();
1318  if (rc < 0)
1319  exit(rc);
1320  else
1321  exit(needtodie_exitcode);
1322 }
1323 
1324 void spf_action_free(struct spf_action *spfa) {
1325  if (spfa->atype == SPF_ACTION_REPORT) {
1326  if (spfa->report.tn)
1327  free(spfa->report.tn);
1328  if (spfa->report.rv)
1329  free(spfa->report.rv);
1330  if (spfa->report.msg)
1331  free(spfa->report.msg);
1332  }
1333  else if (spfa->atype == SPF_ACTION_ENABLE) {
1334  if (spfa->enable.id)
1335  free(spfa->enable.id);
1336  }
1337  else if (spfa->atype == SPF_ACTION_DISABLE) {
1338  if (spfa->disable.id)
1339  free(spfa->disable.id);
1340  }
1341  else if (spfa->atype == SPF_ACTION_REMOVE) {
1342  if (spfa->remove.id)
1343  free(spfa->remove.id);
1344  }
1345 
1346  free(spfa);
1347 }
1348 
1349 void spf_filter_free(struct spf_filter *spff) {
1350  GSList *gsltmp;
1351  struct spf_action *spfa;
1352 
1353  if (spff->id)
1354  free(spff->id);
1355  if (spff->symbol)
1356  free(spff->symbol);
1357  if (spff->bsymbol)
1358  bsymbol_release(spff->bsymbol);
1359  if (spff->pf)
1360  target_nv_filter_free(spff->pf);
1361  if (spff->actions) {
1362  v_g_slist_foreach(spff->actions,gsltmp,spfa) {
1363  spf_action_free(spfa);
1364  }
1365  g_slist_free(spff->actions);
1366  }
1367 
1368  free(spff);
1369 }
1370 
1371 void spf_config_free(struct spf_config *config) {
1372  GSList *gsltmp;
1373  struct spf_filter *spff;
1374 
1375  v_g_slist_foreach(config->spf_filter_list,gsltmp,spff) {
1376  spf_filter_free(spff);
1377  }
1378  g_slist_free(config->spf_filter_list);
1379 }
1380 
1381 /*
1382  * Language is like this. Single lines of probe filters/actions.
1383  *
1384  * [ see README.spf.txt ]
1385  *
1386  * Reports interpreted by the XML server like this:
1387  *
1388  * "RESULT:: (%c:%d) %ms (%d) %ms \"%m[^\"]\" (%m[^)]) ::RESULT\n",
1389  * &rt,&id,&name,&type,&result_value,&msg,&value_str);
1390  *
1391  * rt=(i|f) id=<unique_int> typename typeid result_value "msg" (<meta_kv_pairs>)
1392  *
1393  * We often use result_value as a msg subtype field within typename/typeid.
1394  */
1395 
1396 char *_get_next_non_enc_esc(char *s,int c) {
1397  int wasesc = 0;
1398  int isesc = 0;
1399  int isenc = 0;
1400  int encchar;
1401 
1402  while (*s != '\0') {
1403  wasesc = isesc;
1404  isesc = 0;
1405  if (isenc) {
1406  if (*s == '\\') {
1407  if (!wasesc)
1408  isesc = 1;
1409  }
1410  else if (*s == encchar && !wasesc) {
1411  encchar = '\0';
1412  isenc = 0;
1413  }
1414  }
1415  else if (*s == c) {
1416  if (!wasesc)
1417  break;
1418  }
1419  else if (*s == '\\') {
1420  if (!wasesc)
1421  isesc = 1;
1422  }
1423 
1424  ++s;
1425  }
1426 
1427  if (*s == c)
1428  return s;
1429  else
1430  return NULL;
1431 }
1432 
1434  struct spf_config *newconfig;
1435 
1436  newconfig = load_config_file(opts.config_file);
1437  if (!newconfig) {
1438  if (opts.config_file_fatal) {
1439  verror("could not reread config file %s!\n",opts.config_file);
1440  cleanup_probes();
1442  exit(-1);
1443  }
1444  else {
1445  vwarn("could not reread config file %s; leaving"
1446  " existing configuration in place!\n",opts.config_file);
1447  }
1448  }
1449  else {
1450  apply_config_file(newconfig);
1451  //spf_config_free(config);
1452  config = newconfig;
1453  newconfig = NULL;
1454  }
1455 }
1456 
1457 /*
1458  * Applies the config file.
1459  *
1460  * The easiest thing to do is remove all the filter probes; then see
1461  * which symbol probes we need to add/remove; then re-add all the
1462  * filter probes.
1463  *
1464  * What happens if we get called while one of our filter probes is
1465  * running its handler (or the list the probe is on is getting
1466  * iterated)?
1467  *
1468  * Sigh... we're going to have to add this aren't we. probe_free() will
1469  * have to schedule a free if the probe is in use...
1470  */
1471 int apply_config_file(struct spf_config *config) {
1472  GSList *gsltmp;
1473  struct spf_filter *spff;
1474  struct bsymbol *bsymbol = NULL;
1475  GHashTable *needed = NULL;
1476  GHashTableIter iter;
1477  gpointer kp,vp;
1478  struct probe *probe,*sprobe,*fprobe;
1479  char namebuf[128];
1480  int i;
1481  struct target_os_syscall *syscall;
1482  GList *t1;
1483  struct target *target;
1484 
1485  /* First, destroy all the filter probes. */
1486  g_hash_table_iter_init(&iter,fprobes);
1487  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
1488  probe = (struct probe *)vp;
1489  probe_free(probe,0);
1490  g_hash_table_iter_remove(&iter);
1491  }
1492 
1493  /* Second, build symbol probes for all the probes in the config. */
1494  needed = g_hash_table_new(g_str_hash,g_str_equal);
1495  v_g_slist_foreach(config->spf_filter_list,gsltmp,spff) {
1496  g_hash_table_insert(needed,spff->symbol,NULL);
1497 
1498  if (g_hash_table_lookup(sprobes,spff->symbol))
1499  continue;
1500 
1501  /* Create it. */
1502  bsymbol = NULL;
1503  v_g_list_foreach(targets,t1,target) {
1504  bsymbol = target_lookup_sym(target,spff->symbol,NULL,spff->srcfile,
1506  if (bsymbol)
1507  break;
1508  }
1509 
1510  if (!bsymbol)
1511  bsymbol = target_lookup_sym(target,spff->symbol,NULL,spff->srcfile,
1513 
1514  if (!bsymbol) {
1515  if (opts.config_file_fatal) {
1516  verror("could not lookup symbol %s; aborting!\n",
1517  spff->symbol);
1518  cleanup_probes();
1520  exit(-3);
1521  }
1522  else {
1523  vwarn("could not lookup symbol %s; skipping filter!\n",
1524  spff->symbol);
1525  continue;
1526  }
1527  }
1528 
1529  sprobe = NULL;
1530  if (opts.use_os_syscall_probes) {
1531  v_g_list_foreach(targets,t1,target) {
1532  if (target->personality != TARGET_PERSONALITY_OS)
1533  continue;
1534 
1535  syscall = target_os_syscall_lookup_name(target,spff->symbol);
1536  if (syscall) {
1537  sprobe = target_os_syscall_probe(target,TID_GLOBAL,syscall,
1540  NULL);
1541  if (!sprobe) {
1542  if (opts.config_file_fatal) {
1543  verror("could not place syscall value probe on %s;"
1544  " aborting!\n",
1545  spff->symbol);
1546  cleanup_probes();
1548  exit(-3);
1549  }
1550  else {
1551  vwarn("could not place syscall value probe on %s;"
1552  " skipping filter!\n",
1553  spff->symbol);
1554  continue;
1555  }
1556  }
1557  }
1558  }
1559  }
1560 
1561  if (!sprobe) {
1562  sprobe = probe_value_symbol(bsymbol->region->space->target,
1563  TID_GLOBAL,bsymbol,
1566  if (!sprobe) {
1567  if (opts.config_file_fatal) {
1568  verror("could not place value probe on %s; aborting!\n",
1569  spff->symbol);
1570  cleanup_probes();
1572  exit(-3);
1573  }
1574  else {
1575  vwarn("could not place value probe on %s; skipping filter!\n",
1576  spff->symbol);
1577  continue;
1578  }
1579  }
1580  }
1581 
1582  g_hash_table_insert(sprobes,spff->symbol,sprobe);
1583  }
1584 
1585  /* Third, any sprobe that is *NOT* in needed should be removed. */
1586  g_hash_table_iter_init(&iter,sprobes);
1587  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
1588  if (g_hash_table_lookup_extended(needed,kp,NULL,NULL) == FALSE) {
1589  probe_free((struct probe *)vp,0);
1590  g_hash_table_iter_remove(&iter);
1591  }
1592  }
1593  g_hash_table_destroy(needed);
1594  needed = NULL;
1595 
1596  /* Finally, add all the filter probes. */
1597  v_g_slist_foreach(config->spf_filter_list,gsltmp,spff) {
1598  /* Again, if we failed for any reason to get the symbol, skip here. */
1599  sprobe = (struct probe *)g_hash_table_lookup(sprobes,spff->symbol);
1600  if (!sprobe)
1601  continue;
1602  if (!spff->id) {
1603  snprintf(namebuf,sizeof(namebuf),"filter_%s_%d",spff->symbol,i);
1604  spff->id = strdup(namebuf);
1605  }
1606  if (spff->when == WHEN_PRE)
1607  fprobe = probe_create_filtered(sprobe->target,TID_GLOBAL,NULL,spff->id,
1608  pre_handler,spff->pf,null_handler,NULL,
1609  spff->ttf,spff,0,1);
1610  else
1611  fprobe = probe_create_filtered(sprobe->target,TID_GLOBAL,NULL,spff->id,
1612  null_handler,NULL,post_handler,spff->pf,
1613  spff->ttf,spff,0,1);
1614  probe_register_source(fprobe,sprobe);
1615 
1616  if (spff->disable)
1617  probe_disable(fprobe);
1618 
1619  g_hash_table_insert(fprobes,spff->id,fprobe);
1620  }
1621 
1622  return 0;
1623 }
1624 
1625 /*
1626  * (Re)reads the configuration file.
1627  */
1628 struct spf_config *load_config_file(char *file) {
1629  char *buf;
1630  char *bufptr;
1631  char *tbuf;
1632  int bufsiz = 128;
1633  int rc = 0;
1634  FILE *ffile;
1635  struct spf_filter *spff = NULL;
1636  struct spf_action *spfa = NULL;
1637  char *saveptr;
1638  char *token = NULL, *token2 = NULL;
1639  char *tptr;
1640  long int numval;
1641  struct spf_config *retval = NULL;
1642  int spff_count = 0;
1643  int lineno = 0;
1644  char *tmp;
1645 
1646  if (strcmp(file,"-") == 0)
1647  ffile = stdin;
1648  else {
1649  ffile = fopen(file,"r");
1650  if (!ffile) {
1651  verror("could not fopen config file %s: %s\n",file,strerror(errno));
1652  return NULL;
1653  }
1654  }
1655 
1656  retval = calloc(1,sizeof(*retval));
1657 
1658  /* Read directives line by line. */
1659  buf = malloc(bufsiz);
1660  while (1) {
1661  rc = 0;
1662  while (1) {
1663  errno = 0;
1664  tbuf = fgets(buf + rc,bufsiz - rc,ffile);
1665  if (tbuf && (rc += strlen(buf + rc)) == (bufsiz - 1)
1666  && buf[bufsiz - 2] != '\n') {
1667  /* We filled up the buf; malloc more and keep going. */
1668  tbuf = malloc(bufsiz + 128);
1669  memcpy(tbuf,buf,bufsiz);
1670  free(buf);
1671  buf = tbuf;
1672  bufsiz += 128;
1673  }
1674  else if (tbuf && rc < bufsiz) {
1675  /* We have our line. */
1676  break;
1677  }
1678  else if (errno) {
1679  verror("fgets: %s (aborting filter file read)\n",
1680  strerror(errno));
1681  goto errout;
1682  }
1683  else {
1684  /* EOF. */
1685  free(buf);
1686  buf = NULL;
1687  break;
1688  }
1689  }
1690 
1691  if (!buf)
1692  break;
1693 
1694  ++lineno;
1695  vdebug(2,LA_USER,LF_U_CFG,"read line %d: '%s'\n",lineno,buf);
1696 
1697  if (*buf == '#')
1698  continue;
1699 
1700  if (buf[strlen(buf) - 1] == '\n') {
1701  if (*buf == '\n')
1702  continue;
1703  buf[strlen(buf) - 1] = '\0';
1704  }
1705 
1706  /*
1707  * ProbeFilter.
1708  */
1709  if (strncmp(buf,"ProbeFilter",strlen("ProbeFilter")) == 0) {
1710  bufptr = buf + strlen("ProbeFilter");
1711  while (isspace(*bufptr)) ++bufptr;
1712 
1713  spff = (struct spf_filter *)calloc(1,sizeof(*spff));
1714  /* Default. */
1715  spff->when = WHEN_PRE;
1716 
1717  /*
1718  * Parse the line. We can't use strtok to split it up,
1719  * because there are strings and regexps, and we don't want
1720  * to place any restrictions on them. So we just manually
1721  * lex it... forgotten too much flex yystuff to do it fast.
1722  */
1723 
1724  /* symbol name */
1725  token = bufptr;
1726  while (!isspace(*bufptr)) ++bufptr;
1727  *bufptr = '\0';
1728  spff->symbol = strdup(token);
1729  if ((tmp = index(spff->symbol,':'))) {
1730  spff->srcfile = spff->symbol;
1731  *tmp = '\0';
1732  spff->symbol = strdup(tmp+1);
1733  }
1734  ++bufptr;
1735 
1736  /* These are all optional; take them in any order. */
1737  while (*bufptr != '\0') {
1738  while (isspace(*bufptr)) ++bufptr;
1739  if (*bufptr == '\0')
1740  goto err;
1741 
1742  token = bufptr;
1743  while (isalnum(*bufptr) || *bufptr == '_') ++bufptr;
1744  if (*bufptr == '(') {
1745  *bufptr = '\0';
1746  ++bufptr;
1747  }
1748  else {
1749  *bufptr = '\0';
1750  ++bufptr;
1751  while (isspace(*bufptr)) ++bufptr;
1752  if (*bufptr != '(')
1753  goto err;
1754  ++bufptr;
1755  }
1756 
1757  if (strcmp(token,"id") == 0) {
1758  token = bufptr;
1759  while (isalnum(*bufptr) || *bufptr == '_') ++bufptr;
1760  if (*bufptr != ')')
1761  goto err;
1762  *bufptr = '\0';
1763  ++bufptr;
1764  if (spff->id)
1765  goto err;
1766  else
1767  spff->id = strdup(token);
1768  }
1769  else if (strcmp(token,"when") == 0) {
1770  if (strncmp(bufptr,"pre",strlen("pre")) == 0) {
1771  spff->when = WHEN_PRE;
1772  bufptr += strlen("pre");
1773  }
1774  else if (strncmp(bufptr,"post",strlen("post")) == 0) {
1775  spff->when = WHEN_POST;
1776  bufptr += strlen("post");
1777  }
1778  else
1779  goto err;
1780  if (*bufptr != ')')
1781  goto err;
1782  ++bufptr;
1783  }
1784  else if (strcmp(token,"disable") == 0) {
1785  if (*bufptr != ')')
1786  goto err;
1787  ++bufptr;
1788 
1789  spff->disable = 1;
1790  }
1791  else if (strcmp(token,"vfilter") == 0) {
1792  if (spff->pf)
1793  goto err;
1794  token = bufptr;
1795  /* Find the enclosing ')' */
1796  int isescaped = 0;
1797  char *nextbufptr = NULL;
1798  while (*bufptr != '\0') {
1799  if (*bufptr == '\\') {
1800  if (!isescaped)
1801  isescaped = 1;
1802  else
1803  isescaped = 0;
1804  }
1805  else if (*bufptr == ')' && !isescaped) {
1806  nextbufptr = bufptr + 1;
1807  *bufptr = '\0';
1808  break;
1809  }
1810  ++bufptr;
1811  }
1812  if (!nextbufptr)
1813  goto err;
1814  spff->pf = target_nv_filter_parse(token);
1815  if (!spff->pf)
1816  goto err;
1817  bufptr = nextbufptr;
1818  }
1819  else if (strcmp(token,"tfilter") == 0) {
1820  if (spff->ttf)
1821  goto err;
1822  token = bufptr;
1823  /* Find the enclosing ')' */
1824  int isescaped = 0;
1825  char *nextbufptr = NULL;
1826  while (*bufptr != '\0') {
1827  if (*bufptr == '\\') {
1828  if (!isescaped)
1829  isescaped = 1;
1830  else
1831  isescaped = 0;
1832  }
1833  else if (*bufptr == ')' && !isescaped) {
1834  nextbufptr = bufptr + 1;
1835  *bufptr = '\0';
1836  break;
1837  }
1838  ++bufptr;
1839  }
1840  if (!nextbufptr)
1841  goto err;
1842  spff->ttf = target_nv_filter_parse(token);
1843  if (!spff->ttf)
1844  goto err;
1845  bufptr = nextbufptr;
1846  }
1847  else if (strcmp(token,"abort") == 0) {
1848  token = bufptr;
1849  while (*bufptr == '-' || isdigit(*bufptr)) ++bufptr;
1850  if (*bufptr != ')')
1851  goto err;
1852  *bufptr = '\0';
1853  ++bufptr;
1854  errno = 0;
1855  numval = strtol(token,NULL,0);
1856  if (errno)
1857  goto err;
1858 
1859  spfa = calloc(1,sizeof(*spfa));
1860  spfa->atype = SPF_ACTION_ABORT;
1861  spfa->abort.retval = numval;
1862 
1863  spff->actions = g_slist_append(spff->actions,spfa);
1864  spfa = NULL;
1865  }
1866  else if (strcmp(token,"print") == 0) {
1867  spfa = calloc(1,sizeof(*spfa));
1868  spfa->atype = SPF_ACTION_PRINT;
1869 
1870  if (*bufptr == ')') {
1871  ++bufptr;
1872  }
1873  else {
1874  /*
1875  * XXX: use strtok here ignore the possibility that
1876  * the msg field has a comma in it. Time is not on
1877  * my side...
1878  */
1879  char *nextbufptr = NULL;
1880  nextbufptr = _get_next_non_enc_esc(bufptr,')');
1881  if (!nextbufptr)
1882  goto err;
1883  *nextbufptr = '\0';
1884  ++nextbufptr;
1885  token = NULL;
1886  token2 = NULL;
1887  saveptr = NULL;
1888  while ((token = strtok_r((!token) ? bufptr : NULL,",",
1889  &saveptr))) {
1890  tptr = token;
1891  while (*tptr != '\0') {
1892  if (*tptr == '=') {
1893  *tptr = '\0';
1894  token2 = ++tptr;
1895  break;
1896  }
1897  ++tptr;
1898  }
1899  if (!token2)
1900  goto err;
1901 
1902  if (strcmp(token,"ttctx") == 0) {
1903  if (strcmp(token2,"none") == 0)
1904  spfa->print.ttctx = 0;
1905  else if (strcmp(token2,"self") == 0)
1906  spfa->print.ttctx = 1;
1907  else if (strcmp(token2,"hier") == 0)
1908  spfa->print.ttctx = 2;
1909  else if (strcmp(token2,"all") == 0)
1910  spfa->print.ttctx = 3;
1911  else
1912  goto err;
1913  }
1914  else if (strcmp(token,"ttdetail") == 0) {
1915  spfa->print.ttdetail = atoi(token2);
1916  }
1917  else
1918  goto err;
1919  }
1920  bufptr = nextbufptr;
1921  }
1922 
1923  spff->actions = g_slist_append(spff->actions,spfa);
1924  spfa = NULL;
1925  }
1926  else if (strcmp(token,"report") == 0) {
1927  spfa = calloc(1,sizeof(*spfa));
1928  spfa->atype = SPF_ACTION_REPORT;
1929 
1930  /* Set some defaults. */
1931  spfa->report.rt = 'i';
1932  spfa->report.overlay_levels = 0;
1933  spfa->report.overlay_debuginfo_prefix = NULL;
1934 
1935  /*
1936  * XXX: use strtok here ignore the possibility that
1937  * the msg field has a comma in it. Time is not on
1938  * my side...
1939  */
1940  char *nextbufptr = NULL;
1941  nextbufptr = _get_next_non_enc_esc(bufptr,')');
1942  if (!nextbufptr)
1943  goto err;
1944  *nextbufptr = '\0';
1945  ++nextbufptr;
1946  token = NULL;
1947  token2 = NULL;
1948  saveptr = NULL;
1949  while ((token = strtok_r((!token) ? bufptr : NULL,",",
1950  &saveptr))) {
1951  tptr = token;
1952  while (*tptr != '\0') {
1953  if (*tptr == '=') {
1954  *tptr = '\0';
1955  token2 = ++tptr;
1956  break;
1957  }
1958  ++tptr;
1959  }
1960  if (!token2)
1961  goto err;
1962 
1963  if (strcmp(token,"rt") == 0) {
1964  if (*token2 == 'f')
1965  spfa->report.rt = *token2;
1966  else if (*token2 == 'i')
1967  spfa->report.rt = *token2;
1968  else
1969  goto err;
1970  }
1971  else if (strcmp(token,"tn") == 0) {
1972  spfa->report.tn = strdup(token2);
1973  }
1974  else if (strcmp(token,"tid") == 0) {
1975  errno = 0;
1976  spfa->report.tid = strtol(token2,NULL,0);
1977  if (errno)
1978  goto err;
1979  }
1980  else if (strcmp(token,"rv") == 0) {
1981  spfa->report.rv = strdup(token2);
1982  }
1983  else if (strcmp(token,"msg") == 0) {
1984  if (*token2 != '"') {
1985  spfa->report.msg = malloc(2+1+strlen(token2));
1986  snprintf(spfa->report.msg,2+1+strlen(token2),
1987  "\"%s\"",token2);
1988  }
1989  else
1990  spfa->report.msg = strdup(token2);
1991  }
1992  else if (strcmp(token,"ttctx") == 0) {
1993  if (strcmp(token2,"none") == 0)
1994  spfa->report.ttctx = 0;
1995  else if (strcmp(token2,"self") == 0)
1996  spfa->report.ttctx = 1;
1997  else if (strcmp(token2,"hier") == 0)
1998  spfa->report.ttctx = 2;
1999  else if (strcmp(token2,"all") == 0)
2000  spfa->report.ttctx = 3;
2001  else
2002  goto err;
2003  }
2004  else if (strcmp(token,"ttdetail") == 0) {
2005  spfa->report.ttdetail = atoi(token2);
2006  }
2007  else if (strcmp(token,"bt") == 0) {
2008  spfa->report.bt = atoi(token2);
2009  }
2010  else if (strcmp(token,"overlay_levels") == 0) {
2011  spfa->report.overlay_levels = atoi(token2);
2012  }
2013  else if (strcmp(token,"overlay_debuginfo_root_prefix") == 0) {
2014  spfa->report.overlay_debuginfo_prefix =
2015  strdup(token2);
2016  }
2017  else
2018  goto err;
2019  }
2020  bufptr = nextbufptr;
2021 
2022  spff->actions = g_slist_append(spff->actions,spfa);
2023  spfa = NULL;
2024  }
2025  else if (strcmp(token,"exit") == 0) {
2026  token = bufptr;
2027  while (*bufptr == '-' || isdigit(*bufptr)) ++bufptr;
2028  if (*bufptr != ')')
2029  goto err;
2030  *bufptr = '\0';
2031  ++bufptr;
2032  errno = 0;
2033  numval = strtol(token,NULL,0);
2034  if (errno)
2035  goto err;
2036 
2037  spfa = calloc(1,sizeof(*spfa));
2038  spfa->atype = SPF_ACTION_EXIT;
2039  spfa->exit.retval = numval;
2040 
2041  spff->actions = g_slist_append(spff->actions,spfa);
2042  spfa = NULL;
2043  }
2044  else if (strcmp(token,"enable") == 0) {
2045  token = bufptr;
2046  while (isalnum(*bufptr) || *bufptr == '_') ++bufptr;
2047  if (*bufptr != ')')
2048  goto err;
2049  *bufptr = '\0';
2050  ++bufptr;
2051  spfa = calloc(1,sizeof(*spfa));
2052  spfa->atype = SPF_ACTION_ENABLE;
2053  spfa->enable.id = strdup(token);
2054 
2055  spff->actions = g_slist_append(spff->actions,spfa);
2056  spfa = NULL;
2057  }
2058  else if (strcmp(token,"disable") == 0) {
2059  token = bufptr;
2060  while (isalnum(*bufptr) || *bufptr == '_') ++bufptr;
2061  if (*bufptr != ')')
2062  goto err;
2063  *bufptr = '\0';
2064  ++bufptr;
2065  spfa = calloc(1,sizeof(*spfa));
2066  spfa->atype = SPF_ACTION_DISABLE;
2067  spfa->disable.id = strdup(token);
2068 
2069  spff->actions = g_slist_append(spff->actions,spfa);
2070  spfa = NULL;
2071  }
2072  else if (strcmp(token,"remove") == 0) {
2073  token = bufptr;
2074  while (isalnum(*bufptr) || *bufptr == '_') ++bufptr;
2075  if (*bufptr != ')')
2076  goto err;
2077  *bufptr = '\0';
2078  ++bufptr;
2079  spfa = calloc(1,sizeof(*spfa));
2080  spfa->atype = SPF_ACTION_REMOVE;
2081  spfa->remove.id = strdup(token);
2082 
2083  spff->actions = g_slist_append(spff->actions,spfa);
2084  spfa = NULL;
2085  }
2086  else if (strcmp(token,"bt") == 0) {
2087  spfa = calloc(1,sizeof(*spfa));
2088  spfa->atype = SPF_ACTION_BT;
2089 
2090  /* Set some defaults. */
2091  spfa->bt.tid = -1;
2092  spfa->bt.thid = NULL;
2093  spfa->bt.overlay_levels = 0;
2094  spfa->bt.overlay_debuginfo_prefix = NULL;
2095 
2096  char *nextbufptr = NULL;
2097  nextbufptr = _get_next_non_enc_esc(bufptr,')');
2098  if (!nextbufptr)
2099  goto err;
2100  *nextbufptr = '\0';
2101  ++nextbufptr;
2102  token = NULL;
2103  token2 = NULL;
2104  saveptr = NULL;
2105 
2106  int lpc = 0;
2107  while ((token = strtok_r((!token) ? bufptr : NULL,",",
2108  &saveptr))) {
2109  if (lpc == 0)
2110  spfa->bt.tid = atoi(token);
2111  else if (lpc == 1)
2112  spfa->bt.thid = strdup(token);
2113  else if (lpc == 2)
2114  spfa->bt.overlay_levels = atoi(token);
2115  else if (lpc == 3)
2116  spfa->bt.overlay_debuginfo_prefix = strdup(token);
2117  else
2118  goto err;
2119 
2120  ++lpc;
2121  }
2122  bufptr = nextbufptr;
2123 
2124  spff->actions = g_slist_append(spff->actions,spfa);
2125  spfa = NULL;
2126  }
2127  else if (strcmp(token,"signal") == 0) {
2128  spfa = calloc(1,sizeof(*spfa));
2129  spfa->atype = SPF_ACTION_SIGNAL;
2130 
2131  /* Set some defaults. */
2132  spfa->signal.tid = -1;
2133  spfa->signal.thid = NULL;
2134 
2135  char *nextbufptr = NULL;
2136  nextbufptr = _get_next_non_enc_esc(bufptr,')');
2137  if (!nextbufptr)
2138  goto err;
2139  *nextbufptr = '\0';
2140  ++nextbufptr;
2141  token = NULL;
2142  token2 = NULL;
2143  saveptr = NULL;
2144 
2145  int lpc = 0;
2146  while ((token = strtok_r((!token) ? bufptr : NULL,",",
2147  &saveptr))) {
2148  if (lpc == 0)
2149  spfa->signal.tid = atoi(token);
2150  else if (lpc == 1)
2151  spfa->signal.thid = strdup(token);
2152  else if (lpc == 2)
2153  spfa->signal.sigdesc = strdup(token);
2154  else
2155  goto err;
2156 
2157  ++lpc;
2158  }
2159  bufptr = nextbufptr;
2160 
2161  spff->actions = g_slist_append(spff->actions,spfa);
2162  spfa = NULL;
2163  }
2164  else
2165  goto err;
2166  }
2167 
2168  retval->spf_filter_list =
2169  g_slist_append(retval->spf_filter_list,spff);
2170  spff = NULL;
2171  ++spff_count;
2172  }
2173  else {
2174  /*
2175  * Invalid rule
2176  */
2177  fprintf(stderr,"ERROR: unknown config directive line %d:\n",lineno);
2178  fprintf(stderr,"%s\n", buf);
2179  goto errout;
2180  }
2181  }
2182 
2183  fclose(ffile);
2184 
2185  if (buf)
2186  free(buf);
2187 
2188  vdebug(2,LA_USER,LF_U_CFG,"configfile: %d probefilters.\n",spff_count);
2189 
2190  return retval;
2191 
2192  err:
2193  verror("parse error at line %d col %d: '%.48s ...'\n",
2194  lineno,(int)(bufptr - buf),bufptr);
2195 
2196  errout:
2197  fclose(ffile);
2198 
2199  if (spfa)
2200  spf_action_free(spfa);
2201  if (spff)
2202  spf_filter_free(spff);
2203  if (retval)
2204  spf_config_free(retval);
2205 
2206  if (buf)
2207  free(buf);
2208 
2209  return NULL;
2210 }
struct target * target_instantiate_overlay(struct target *target, tid_t tid, struct target_spec *spec)
Definition: target_api.c:724
int target_thread_snprintf(struct target *target, tid_t tid, char *buf, int bufsiz, int detail, char *sep, char *kvsep)
Definition: target_api.c:1360
struct action * action_return(REGVAL retval)
Definition: probe.c:4455
result_t pre_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:849
int bt
Definition: spf.c:72
void spf_backtrace(struct target *t, tid_t ctid, char *tiddesc, int overlay_levels, char *overlay_debuginfo_prefix)
Definition: spf.c:354
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
#define __TARGET_OVERLAY
Definition: spf.c:870
int probe_unregister(struct probe *probe, int force)
Definition: probe.c:1137
void reload_config_file(void)
Definition: spf.c:1433
void target_monitor_schedule_global_interrupt(void)
Definition: target.c:314
int argc
Definition: spf.c:143
char * id
Definition: spf.c:113
int value_snprintf(struct value *value, char *buf, int buflen)
Definition: value.c:581
int ttctx
Definition: spf.c:70
int use_os_syscall_probes
Definition: spf.c:147
char * rv
Definition: spf.c:68
int32_t tid_t
Definition: common.h:36
target_personality_t personality
Definition: target_api.h:2477
void * target_argp_driver_state(struct argp_state *state)
Definition: target.c:703
struct target_nv_filter * ttf
Definition: spf.c:128
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:5424
struct spf_config * load_config_file(char *file)
Definition: spf.c:1628
Definition: probe.h:392
char * name
Definition: probe.h:314
result_t handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: probetargets.c:59
sigset_t interrupt
Definition: spf.c:211
struct bsymbol * target_lookup_sym(struct target *target, const char *name, const char *delim, char *srcfile, symbol_type_flag_t ftype)
Definition: target.c:2169
int target_monitor_evloop(struct evloop *evloop, struct timeval *timeout, struct target **target, target_status_t *status)
Definition: target_api.c:841
void print_thread_context(FILE *stream, struct target *target, tid_t tid, int ttctx, int ttdetail, int bt, char *sep, char *kvsep, char *tprefix, char *tsep)
void target_init(void)
Definition: target.c:67
Definition: arch.h:74
GList * targets
Definition: backtrace.c:47
REFCNT action_release(struct action *action)
Definition: probe.c:4574
#define v_g_slist_foreach(gslhead, gslcur, elm)
Definition: glib_wrapper.h:60
int target_resume(struct target *target)
Definition: target_api.c:973
struct overlay_spec ** ospecs
Definition: spf.c:149
struct bsymbol * bsymbol
Definition: spf.c:117
#define v_g_list_foreach(glhead, glcur, elm)
Definition: glib_wrapper.h:34
result_t null_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:864
char * msg
Definition: spf.c:69
int target_pause(struct target *target)
Definition: target_api.c:988
char * thid
Definition: spf.c:97
#define PROBE_VALUE_NAME_RETURN
Definition: probe_api.h:159
tid_t target_gettid(struct target *target)
Definition: target_api.c:1853
struct argp_option spf_argp_opts[]
Definition: spf.c:874
struct probe * probe_create_filtered(struct target *target, tid_t tid, struct probe_ops *pops, const char *name, probe_handler_t pre_handler, struct target_nv_filter *pre_filter, probe_handler_t post_handler, struct target_nv_filter *post_filter, struct target_nv_filter *thread_filter, void *handler_data, int autofree, int tracked)
Definition: probe_filter.c:95
GHashTable * probe_value_get_table(struct probe *probe, tid_t tid)
Definition: probe_value.c:618
struct target * target
Definition: target.h:884
result_t probe_do_sink_post_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe.c:109
GHashTable * fprobes
Definition: spf.c:160
struct spf_action::@30::@38 remove
struct target_os_syscall * target_os_syscall_lookup_name(struct target *target, char *name)
Definition: target_os.c:437
int config_file_fatal
Definition: spf.c:146
int target_close(struct target *target)
Definition: target_api.c:1446
struct spf_action::@30::@32 report
struct list_head probe
Definition: probe.h:379
#define verror(format,...)
Definition: log.h:30
result_t probe_do_sink_pre_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe.c:48
GHashTable * sprobes
Definition: spf.c:159
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:263
int tid
Definition: spf.c:67
GSList * actions
Definition: spf.c:129
char * _get_next_non_enc_esc(char *s, int c)
Definition: spf.c:1396
Definition: evloop.h:66
void target_fini(void)
Definition: target.c:84
char * config_file
Definition: spf.c:145
#define LF_U_CFG
Definition: spf.c:42
struct spf_action::@30::@33 print
#define vwarn(format,...)
Definition: log.h:33
#define LF_U_PROBE
Definition: spf.c:43
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1083
void spf_filter_free(struct spf_filter *spff)
Definition: spf.c:1349
struct spf_action::@30::@36 enable
tid_t tid
Definition: probe.h:344
struct probe * probe_register_source(struct probe *sink, struct probe *src)
Definition: probe.c:1593
error_t spf_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: spf.c:884
struct target_nv_filter * pf
Definition: spf.c:124
#define array_list_foreach(alist, lpc, placeholder)
Definition: alist.h:371
void target_monitor_clear_global_interrupt(void)
Definition: target.c:228
void spf_config_free(struct spf_config *config)
Definition: spf.c:1371
void target_default_cleanup()
Definition: target.c:121
struct spf_action::@30::@35 exit
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:900
int target_monitor_was_interrupted(siginfo_t *last_siginfo)
Definition: target.c:219
struct array_list * target_list_tids(struct target *target)
Definition: target_api.c:1145
int target_os_syscall_table_load(struct target *target)
Definition: target_os.c:415
int result_counter
Definition: spf.c:165
struct probe * target_os_syscall_probe(struct target *target, tid_t tid, struct target_os_syscall *syscall, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data)
Definition: target_os.c:465
#define WHEN_POST
Definition: spf.c:110
int probe_free(struct probe *probe, int force)
Definition: probe.c:777
struct addrspace * space
Definition: target.h:926
int ospecs_len
Definition: spf.c:148
struct dt_argp_state opts
Definition: dumptarget.c:111
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
int main(int argc, char **argv)
Definition: dumpdebuginfo.c:41
struct target_spec * target_build_default_overlay_spec(struct target *target, tid_t tid)
Definition: target_api.c:711
char * target_name(struct target *target)
Definition: target_api.c:488
char * base_target_id
Definition: dumptarget.c:72
char * srcfile
Definition: spf.c:115
char rt
Definition: spf.c:65
int needtodie
Definition: spf.c:162
struct spf_action::@30::@37 disable
char ** argv
Definition: dumptarget.c:86
int probe_enable(struct probe *probe)
Definition: probe.c:1861
#define SPF_CONFIGFILE_FATAL
Definition: spf.c:871
Definition: probe.h:308
Definition: spf.c:60
struct spf_action::@30::@34 abort
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
int when
Definition: spf.c:119
#define SPF_OS_SYSCALL_PROBES
Definition: spf.c:872
int needtodie_exitcode
Definition: spf.c:163
uint8_t disable
Definition: spf.c:120
int apply_config_file(struct spf_config *config)
Definition: spf.c:1471
spf_action_type_t atype
Definition: spf.c:61
struct array_list * target_list_available_tids(struct target *target)
Definition: target_api.c:1207
int evloop_maxsize(struct evloop *evloop)
Definition: evloop.c:191
char * sigdesc
Definition: spf.c:104
struct target_nv_filter * target_nv_filter_parse(char *expr)
long int retval
Definition: spf.c:81
result_t post_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:854
int target_os_signal_from_name(struct target *target, const char *name)
Definition: target_os.c:411
char * id
Definition: spf.c:87
int probe_disable(struct probe *probe)
Definition: probe.c:1811
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:325
char * tn
Definition: spf.c:66
#define PRIiTID
Definition: common.h:37
int overlay_levels
Definition: spf.c:73
sigset_t ignored
Definition: spf.c:211
Definition: log.h:76
int target_finalize(struct target *target)
Definition: target.c:1925
struct symbol * bsymbol_get_symbol(struct bsymbol *bsymbol)
Definition: symbol.c:66
struct target * target
Definition: probe.h:342
void target_nv_filter_free(struct target_nv_filter *pf)
#define vwarnc(format,...)
Definition: log.h:35
spf_action_type_t
Definition: spf.c:48
char * base_thread_name_or_id
Definition: dumptarget.c:73
char * name
Definition: target_api.h:2483
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
int target_open(struct target *target)
Definition: target_api.c:496
#define WHEN_PRE
Definition: spf.c:109
sigset_t exitset
Definition: spf.c:211
#define PRIxADDR
Definition: common.h:67
void sigh_cleanup_probes(int signo, siginfo_t *siginfo, void *x)
Definition: cfi_check.c:59
struct argp spf_argp
Definition: spf.c:930
struct bsymbol * bsymbol
Definition: probe.h:389
int spf_signal(struct target *t, tid_t ctid, char *tiddesc, char *sigdesc)
Definition: spf.c:482
char * overlay_debuginfo_prefix
Definition: spf.c:74
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
GSList * spf_filter_list
Definition: spf.c:133
char * debugfile_root_prefix
Definition: target_api.h:2197
struct target_thread * target_lookup_thread(struct target *target, tid_t tid)
Definition: target.c:3981
char ** argv
Definition: spf.c:144
#define array_list_foreach_fakeptr_t(alist, lpc, placeholder, intertype)
Definition: alist.h:381
struct spf_action::@30::@40 signal
char * probe_name(struct probe *probe)
Definition: probe.c:1935
void spf_action_free(struct spf_action *spfa)
Definition: spf.c:1324
int target_os_signal_enqueue(struct target *target, tid_t tid, int signo, void *data)
Definition: target_os.c:399
char * symbol
Definition: spf.c:116
struct target_spec * spec
Definition: dumptarget.c:74
int action_sched(struct probe *probe, struct action *action, action_whence_t whence, action_handler_t handler, void *handler_data)
Definition: probe.c:4117
void cleanup_probes()
Definition: dumptarget.c:115
struct probe * probe
Definition: probe.h:450
#define TID_GLOBAL
Definition: target_api.h:145
int ttdetail
Definition: spf.c:71
struct memregion * region
Definition: target.h:1009
void target_driver_argp_init_children(struct argp_state *state)
Definition: target.c:1044
struct spf_config * config
Definition: spf.c:156
struct target * t
Definition: dumptarget.c:48