summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-05-07 16:17:11 -0700
committerJosh Stone <jistone@redhat.com>2009-05-07 16:17:11 -0700
commit93646f4d5ccaa051cd996cc2ab6a2b4a21418714 (patch)
tree38a0ed4ae4871ec2574778dd812b5e388d548185
parentdd0e4fa70fd7589ff80618305bd3d24e98a5d73b (diff)
downloadsystemtap-steved-93646f4d5ccaa051cd996cc2ab6a2b4a21418714.tar.gz
systemtap-steved-93646f4d5ccaa051cd996cc2ab6a2b4a21418714.tar.xz
systemtap-steved-93646f4d5ccaa051cd996cc2ab6a2b4a21418714.zip
Separate task_finder and the itrace tapset
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in34
-rw-r--r--tapset-itrace.cxx337
-rw-r--r--tapsets.cxx389
-rw-r--r--tapsets.h3
-rw-r--r--task_finder.cxx103
-rw-r--r--task_finder.h20
7 files changed, 501 insertions, 388 deletions
diff --git a/Makefile.am b/Makefile.am
index e65d1535..4b2d724d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,8 @@ stap_SOURCES = main.cxx \
tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \
cache.cxx util.cxx coveragedb.cxx dwarf_wrappers.cxx \
tapset-been.cxx tapset-procfs.cxx tapset-timers.cxx \
- tapset-perfmon.cxx tapset-mark.cxx
+ tapset-perfmon.cxx tapset-mark.cxx tapset-itrace.cxx \
+ task_finder.cxx
stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@
BUILT_SOURCES =
diff --git a/Makefile.in b/Makefile.in
index 0e0aee9a..baaed3dd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -124,6 +124,7 @@ am_stap_OBJECTS = stap-main.$(OBJEXT) stap-parse.$(OBJEXT) \
stap-dwarf_wrappers.$(OBJEXT) stap-tapset-been.$(OBJEXT) \
stap-tapset-procfs.$(OBJEXT) stap-tapset-timers.$(OBJEXT) \
stap-tapset-perfmon.$(OBJEXT) stap-tapset-mark.$(OBJEXT) \
+ stap-tapset-itrace.$(OBJEXT) stap-task_finder.$(OBJEXT) \
$(am__objects_1)
stap_OBJECTS = $(am_stap_OBJECTS)
stap_LINK = $(CXXLD) $(stap_CXXFLAGS) $(CXXFLAGS) $(stap_LDFLAGS) \
@@ -331,7 +332,8 @@ stap_SOURCES = main.cxx parse.cxx staptree.cxx elaborate.cxx \
translate.cxx tapsets.cxx buildrun.cxx loc2c.c hash.cxx \
mdfour.c cache.cxx util.cxx coveragedb.cxx dwarf_wrappers.cxx \
tapset-been.cxx tapset-procfs.cxx tapset-timers.cxx \
- tapset-perfmon.cxx tapset-mark.cxx $(am__append_4)
+ tapset-perfmon.cxx tapset-mark.cxx tapset-itrace.cxx \
+ task_finder.cxx $(am__append_4)
stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@ $(am__append_6)
# Arrange for git_version.h to be regenerated at every "make".
@@ -606,11 +608,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-parse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-staptree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-been.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-itrace.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-mark.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-perfmon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-procfs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapset-timers.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapsets.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-task_finder.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-translate.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-util.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap_client_connect-stap-client-connect.Po@am__quote@
@@ -1160,6 +1164,34 @@ stap-tapset-mark.obj: tapset-mark.cxx
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-mark.obj `if test -f 'tapset-mark.cxx'; then $(CYGPATH_W) 'tapset-mark.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-mark.cxx'; fi`
+stap-tapset-itrace.o: tapset-itrace.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-itrace.o -MD -MP -MF $(DEPDIR)/stap-tapset-itrace.Tpo -c -o stap-tapset-itrace.o `test -f 'tapset-itrace.cxx' || echo '$(srcdir)/'`tapset-itrace.cxx
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stap-tapset-itrace.Tpo $(DEPDIR)/stap-tapset-itrace.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tapset-itrace.cxx' object='stap-tapset-itrace.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-itrace.o `test -f 'tapset-itrace.cxx' || echo '$(srcdir)/'`tapset-itrace.cxx
+
+stap-tapset-itrace.obj: tapset-itrace.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-tapset-itrace.obj -MD -MP -MF $(DEPDIR)/stap-tapset-itrace.Tpo -c -o stap-tapset-itrace.obj `if test -f 'tapset-itrace.cxx'; then $(CYGPATH_W) 'tapset-itrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-itrace.cxx'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stap-tapset-itrace.Tpo $(DEPDIR)/stap-tapset-itrace.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='tapset-itrace.cxx' object='stap-tapset-itrace.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-tapset-itrace.obj `if test -f 'tapset-itrace.cxx'; then $(CYGPATH_W) 'tapset-itrace.cxx'; else $(CYGPATH_W) '$(srcdir)/tapset-itrace.cxx'; fi`
+
+stap-task_finder.o: task_finder.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-task_finder.o -MD -MP -MF $(DEPDIR)/stap-task_finder.Tpo -c -o stap-task_finder.o `test -f 'task_finder.cxx' || echo '$(srcdir)/'`task_finder.cxx
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stap-task_finder.Tpo $(DEPDIR)/stap-task_finder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='task_finder.cxx' object='stap-task_finder.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-task_finder.o `test -f 'task_finder.cxx' || echo '$(srcdir)/'`task_finder.cxx
+
+stap-task_finder.obj: task_finder.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-task_finder.obj -MD -MP -MF $(DEPDIR)/stap-task_finder.Tpo -c -o stap-task_finder.obj `if test -f 'task_finder.cxx'; then $(CYGPATH_W) 'task_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/task_finder.cxx'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stap-task_finder.Tpo $(DEPDIR)/stap-task_finder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='task_finder.cxx' object='stap-task_finder.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-task_finder.obj `if test -f 'task_finder.cxx'; then $(CYGPATH_W) 'task_finder.cxx'; else $(CYGPATH_W) '$(srcdir)/task_finder.cxx'; fi`
+
stap-modsign.o: modsign.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-modsign.o -MD -MP -MF $(DEPDIR)/stap-modsign.Tpo -c -o stap-modsign.o `test -f 'modsign.cxx' || echo '$(srcdir)/'`modsign.cxx
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stap-modsign.Tpo $(DEPDIR)/stap-modsign.Po
diff --git a/tapset-itrace.cxx b/tapset-itrace.cxx
new file mode 100644
index 00000000..38304a98
--- /dev/null
+++ b/tapset-itrace.cxx
@@ -0,0 +1,337 @@
+// tapset for timers
+// Copyright (C) 2005-2009 Red Hat Inc.
+// Copyright (C) 2005-2007 Intel Corporation.
+// Copyright (C) 2008 James.Bottomley@HansenPartnership.com
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+
+#include "session.h"
+#include "tapsets.h"
+#include "task_finder.h"
+#include "translate.h"
+#include "util.h"
+
+#include <cstring>
+#include <string>
+
+
+using namespace std;
+using namespace __gnu_cxx;
+
+
+static string TOK_PROCESS("process");
+static string TOK_INSN("insn");
+static string TOK_BLOCK("block");
+
+
+// ------------------------------------------------------------------------
+// itrace user-space probes
+// ------------------------------------------------------------------------
+
+
+struct itrace_derived_probe: public derived_probe
+{
+ bool has_path;
+ string path;
+ int64_t pid;
+ int single_step;
+
+ itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l,
+ bool hp, string &pn, int64_t pd, int ss
+ );
+ void join_group (systemtap_session& s);
+};
+
+
+struct itrace_derived_probe_group: public generic_dpg<itrace_derived_probe>
+{
+private:
+ map<string, vector<itrace_derived_probe*> > probes_by_path;
+ typedef map<string, vector<itrace_derived_probe*> >::iterator p_b_path_iterator;
+ map<int64_t, vector<itrace_derived_probe*> > probes_by_pid;
+ typedef map<int64_t, vector<itrace_derived_probe*> >::iterator p_b_pid_iterator;
+ unsigned num_probes;
+
+ void emit_probe_decl (systemtap_session& s, itrace_derived_probe *p);
+
+public:
+ itrace_derived_probe_group(): num_probes(0) { }
+
+ void enroll (itrace_derived_probe* probe);
+ void emit_module_decls (systemtap_session& s);
+ void emit_module_init (systemtap_session& s);
+ void emit_module_exit (systemtap_session& s);
+};
+
+
+itrace_derived_probe::itrace_derived_probe (systemtap_session &s,
+ probe* p, probe_point* l,
+ bool hp, string &pn, int64_t pd,
+ int ss
+ ):
+ derived_probe(p, l), has_path(hp), path(pn), pid(pd), single_step(ss)
+{
+}
+
+
+void
+itrace_derived_probe::join_group (systemtap_session& s)
+{
+ if (! s.itrace_derived_probes)
+ s.itrace_derived_probes = new itrace_derived_probe_group ();
+
+ s.itrace_derived_probes->enroll (this);
+
+ enable_task_finder(s);
+}
+
+struct itrace_builder: public derived_probe_builder
+{
+ itrace_builder() {}
+ virtual void build(systemtap_session & sess,
+ probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<derived_probe *> & finished_results)
+ {
+ string path;
+ int64_t pid = 0;
+ int single_step;
+
+ bool has_path = get_param (parameters, TOK_PROCESS, path);
+ bool has_pid = get_param (parameters, TOK_PROCESS, pid);
+ // XXX: PR 6445 needs !has_path && !has_pid support
+ assert (has_path || has_pid);
+
+ single_step = ! has_null_param (parameters, TOK_BLOCK);
+
+ // If we have a path, we need to validate it.
+ if (has_path)
+ path = find_executable (path);
+
+ finished_results.push_back(new itrace_derived_probe(sess, base, location,
+ has_path, path, pid,
+ single_step
+ ));
+ }
+};
+
+
+void
+itrace_derived_probe_group::enroll (itrace_derived_probe* p)
+{
+ if (p->has_path)
+ probes_by_path[p->path].push_back(p);
+ else
+ probes_by_pid[p->pid].push_back(p);
+ num_probes++;
+
+ // XXX: multiple exec probes (for instance) for the same path (or
+ // pid) should all share a itrace report function, and have their
+ // handlers executed sequentially.
+}
+
+
+void
+itrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
+ itrace_derived_probe *p)
+{
+ s.op->newline() << "{";
+ s.op->line() << " .tgt={";
+
+ if (p->has_path)
+ {
+ s.op->line() << " .pathname=\"" << p->path << "\",";
+ s.op->line() << " .pid=0,";
+ }
+ else
+ {
+ s.op->line() << " .pathname=NULL,";
+ s.op->line() << " .pid=" << p->pid << ",";
+ }
+
+ s.op->line() << " .callback=&_stp_itrace_probe_cb,";
+ s.op->line() << " },";
+ s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
+ s.op->line() << " .single_step=" << p->single_step << ",";
+ s.op->line() << " .ph=&" << p->name << ",";
+
+ s.op->line() << " },";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty())
+ return;
+
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+
+ s.op->newline() << "struct stap_itrace_probe {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target tgt;";
+ s.op->newline() << "const char *pp;";
+ s.op->newline() << "void (*ph) (struct context*);";
+ s.op->newline() << "int single_step;";
+ s.op->newline(-1) << "};";
+ s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);";
+ s.op->newline() << "#include \"itrace.c\"";
+
+ // output routine to call itrace probe
+ s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {";
+ s.op->indent(1);
+
+ common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "p->pp");
+ s.op->newline() << "c->regs = regs;";
+ s.op->newline() << "c->data = data;";
+
+ // call probe function
+ s.op->newline() << "(*p->ph) (c);";
+ common_probe_entryfn_epilogue (s.op);
+
+ s.op->newline() << "return;";
+ s.op->newline(-1) << "}";
+
+ // Output task finder callback routine that gets called for all
+ // itrace probe types.
+ s.op->newline() << "static int _stp_itrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
+ s.op->indent(1);
+ s.op->newline() << "int rc = 0;";
+ s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);";
+
+ s.op->newline() << "if (register_p) ";
+ s.op->indent(1);
+
+ s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk->pid, p);";
+ s.op->newline(-1) << "else";
+ s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(p->tgt.pid));";
+ s.op->newline(-1) << "return rc;";
+ s.op->newline(-1) << "}";
+
+ // Emit vma callbacks.
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {";
+ s.op->indent(1);
+ if (! probes_by_path.empty())
+ {
+ for (p_b_path_iterator it = probes_by_path.begin();
+ it != probes_by_path.end(); it++)
+ emit_vma_callback_probe_decl (s, it->first, (int64_t)0);
+ }
+ if (! probes_by_pid.empty())
+ {
+ for (p_b_pid_iterator it = probes_by_pid.begin();
+ it != probes_by_pid.end(); it++)
+ emit_vma_callback_probe_decl (s, "", it->first);
+ }
+ s.op->newline(-1) << "};";
+ s.op->newline() << "#endif";
+
+ s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {";
+ s.op->indent(1);
+
+ // Set up 'process(PATH)' probes
+ if (! probes_by_path.empty())
+ {
+ for (p_b_path_iterator it = probes_by_path.begin();
+ it != probes_by_path.end(); it++)
+ {
+ for (unsigned i = 0; i < it->second.size(); i++)
+ {
+ itrace_derived_probe *p = it->second[i];
+ emit_probe_decl(s, p);
+ }
+ }
+ }
+
+ // Set up 'process(PID)' probes
+ if (! probes_by_pid.empty())
+ {
+ for (p_b_pid_iterator it = probes_by_pid.begin();
+ it != probes_by_pid.end(); it++)
+ {
+ for (unsigned i = 0; i < it->second.size(); i++)
+ {
+ itrace_derived_probe *p = it->second[i];
+ emit_probe_decl(s, p);
+ }
+ }
+ }
+ s.op->newline(-1) << "};";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_init (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty())
+ return;
+
+ s.op->newline();
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
+ s.op->newline() << "/* ---- itrace vma callbacks ---- */";
+ s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_itrace_vmcbs); i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];";
+ s.op->newline() << "rc = stap_register_task_finder_target(r);";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "#endif";
+
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+
+ s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];";
+
+ // 'arch_has_single_step' needs to be defined for either single step mode
+ // or branch mode.
+ s.op->newline() << "if (!arch_has_single_step()) {";
+ s.op->indent(1);
+ s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");";
+ s.op->newline() << "rc = -EPERM;";
+ s.op->newline() << "break;";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {";
+ s.op->indent(1);
+ s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");";
+ s.op->newline() << "rc = -EPERM;";
+ s.op->newline() << "break;";
+ s.op->newline(-1) << "}";
+
+ s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
+ s.op->newline(-1) << "}";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_exit (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty()) return;
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+ s.op->newline() << "cleanup_usr_itrace();";
+}
+
+void
+register_tapset_itrace(systemtap_session& s)
+{
+ match_node* root = s.pattern_root;
+ derived_probe_builder *builder = new itrace_builder();
+
+ root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(builder);
+ root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(builder);
+ root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)->bind(builder);
+ root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)->bind(builder);
+}
+
+
+
+/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/tapsets.cxx b/tapsets.cxx
index 3ea94a73..6a4d41b6 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -12,6 +12,7 @@
#include "staptree.h"
#include "elaborate.h"
#include "tapsets.h"
+#include "task_finder.h"
#include "translate.h"
#include "session.h"
#include "util.h"
@@ -6150,379 +6151,6 @@ module_info::~module_info()
delete sym_table;
}
-// Helper function to emit vma tracker callbacks.
-static void
-emit_vma_callback_probe_decl (systemtap_session& s,
- string path,
- int64_t pid)
-{
- s.op->newline() << "{";
- if (pid == 0)
- {
- s.op->line() << " .pathname=\"" << path << "\",";
- s.op->line() << " .pid=0,";
- }
- else
- {
- s.op->line() << " .pathname=NULL,";
- s.op->line() << " .pid=" << pid << ",";
- }
- s.op->line() << " .callback=NULL,";
- s.op->line() << " .mmap_callback=&_stp_tf_mmap_cb,";
- s.op->line() << " .munmap_callback=&_stp_tf_munmap_cb,";
- s.op->line() << " .mprotect_callback=NULL,";
- s.op->line() << " },";
-}
-
-// ------------------------------------------------------------------------
-// task_finder derived 'probes': These don't really exist. The whole
-// purpose of the task_finder_derived_probe_group is to make sure that
-// stap_start_task_finder()/stap_stop_task_finder() get called only
-// once and in the right place.
-// ------------------------------------------------------------------------
-
-struct task_finder_derived_probe: public derived_probe
-{
- // Dummy constructor for gcc 3.4 compatibility
- task_finder_derived_probe (): derived_probe (0) { assert(0); }
-};
-
-
-struct task_finder_derived_probe_group: public generic_dpg<task_finder_derived_probe>
-{
-public:
- static void create_session_group (systemtap_session& s);
-
- void emit_module_decls (systemtap_session& ) { }
- void emit_module_init (systemtap_session& s);
- void emit_module_exit (systemtap_session& s);
-};
-
-
-void
-task_finder_derived_probe_group::create_session_group (systemtap_session& s)
-{
- if (! s.task_finder_derived_probes)
- s.task_finder_derived_probes = new task_finder_derived_probe_group();
-}
-
-
-void
-task_finder_derived_probe_group::emit_module_init (systemtap_session& s)
-{
- s.op->newline();
- s.op->newline() << "/* ---- task finder ---- */";
- s.op->newline() << "rc = stap_start_task_finder();";
-
- s.op->newline() << "if (rc) {";
- s.op->newline(1) << "stap_stop_task_finder();";
- s.op->newline(-1) << "}";
-}
-
-
-void
-task_finder_derived_probe_group::emit_module_exit (systemtap_session& s)
-{
- s.op->newline();
- s.op->newline() << "/* ---- task finder ---- */";
- s.op->newline() << "stap_stop_task_finder();";
-}
-
-// ------------------------------------------------------------------------
-// itrace user-space probes
-// ------------------------------------------------------------------------
-
-
-static string TOK_INSN("insn");
-static string TOK_BLOCK("block");
-
-struct itrace_derived_probe: public derived_probe
-{
- bool has_path;
- string path;
- int64_t pid;
- int single_step;
-
- itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l,
- bool hp, string &pn, int64_t pd, int ss
- );
- void join_group (systemtap_session& s);
-};
-
-
-struct itrace_derived_probe_group: public generic_dpg<itrace_derived_probe>
-{
-private:
- map<string, vector<itrace_derived_probe*> > probes_by_path;
- typedef map<string, vector<itrace_derived_probe*> >::iterator p_b_path_iterator;
- map<int64_t, vector<itrace_derived_probe*> > probes_by_pid;
- typedef map<int64_t, vector<itrace_derived_probe*> >::iterator p_b_pid_iterator;
- unsigned num_probes;
-
- void emit_probe_decl (systemtap_session& s, itrace_derived_probe *p);
-
-public:
- itrace_derived_probe_group(): num_probes(0) { }
-
- void enroll (itrace_derived_probe* probe);
- void emit_module_decls (systemtap_session& s);
- void emit_module_init (systemtap_session& s);
- void emit_module_exit (systemtap_session& s);
-};
-
-
-itrace_derived_probe::itrace_derived_probe (systemtap_session &s,
- probe* p, probe_point* l,
- bool hp, string &pn, int64_t pd,
- int ss
- ):
- derived_probe(p, l), has_path(hp), path(pn), pid(pd), single_step(ss)
-{
-}
-
-
-void
-itrace_derived_probe::join_group (systemtap_session& s)
-{
- if (! s.itrace_derived_probes)
- s.itrace_derived_probes = new itrace_derived_probe_group ();
-
- s.itrace_derived_probes->enroll (this);
-
- task_finder_derived_probe_group::create_session_group (s);
-}
-
-struct itrace_builder: public derived_probe_builder
-{
- itrace_builder() {}
- virtual void build(systemtap_session & sess,
- probe * base,
- probe_point * location,
- std::map<std::string, literal *> const & parameters,
- vector<derived_probe *> & finished_results)
- {
- string path;
- int64_t pid = 0;
- int single_step;
-
- bool has_path = get_param (parameters, TOK_PROCESS, path);
- bool has_pid = get_param (parameters, TOK_PROCESS, pid);
- // XXX: PR 6445 needs !has_path && !has_pid support
- assert (has_path || has_pid);
-
- single_step = ! has_null_param (parameters, TOK_BLOCK);
-
- // If we have a path, we need to validate it.
- if (has_path)
- path = find_executable (path);
-
- finished_results.push_back(new itrace_derived_probe(sess, base, location,
- has_path, path, pid,
- single_step
- ));
- }
-};
-
-
-void
-itrace_derived_probe_group::enroll (itrace_derived_probe* p)
-{
- if (p->has_path)
- probes_by_path[p->path].push_back(p);
- else
- probes_by_pid[p->pid].push_back(p);
- num_probes++;
-
- // XXX: multiple exec probes (for instance) for the same path (or
- // pid) should all share a itrace report function, and have their
- // handlers executed sequentially.
-}
-
-
-void
-itrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
- itrace_derived_probe *p)
-{
- s.op->newline() << "{";
- s.op->line() << " .tgt={";
-
- if (p->has_path)
- {
- s.op->line() << " .pathname=\"" << p->path << "\",";
- s.op->line() << " .pid=0,";
- }
- else
- {
- s.op->line() << " .pathname=NULL,";
- s.op->line() << " .pid=" << p->pid << ",";
- }
-
- s.op->line() << " .callback=&_stp_itrace_probe_cb,";
- s.op->line() << " },";
- s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
- s.op->line() << " .single_step=" << p->single_step << ",";
- s.op->line() << " .ph=&" << p->name << ",";
-
- s.op->line() << " },";
-}
-
-
-void
-itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
-{
- if (probes_by_path.empty() && probes_by_pid.empty())
- return;
-
- s.op->newline();
- s.op->newline() << "/* ---- itrace probes ---- */";
-
- s.op->newline() << "struct stap_itrace_probe {";
- s.op->indent(1);
- s.op->newline() << "struct stap_task_finder_target tgt;";
- s.op->newline() << "const char *pp;";
- s.op->newline() << "void (*ph) (struct context*);";
- s.op->newline() << "int single_step;";
- s.op->newline(-1) << "};";
- s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);";
- s.op->newline() << "#include \"itrace.c\"";
-
- // output routine to call itrace probe
- s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {";
- s.op->indent(1);
-
- common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "p->pp");
- s.op->newline() << "c->regs = regs;";
- s.op->newline() << "c->data = data;";
-
- // call probe function
- s.op->newline() << "(*p->ph) (c);";
- common_probe_entryfn_epilogue (s.op);
-
- s.op->newline() << "return;";
- s.op->newline(-1) << "}";
-
- // Output task finder callback routine that gets called for all
- // itrace probe types.
- s.op->newline() << "static int _stp_itrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
- s.op->indent(1);
- s.op->newline() << "int rc = 0;";
- s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);";
-
- s.op->newline() << "if (register_p) ";
- s.op->indent(1);
-
- s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk->pid, p);";
- s.op->newline(-1) << "else";
- s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(p->tgt.pid));";
- s.op->newline(-1) << "return rc;";
- s.op->newline(-1) << "}";
-
- // Emit vma callbacks.
- s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
- s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {";
- s.op->indent(1);
- if (! probes_by_path.empty())
- {
- for (p_b_path_iterator it = probes_by_path.begin();
- it != probes_by_path.end(); it++)
- emit_vma_callback_probe_decl (s, it->first, (int64_t)0);
- }
- if (! probes_by_pid.empty())
- {
- for (p_b_pid_iterator it = probes_by_pid.begin();
- it != probes_by_pid.end(); it++)
- emit_vma_callback_probe_decl (s, "", it->first);
- }
- s.op->newline(-1) << "};";
- s.op->newline() << "#endif";
-
- s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {";
- s.op->indent(1);
-
- // Set up 'process(PATH)' probes
- if (! probes_by_path.empty())
- {
- for (p_b_path_iterator it = probes_by_path.begin();
- it != probes_by_path.end(); it++)
- {
- for (unsigned i = 0; i < it->second.size(); i++)
- {
- itrace_derived_probe *p = it->second[i];
- emit_probe_decl(s, p);
- }
- }
- }
-
- // Set up 'process(PID)' probes
- if (! probes_by_pid.empty())
- {
- for (p_b_pid_iterator it = probes_by_pid.begin();
- it != probes_by_pid.end(); it++)
- {
- for (unsigned i = 0; i < it->second.size(); i++)
- {
- itrace_derived_probe *p = it->second[i];
- emit_probe_decl(s, p);
- }
- }
- }
- s.op->newline(-1) << "};";
-}
-
-
-void
-itrace_derived_probe_group::emit_module_init (systemtap_session& s)
-{
- if (probes_by_path.empty() && probes_by_pid.empty())
- return;
-
- s.op->newline();
- s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
- s.op->newline() << "_stp_sym_init();";
- s.op->newline() << "/* ---- itrace vma callbacks ---- */";
- s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_itrace_vmcbs); i++) {";
- s.op->indent(1);
- s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];";
- s.op->newline() << "rc = stap_register_task_finder_target(r);";
- s.op->newline(-1) << "}";
- s.op->newline() << "#endif";
-
- s.op->newline();
- s.op->newline() << "/* ---- itrace probes ---- */";
-
- s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {";
- s.op->indent(1);
- s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];";
-
- // 'arch_has_single_step' needs to be defined for either single step mode
- // or branch mode.
- s.op->newline() << "if (!arch_has_single_step()) {";
- s.op->indent(1);
- s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");";
- s.op->newline() << "rc = -EPERM;";
- s.op->newline() << "break;";
- s.op->newline(-1) << "}";
- s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {";
- s.op->indent(1);
- s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");";
- s.op->newline() << "rc = -EPERM;";
- s.op->newline() << "break;";
- s.op->newline(-1) << "}";
-
- s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
- s.op->newline(-1) << "}";
-}
-
-
-void
-itrace_derived_probe_group::emit_module_exit (systemtap_session& s)
-{
- if (probes_by_path.empty() && probes_by_pid.empty()) return;
- s.op->newline();
- s.op->newline() << "/* ---- itrace probes ---- */";
- s.op->newline() << "cleanup_usr_itrace();";
-}
-
// ------------------------------------------------------------------------
// utrace user-space probes
// ------------------------------------------------------------------------
@@ -6687,7 +6315,7 @@ utrace_derived_probe::join_group (systemtap_session& s)
}
s.utrace_derived_probes->enroll (this);
- task_finder_derived_probe_group::create_session_group (s);
+ enable_task_finder(s);
}
@@ -7678,7 +7306,7 @@ uprobe_derived_probe::join_group (systemtap_session& s)
if (! s.uprobe_derived_probes)
s.uprobe_derived_probes = new uprobe_derived_probe_group ();
s.uprobe_derived_probes->enroll (this);
- task_finder_derived_probe_group::create_session_group (s);
+ enable_task_finder(s);
// Ask buildrun.cxx to build extra module if needed, and
// signal staprun to load that module
@@ -9338,6 +8966,7 @@ void
register_standard_tapsets(systemtap_session & s)
{
register_tapset_been(s);
+ register_tapset_itrace(s);
register_tapset_mark(s);
register_tapset_perfmon(s);
register_tapset_procfs(s);
@@ -9393,16 +9022,6 @@ register_standard_tapsets(systemtap_session & s)
s.pattern_root->bind(TOK_PROCESS)->bind(TOK_SYSCALL)->bind(TOK_RETURN)
->bind(new utrace_builder ());
- // itrace user-space probes
- s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
- ->bind(new itrace_builder ());
- s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
- ->bind(new itrace_builder ());
- s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
- ->bind(new itrace_builder ());
- s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
- ->bind(new itrace_builder ());
-
// kernel tracepoint probes
s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_TRACE)
->bind(new tracepoint_builder());
diff --git a/tapsets.h b/tapsets.h
index d4fe7a91..da4bebd3 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2009 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
@@ -21,6 +21,7 @@ void common_probe_entryfn_prologue (translator_output* o, std::string statestr,
void common_probe_entryfn_epilogue (translator_output* o, bool overload_processing = true);
void register_tapset_been(systemtap_session& sess);
+void register_tapset_itrace(systemtap_session& sess);
void register_tapset_mark(systemtap_session& sess);
void register_tapset_perfmon(systemtap_session& sess);
void register_tapset_procfs(systemtap_session& sess);
diff --git a/task_finder.cxx b/task_finder.cxx
new file mode 100644
index 00000000..de1c2208
--- /dev/null
+++ b/task_finder.cxx
@@ -0,0 +1,103 @@
+// task finder for user tapsets
+// Copyright (C) 2005-2009 Red Hat Inc.
+// Copyright (C) 2005-2007 Intel Corporation.
+// Copyright (C) 2008 James.Bottomley@HansenPartnership.com
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+
+#include "session.h"
+#include "tapsets.h"
+#include "task_finder.h"
+#include "translate.h"
+#include "util.h"
+
+#include <cstring>
+#include <string>
+
+
+using namespace std;
+using namespace __gnu_cxx;
+
+
+// ------------------------------------------------------------------------
+// task_finder derived 'probes': These don't really exist. The whole
+// purpose of the task_finder_derived_probe_group is to make sure that
+// stap_start_task_finder()/stap_stop_task_finder() get called only
+// once and in the right place.
+// ------------------------------------------------------------------------
+
+struct task_finder_derived_probe: public derived_probe
+{
+ // Dummy constructor for gcc 3.4 compatibility
+ task_finder_derived_probe (): derived_probe (0) { assert(0); }
+};
+
+
+struct task_finder_derived_probe_group: public generic_dpg<task_finder_derived_probe>
+{
+public:
+ void emit_module_decls (systemtap_session& ) { }
+ void emit_module_init (systemtap_session& s);
+ void emit_module_exit (systemtap_session& s);
+};
+
+
+void
+task_finder_derived_probe_group::emit_module_init (systemtap_session& s)
+{
+ s.op->newline();
+ s.op->newline() << "/* ---- task finder ---- */";
+ s.op->newline() << "rc = stap_start_task_finder();";
+
+ s.op->newline() << "if (rc) {";
+ s.op->newline(1) << "stap_stop_task_finder();";
+ s.op->newline(-1) << "}";
+}
+
+
+void
+task_finder_derived_probe_group::emit_module_exit (systemtap_session& s)
+{
+ s.op->newline();
+ s.op->newline() << "/* ---- task finder ---- */";
+ s.op->newline() << "stap_stop_task_finder();";
+}
+
+
+// Declare that task_finder is needed in this session
+void
+enable_task_finder(systemtap_session& s)
+{
+ if (! s.task_finder_derived_probes)
+ s.task_finder_derived_probes = new task_finder_derived_probe_group();
+}
+
+// Helper function to emit vma tracker callbacks.
+void
+emit_vma_callback_probe_decl (systemtap_session& s,
+ string path,
+ int64_t pid)
+{
+ s.op->newline() << "{";
+ if (pid == 0)
+ {
+ s.op->line() << " .pathname=\"" << path << "\",";
+ s.op->line() << " .pid=0,";
+ }
+ else
+ {
+ s.op->line() << " .pathname=NULL,";
+ s.op->line() << " .pid=" << pid << ",";
+ }
+ s.op->line() << " .callback=NULL,";
+ s.op->line() << " .mmap_callback=&_stp_tf_mmap_cb,";
+ s.op->line() << " .munmap_callback=&_stp_tf_munmap_cb,";
+ s.op->line() << " .mprotect_callback=NULL,";
+ s.op->line() << " },";
+}
+
+/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/task_finder.h b/task_finder.h
new file mode 100644
index 00000000..99419e32
--- /dev/null
+++ b/task_finder.h
@@ -0,0 +1,20 @@
+// -*- C++ -*-
+// Copyright (C) 2009 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+#ifndef TASK_FINDER_H
+#define TASK_FINDER_H
+
+// Declare that task_finder is needed in this session
+void enable_task_finder(systemtap_session& s);
+
+// Helper function to emit vma tracker callbacks.
+void emit_vma_callback_probe_decl (systemtap_session& s, std::string path, int64_t pid);
+
+#endif // TASK_FINDER_H
+
+/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */