public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* [RFC][Patch 0/2] New Probe family : probe kprobe.function()
@ 2009-04-16 12:27 Prerna Saxena
  2009-04-16 12:29 ` [RFC][Patch 1/2] " Prerna Saxena
  2009-04-16 16:48 ` [RFC][Patch 0/2] " Frank Ch. Eigler
  0 siblings, 2 replies; 6+ messages in thread
From: Prerna Saxena @ 2009-04-16 12:27 UTC (permalink / raw)
  To: systemtap

Hi all,
Here's a prototype of a new language feature in systemtap : probe 
kprobe, which bypasses all dwarf lookup for function names & utilizes 
kernel symbol table at runtime. Such probes are therefore agnostic to 
kernel version with no dependency on debuginfo.

This can be invoked using " probe 
kprobe.function("kernel_function_name"){.......} "

Limitations :
1. Does not support statement probing
2. Does not support wildcards.
3. Does not support probing the local variables of a function.

TODOs:
1. Support function argument probing.
2. Extend this to probe function returns.
3. Allow demoting  kernel.function (...) probes to kprobe.function (..) 
probes if debuginfo is missing.
4. Use /proc/kallsyms to validate function names in pass 2

Not tested too extensively, I'm looking fwd to comments :-)

Regards,

-- 
Prerna Saxena

Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][Patch 1/2] New Probe family : probe kprobe.function()
  2009-04-16 12:27 [RFC][Patch 0/2] New Probe family : probe kprobe.function() Prerna Saxena
@ 2009-04-16 12:29 ` Prerna Saxena
  2009-04-16 12:30   ` [RFC][Patch 2/2] " Prerna Saxena
  2009-04-16 16:48 ` [RFC][Patch 0/2] " Frank Ch. Eigler
  1 sibling, 1 reply; 6+ messages in thread
From: Prerna Saxena @ 2009-04-16 12:29 UTC (permalink / raw)
  To: systemtap

[-- Attachment #1: Type: text/plain, Size: 191 bytes --]

This patch addresses changes to tapsets.cxx for creating a new probe 
type  "kprobe"

Regards,

-- 
Prerna Saxena

Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India 


[-- Attachment #2: kprobe-patch-1 --]
[-- Type: text/plain, Size: 20587 bytes --]

Signed-off-by: Prerna Saxena <prerna@linux.vnet.ibm.com>

Index: git-24-mar/tapsets.cxx
===================================================================
--- git-24-mar.orig/tapsets.cxx
+++ git-24-mar/tapsets.cxx
@@ -2649,7 +2649,34 @@ struct uprobe_derived_probe: public deri
   void join_group (systemtap_session& s);
 };
 
+struct kprobe_derived_probe: public derived_probe
+{
+  kprobe_derived_probe (probe *base,
+			probe_point *location,
+			const string& name,
+			bool has_return
+			);
+  string symbol_name;
+  bool has_return;
+  bool has_maxactive;
+  long maxactive_val;
+  bool access_var;
+  void printsig (std::ostream &o) const;
+  void join_group (systemtap_session& s);
+};
+
+struct kprobe_derived_probe_group: public derived_probe_group
+{
+private:
+  multimap<string,kprobe_derived_probe*> probes_by_module;
+  typedef multimap<string,kprobe_derived_probe*>::iterator p_b_m_iterator;
 
+public:
+  void enroll (kprobe_derived_probe* probe);
+  void emit_module_decls (systemtap_session& s);
+  void emit_module_init (systemtap_session& s);
+  void emit_module_exit (systemtap_session& s);
+};
 
 struct dwarf_derived_probe_group: public derived_probe_group
 {
@@ -4343,7 +4370,6 @@ struct dwarf_var_expanding_visitor: publ
 };
 
 
-
 unsigned var_expanding_visitor::tick = 0;
 
 void
@@ -5360,6 +5386,23 @@ dwarf_derived_probe_group::enroll (dwarf
   // sequentially.
 }
 
+/*
+void
+dwarf_derived_probe_group::enroll (kprobe_derived_probe* p)
+{
+  dwarf_derived_probe *dw_probe = new dwarf_derived_probe (p->symbol_name,
+							   "",0,
+							   p->module_name,
+							   p->section_name,
+							   0,0,
+							   p->q,NULL);
+  probes_by_module.insert (make_pair (p->module, p));
+
+  // XXX: probes put at the same address should all share a
+  // single kprobe/kretprobe, and have their handlers executed
+  // sequentially.
+}
+*/
 
 void
 dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
@@ -5442,6 +5485,7 @@ dwarf_derived_probe_group::emit_module_d
   CALCIT(module);
   CALCIT(section);
   CALCIT(pp);
+#undef CALCIT
 
   s.op->newline() << "const unsigned long address;";
   s.op->newline() << "void (* const ph) (struct context*);";
@@ -6180,7 +6224,6 @@ module_info::~module_info()
 }
 
 
-
 // ------------------------------------------------------------------------
 // task_finder derived 'probes': These don't really exist.  The whole
 // purpose of the task_finder_derived_probe_group is to make sure that
@@ -7735,8 +7778,378 @@ uprobe_derived_probe_group::emit_module_
   s.op->newline() << "mutex_destroy (& stap_uprobes_lock);";
 }
 
+// ------------------------------------------------------------------------
+// Kprobe derived probes
+// ------------------------------------------------------------------------
+
+static string TOK_KPROBE("kprobe");
+
+kprobe_derived_probe::kprobe_derived_probe (probe *base,
+					    probe_point *location,
+				  	    const string& name,
+					    bool has_return
+):
+  derived_probe (base, location),
+  symbol_name (name)
+{
+  this->tok = base->tok;
+  this->access_var = false;
+
+#ifndef USHRT_MAX
+#define USHRT_MAX 32767
+#endif
+
+  // Expansion of $target variables in the probe body produces an error during translate phase
+  vector<probe_point::component*> comps;
+
+  if (has_return)
+	comps.push_back (new probe_point::component(TOK_RETURN));
+
+  this->sole_location()->components = comps;
+}
+
+void kprobe_derived_probe::printsig (ostream& o) const
+{
+  sole_location()->print (o);
+  o << " /* " << " name = " << symbol_name << "*/";
+  printsig_nested (o);
+}
+
+void kprobe_derived_probe::join_group (systemtap_session& s)
+{
+
+  if (! s.kprobe_derived_probes)
+	s.kprobe_derived_probes = new kprobe_derived_probe_group ();
+  s.kprobe_derived_probes->enroll (this);
+
+}
+
+void kprobe_derived_probe_group::enroll (kprobe_derived_probe* p)
+{
+  probes_by_module.insert (make_pair (p->symbol_name, p));
+  // probes of same symbol should share single kprobe/kretprobe
+}
+
+void
+kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+  if (probes_by_module.empty()) return;
+
+  s.op->newline() << "/* ---- kprobe-based probes ---- */";
+
+  // Warn of misconfigured kernels
+  s.op->newline() << "#if ! defined(CONFIG_KPROBES)";
+  s.op->newline() << "#error \"Need CONFIG_KPROBES!\"";
+  s.op->newline() << "#endif";
+  s.op->newline();
+
+  // Forward declare the master entry functions
+  s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
+  s.op->line() << " struct pt_regs *regs);";
+  s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
+  s.op->line() << " struct pt_regs *regs);";
+
+  // Emit an array of kprobe/kretprobe pointers
+  s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
+  s.op->newline() << "static void * stap_unreg_kprobes[" << probes_by_module.size() << "];";
+  s.op->newline() << "#endif";
+
+  // Emit the actual probe list.
+
+  s.op->newline() << "static struct stap_dwarfless_kprobe {";
+  s.op->newline(1) << "union { struct kprobe kp; struct kretprobe krp; } u;";
+  s.op->newline() << "#ifdef __ia64__";
+  s.op->newline() << "struct kprobe dummy;";
+  s.op->newline() << "#endif";
+  s.op->newline(-1) << "} stap_dwarfless_kprobes[" << probes_by_module.size() << "];";
+  // NB: bss!
+
+  s.op->newline() << "static struct stap_dwarfless_probe {";
+  s.op->newline(1) << "const unsigned return_p:1;";
+  s.op->newline() << "const unsigned maxactive_p:1;";
+  s.op->newline() << "unsigned registered_p:1;";
+  s.op->newline() << "const unsigned short maxactive_val;";
+
+  // Let's find some stats for the three embedded strings.  Maybe they
+  // are small and uniform enough to justify putting char[MAX]'s into
+  // the array instead of relocated char*'s.
+  size_t pp_name_max = 0, symbol_string_name_max = 0;
+  size_t pp_name_tot = 0, symbol_string_name_tot = 0;
+  size_t all_name_cnt = probes_by_module.size(); // for average
+  for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
+    {
+      kprobe_derived_probe* p = it->second;
+#define DOIT(var,expr) do {                             \
+        size_t var##_size = (expr) + 1;                 \
+        var##_max = max (var##_max, var##_size);        \
+        var##_tot += var##_size; } while (0)
+      DOIT(pp_name, lex_cast_qstring(*p->sole_location()).size());
+      DOIT(symbol_string_name, p->symbol_name.size());
+#undef DOIT
+
+    }
+
+  // Decide whether it's worthwhile to use char[] or char* by comparing
+  // the amount of average waste (max - avg) to the relocation data size
+  // (3 native long words).
+#define CALCIT(var)                                                     \
+  if ((var##_name_max-(var##_name_tot/all_name_cnt)) < (3 * sizeof(void*))) \
+    {                                                                   \
+      s.op->newline() << "const char " << #var << "[" << var##_name_max << "];"; \
+      if (s.verbose > 2) clog << "stap_dwarfless_probe " << #var            \
+                              << "[" << var##_name_max << "]" << endl;  \
+    }                                                                   \
+  else                                                                  \
+    {                                                                   \
+      s.op->newline() << "const char * const " << #var << ";";                 \
+      if (s.verbose > 2) clog << "stap_dwarfless_probe *" << #var << endl;  \
+    }
+
+  CALCIT(pp);
+  CALCIT(symbol_string);
+#undef CALCIT
+
+  s.op->newline() << "const unsigned long address;";
+  s.op->newline() << "void (* const ph) (struct context*);";
+  s.op->newline(-1) << "} stap_dwarfless_probes[] = {";
+  s.op->indent(1);
+
+  for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
+    {
+      kprobe_derived_probe* p = it->second;
+      s.op->newline() << "{";
+      if (p->has_return)
+        s.op->line() << " .return_p=1,";
+      if (p->has_maxactive)
+        {
+          s.op->line() << " .maxactive_p=1,";
+          assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX);
+          s.op->line() << " .maxactive_val=" << p->maxactive_val << ",";
+        }
+      s.op->line() << " .address=(unsigned long)0x" << hex << 0 << dec << "ULL,";
+      s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
+      s.op->line() << " .ph=&" << p->name << ",";
+      s.op->line() << " .symbol_string=\"" << p->symbol_name << "\"";
+      s.op->line() << " },";
+    }
+
+  s.op->newline(-1) << "};";
 
+  // Emit the kprobes callback function
+  s.op->newline();
+  s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
+  s.op->line() << " struct pt_regs *regs) {";
+  // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
+  s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);";
+  // Check that the index is plausible
+  s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes[";
+  s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
+  s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
+  // XXX: it would be nice to give a more verbose error though; BUG_ON later?
+  s.op->line() << "];";
+  common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
+  s.op->newline() << "c->regs = regs;";
+  s.op->newline() << "(*sdp->ph) (c);";
+  common_probe_entryfn_epilogue (s.op);
+  s.op->newline() << "return 0;";
+  s.op->newline(-1) << "}";
 
+  // Same for kretprobes
+  s.op->newline();
+  s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
+  s.op->line() << " struct pt_regs *regs) {";
+  s.op->newline(1) << "struct kretprobe *krp = inst->rp;";
+
+  // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
+  s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);";
+  // Check that the index is plausible
+  s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes[";
+  s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
+  s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
+  // XXX: it would be nice to give a more verbose error though; BUG_ON later?
+  s.op->line() << "];";
+
+  common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
+  s.op->newline() << "c->regs = regs;";
+  s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic
+  s.op->newline() << "(*sdp->ph) (c);";
+  common_probe_entryfn_epilogue (s.op);
+  s.op->newline() << "return 0;";
+  s.op->newline(-1) << "}";
+}
+
+
+void
+kprobe_derived_probe_group::emit_module_init (systemtap_session& s)
+{
+  s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
+  s.op->newline() << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+  s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
+  s.op->newline() << "unsigned long relocated_addr = 0;";
+  s.op->newline() << "probe_point = sdp->pp;"; // for error messages
+  s.op->newline() << "if (sdp->return_p) {";
+  s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;";
+  s.op->newline() << "kp->u.krp.kp.symbol_name = sdp->symbol_string;";
+  s.op->newline() << "if (sdp->maxactive_p) {";
+  s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;";
+  s.op->newline(-1) << "} else {";
+  s.op->newline(1) << "kp->u.krp.maxactive = max(10, 4*NR_CPUS);";
+  s.op->newline(-1) << "}";
+  s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;";
+  // to ensure safeness of bspcache, always use aggr_kprobe on ia64
+  s.op->newline() << "#ifdef __ia64__";
+  s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
+  s.op->newline() << "kp->dummy.pre_handler = NULL;";
+  s.op->newline() << "kp->dummy.symbol_name = sdp->symbol_string;";
+  s.op->newline() << "rc = register_kprobe (& kp->dummy);";
+  s.op->newline() << "if (rc == 0) {";
+  s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);";
+  s.op->newline() << "if (rc != 0)";
+  s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
+  s.op->newline(-2) << "}";
+  s.op->newline() << "#else";
+  s.op->newline() << "rc = register_kretprobe (& kp->u.krp);";
+  s.op->newline() << "#endif";
+  s.op->newline(-1) << "} else {";
+  // to ensure safeness of bspcache, always use aggr_kprobe on ia64
+  s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;";
+  s.op->newline(1) << "kp->u.kp.symbol_name = sdp->symbol_string;";
+  s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe_probe;";
+  s.op->newline() << "#ifdef __ia64__";
+  s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
+  s.op->newline() << "kp->dummy.pre_handler = NULL;";
+  s.op->newline() << "kp->dummy.symbol_name = sdp->symbol_string;";
+  s.op->newline() << "rc = register_kprobe (& kp->dummy);";
+  s.op->newline() << "if (rc == 0) {";
+  s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);";
+  s.op->newline() << "if (rc != 0)";
+  s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
+  s.op->newline(-2) << "}";
+  s.op->newline() << "#else";
+  s.op->newline() << "rc = register_kprobe (& kp->u.kp);";
+  s.op->newline() << "#endif";
+  s.op->newline(-1) << "}";
+  s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe.
+  s.op->newline(1) << "sdp->registered_p = 0;";
+  s.op->newline() << "if (rc == -EINVAL)";
+  s.op->newline() << "{";
+  s.op->newline() << "  _stp_error (\"Error registering kprobe,possibly an incorrect name %s \", sdp->symbol_string);";
+  s.op->newline() << "  atomic_set (&session_state, STAP_SESSION_ERROR);";
+  s.op->newline() << "  goto out;";
+  s.op->newline() << "}";
+  s.op->newline() << "else";
+  s.op->newline() << "_stp_warn (\"probe %s for %s registration error (rc %d)\", probe_point, sdp->pp, rc);";
+  s.op->newline() << "rc = 0;"; // continue with other probes
+  // XXX: shall we increment numskipped?
+  s.op->newline(-1) << "}";
+
+  s.op->newline() << "else sdp->registered_p = 1;";
+  s.op->newline(-1) << "}"; // for loop
+}
+
+void
+kprobe_derived_probe_group::emit_module_exit (systemtap_session& s)
+{
+  //Unregister kprobes by batch interfaces.
+  s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
+  s.op->newline() << "j = 0;";
+  s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
+  s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+  s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
+  s.op->newline() << "if (! sdp->registered_p) continue;";
+  s.op->newline() << "if (!sdp->return_p)";
+  s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.kp;";
+  s.op->newline(-2) << "}";
+  s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);";
+  s.op->newline() << "j = 0;";
+  s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
+  s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+  s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
+  s.op->newline() << "if (! sdp->registered_p) continue;";
+  s.op->newline() << "if (sdp->return_p)";
+  s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.krp;";
+  s.op->newline(-2) << "}";
+  s.op->newline() << "unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, j);";
+  s.op->newline() << "#ifdef __ia64__";
+  s.op->newline() << "j = 0;";
+  s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
+  s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+  s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
+  s.op->newline() << "if (! sdp->registered_p) continue;";
+  s.op->newline() << "stap_unreg_kprobes[j++] = &kp->dummy;";
+  s.op->newline(-1) << "}";
+  s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);";
+  s.op->newline() << "#endif";
+  s.op->newline() << "#endif";
+
+  s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
+  s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+  s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
+  s.op->newline() << "if (! sdp->registered_p) continue;";
+  s.op->newline() << "if (sdp->return_p) {";
+  s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
+  s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);";
+  s.op->newline() << "#endif";
+  s.op->newline() << "atomic_add (kp->u.krp.nmissed, & skipped_count);";
+  s.op->newline() << "#ifdef STP_TIMING";
+  s.op->newline() << "if (kp->u.krp.nmissed)";
+  s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->pp, kp->u.krp.nmissed);";
+  s.op->newline(-1) << "#endif";
+  s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, & skipped_count);";
+  s.op->newline() << "#ifdef STP_TIMING";
+  s.op->newline() << "if (kp->u.krp.kp.nmissed)";
+  s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %d\\n\", sdp->pp, kp->u.krp.kp.nmissed);";
+  s.op->newline(-1) << "#endif";
+  s.op->newline(-1) << "} else {";
+  s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
+  s.op->newline(1) << "unregister_kprobe (&kp->u.kp);";
+  s.op->newline() << "#endif";
+  s.op->newline() << "atomic_add (kp->u.kp.nmissed, & skipped_count);";
+  s.op->newline() << "#ifdef STP_TIMING";
+  s.op->newline() << "if (kp->u.kp.nmissed)";
+  s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %d\\n\", sdp->pp, kp->u.kp.nmissed);";
+  s.op->newline(-1) << "#endif";
+  s.op->newline(-1) << "}";
+  s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)";
+  s.op->newline() << "unregister_kprobe (&kp->dummy);";
+  s.op->newline() << "#endif";
+  s.op->newline() << "sdp->registered_p = 0;";
+  s.op->newline(-1) << "}";
+}
+
+struct kprobe_builder: public derived_probe_builder
+{
+  kprobe_builder() {}
+  virtual void build(systemtap_session & sess,
+		     probe * base,
+		     probe_point * location,
+		     literal_map_t const & parameters,
+		     vector<derived_probe *> & finished_results);
+};
+
+
+void
+kprobe_builder::build(systemtap_session & sess,
+		      probe * base,
+		      probe_point * location,
+		      literal_map_t const & parameters,
+		      vector<derived_probe *> & finished_results)
+{
+  string function_string_val;
+
+  bool has_function_str = this->get_param(parameters, TOK_FUNCTION, function_string_val);
+  if ( ! has_function_str )
+	throw semantic_error("\n Function name required for kprobe based probes");
+  bool has_inline = this->has_null_param (parameters, TOK_INLINE);
+  bool has_return = this->has_null_param (parameters, TOK_RETURN);
+
+  if (has_inline)
+	throw semantic_error("\n Kprobe-based probes cannot handle inlines \n");
+
+  finished_results.push_back(new kprobe_derived_probe ( base, location,
+						        function_string_val,
+							has_return) );
+}
 // ------------------------------------------------------------------------
 // timer derived probes
 // ------------------------------------------------------------------------
@@ -10685,6 +11098,10 @@ perfmon_derived_probe_group::emit_module
 }
 #endif
 
+// ------------------------------------------------------------------------
+//   kprobes-based probes,which postpone symbol resolution until runtime.
+// ------------------------------------------------------------------------
+
 
 // ------------------------------------------------------------------------
 //  Standard tapset registry.
@@ -10779,6 +11196,10 @@ register_standard_tapsets(systemtap_sess
   s.pattern_root->bind(TOK_PROCFS)->bind(TOK_WRITE)->bind(new procfs_builder());
   s.pattern_root->bind_str(TOK_PROCFS)->bind(TOK_WRITE)
     ->bind(new procfs_builder());
+
+  // Kprobe based probe
+  s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)
+     ->bind(new kprobe_builder());
 }
 
 
@@ -10801,6 +11222,7 @@ all_session_groups(systemtap_session& s)
   DOONE(profile);
   DOONE(mark);
   DOONE(tracepoint);
+  DOONE(kprobe);
   DOONE(hrtimer);
   DOONE(perfmon);
   DOONE(procfs);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][Patch 2/2] New Probe family : probe kprobe.function()
  2009-04-16 12:29 ` [RFC][Patch 1/2] " Prerna Saxena
@ 2009-04-16 12:30   ` Prerna Saxena
  0 siblings, 0 replies; 6+ messages in thread
From: Prerna Saxena @ 2009-04-16 12:30 UTC (permalink / raw)
  To: systemtap

[-- Attachment #1: Type: text/plain, Size: 208 bytes --]

This patch adds the probe group "kprobe_derived_probe_group" to 
systemtap_session class in session.h

Regards,

-- 
Prerna Saxena

Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India 


[-- Attachment #2: kprobe-patch-2 --]
[-- Type: text/plain, Size: 870 bytes --]

Signed-off-by: Prerna Saxena <prerna@linux.vnet.ibm.com>

Index: git-24-mar/session.h
===================================================================
--- git-24-mar.orig/session.h
+++ git-24-mar/session.h
@@ -30,6 +30,7 @@ struct functiondecl;
 struct derived_probe;
 struct be_derived_probe_group;
 struct dwarf_derived_probe_group;
+struct kprobe_derived_probe_group;
 struct uprobe_derived_probe_group;
 struct utrace_derived_probe_group;
 struct itrace_derived_probe_group;
@@ -159,6 +160,7 @@ struct systemtap_session
   // session.probes vector.
   be_derived_probe_group* be_derived_probes;
   dwarf_derived_probe_group* dwarf_derived_probes;
+  kprobe_derived_probe_group* kprobe_derived_probes;
   uprobe_derived_probe_group* uprobe_derived_probes;
   utrace_derived_probe_group* utrace_derived_probes;
   itrace_derived_probe_group* itrace_derived_probes;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][Patch 0/2] New Probe family : probe kprobe.function()
  2009-04-16 12:27 [RFC][Patch 0/2] New Probe family : probe kprobe.function() Prerna Saxena
  2009-04-16 12:29 ` [RFC][Patch 1/2] " Prerna Saxena
@ 2009-04-16 16:48 ` Frank Ch. Eigler
  2009-04-16 16:58   ` Ananth N Mavinakayanahalli
       [not found]   ` <49EB6076.4050905@linux.vnet.ibm.com>
  1 sibling, 2 replies; 6+ messages in thread
From: Frank Ch. Eigler @ 2009-04-16 16:48 UTC (permalink / raw)
  To: Prerna Saxena; +Cc: systemtap


Prerna Saxena <prerna@linux.vnet.ibm.com> writes:

> Here's a prototype of a new language feature in systemtap : probe
> kprobe [...]

Looks good.  I suggest a few changes:

- removal of ".inline"-related logic/variables, since they are inherently
  unavailable
- removal of registration/unregistration code that was added for symbolic
  kprobes only to optimize the thousands-of-probes case, such as the
  char*/char[] automagic selector
- initialization of the new systemtap_session field 
- adding test cases, documentation, NEWS blurb

To what extent does the kernel's symbolic kprobe logic allow probes to
be placed within modules?  Would it be worthwhile to allow numeric
probe addresses (as in kernel.statement(0xaddr).absolute)?


- FChE

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][Patch 0/2] New Probe family : probe kprobe.function()
  2009-04-16 16:48 ` [RFC][Patch 0/2] " Frank Ch. Eigler
@ 2009-04-16 16:58   ` Ananth N Mavinakayanahalli
       [not found]   ` <49EB6076.4050905@linux.vnet.ibm.com>
  1 sibling, 0 replies; 6+ messages in thread
From: Ananth N Mavinakayanahalli @ 2009-04-16 16:58 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: Prerna Saxena, systemtap

On Thu, Apr 16, 2009 at 12:48:43PM -0400, Frank Ch. Eigler wrote:
> 
> Prerna Saxena <prerna@linux.vnet.ibm.com> writes:
> 
> To what extent does the kernel's symbolic kprobe logic allow probes to
> be placed within modules?

There is no difference in logic between probes in modules vs. those in
kernel - both just work since the kallsyms_lookup_name() calls into
module_kallsyms_lookup_name() if the symbol wasn't resolved in the
kernel.

However, namespace clashes are allowed in modules. AFAICS if there is a
namespace clash, the first resolved address is returned. To mitigate
this, one can use <module>:<symbol>.

>  Would it be worthwhile to allow numeric
> probe addresses (as in kernel.statement(0xaddr).absolute)?

That would be even more straightforward I think - just set the emitted
kp.addr = 0xaddr

Ananth

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function()
       [not found]   ` <49EB6076.4050905@linux.vnet.ibm.com>
@ 2009-04-19 18:25     ` Frank Ch. Eigler
  0 siblings, 0 replies; 6+ messages in thread
From: Frank Ch. Eigler @ 2009-04-19 18:25 UTC (permalink / raw)
  To: Prerna Saxena; +Cc: systemtap

Hi -

On Sun, Apr 19, 2009 at 11:03:42PM +0530, Prerna Saxena wrote:
> Here's the revised set of patches.
> [...]

Thank you, nicely done.

- FChE

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-04-19 18:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-16 12:27 [RFC][Patch 0/2] New Probe family : probe kprobe.function() Prerna Saxena
2009-04-16 12:29 ` [RFC][Patch 1/2] " Prerna Saxena
2009-04-16 12:30   ` [RFC][Patch 2/2] " Prerna Saxena
2009-04-16 16:48 ` [RFC][Patch 0/2] " Frank Ch. Eigler
2009-04-16 16:58   ` Ananth N Mavinakayanahalli
     [not found]   ` <49EB6076.4050905@linux.vnet.ibm.com>
2009-04-19 18:25     ` [RFC][Revised Patch 0/5] " Frank Ch. Eigler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).