public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* Re: [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function()
@ 2009-04-19 17:37 Prerna Saxena
  2009-04-19 17:51 ` [RFC][Revised Patch 1/5] " Prerna Saxena
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 17:37 UTC (permalink / raw)
  To: systemtap

Here's the revised set of patches.

Frank Ch. Eigler wrote:
> 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
>   
Done.
> - 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
>   
Changed code to implement "stap_dwarfless_probe->pp" & 
"stap_dwarfless_probe->symbol_name" as a char[] only , instead of 
allowing a choice between char* & char[]  implementation.
> - initialization of the new systemtap_session field
>   
Thanks.....dunno how I'd missed this one :-)
> - adding test cases, documentation, NEWS blurb
>   
I've added one testcase in systemtap.base for probe kprobe.function().
> To what extent does the kernel's symbolic kprobe logic allow probes to
> be placed within modules? 
As pointed by Ananth, a kprobe.function("") construct can be used to 
probe module functions too, since it searches modules if the said symbol 
wasnt found in the kernel. However, in the event the probed function 
name is present in more than one modules, the probe point gets 
registered for first instance of the function.  ( which may or may not 
be the desired probe point) .

Probing module functions can be accomplished using this separate construct :
    probe kprobe.module("module_name").function("function_name")
>  Would it be worthwhile to allow numeric
> probe addresses (as in kernel.statement(0xaddr).absolute)?
>
>   
Thanks for the suggestion :-)
This is implemented as :
    probe kprobe.statement(ADDRESS).absolute
This needs to be run in privileged mode , just like kernel.statement() 
probes  

> - FChE
>   
Regards,

-- 
Prerna Saxena

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


-- 
Prerna Saxena

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

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

* Re: [RFC][Revised Patch 1/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
@ 2009-04-19 17:51 ` Prerna Saxena
  2009-04-19 18:00 ` [RFC][Revised Patch 2/5] " Prerna Saxena
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 17:51 UTC (permalink / raw)
  To: systemtap; +Cc: Frank Ch. Eigler

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

This patch describes changes to tapsets.cxx for introducing probes :  
kprobe.function, kprobe.module().function(), kprobe.statement().absolute

-- 
Prerna Saxena

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


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

Index: git-24-mar/tapsets.cxx
===================================================================
--- git-24-mar.orig/tapsets.cxx
+++ git-24-mar/tapsets.cxx
@@ -2649,7 +2649,38 @@ 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,
+			int64_t stmt_addr,
+			bool has_return,
+			bool has_statement
+			);
+  string symbol_name;
+  Dwarf_Addr addr;
+  bool has_return;
+  bool has_statement;
+  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 +4374,6 @@ struct dwarf_var_expanding_visitor: publ
 };
 
 
-
 unsigned var_expanding_visitor::tick = 0;
 
 void
@@ -5360,6 +5390,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 +5489,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 +6228,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 +7782,402 @@ 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,
+					    int64_t stmt_addr,
+					    bool if_return,
+					    bool if_statement
+):
+  derived_probe (base, location),
+  symbol_name (name), addr (stmt_addr),
+  has_return (if_return), has_statement (if_statement)
+{
+  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() << "const unsigned statement_p:1;";
+  s.op->newline() << "unsigned registered_p:1;";
+  s.op->newline() << "const unsigned short maxactive_val;";
+
+  // Function Names are mostly 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;
+  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
+    }
+
+#define CALCIT(var)                                                     \
+	s.op->newline() << "const char " << #var << "[" << var##_name_max << "] ;";
+
+  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 << ",";
+        }
+      if (p->has_statement)
+	{
+          s.op->line() << " .statement_p=1,";
+	  s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
+          s.op->line() << " .symbol_string=\"" <<  "\",";
+	}
+      else
+	{
+	  s.op->line() << " .address=(unsigned long)0x" << hex << 0 << dec << "ULL,";
+          s.op->line() << " .symbol_string=\"" << p->symbol_name << "\",";
+	}
+
+      s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
+      s.op->line() << " .ph=&" << p->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)
+{
+#define CHECK_STMT(var)						\
+  s.op->newline() << "if (sdp->statement_p) {";			\
+  s.op->newline() << var << ".symbol_name = NULL;";		\
+  s.op->newline() << "} else {";				\
+  s.op->newline() << var << ".symbol_name = sdp->symbol_string;";	\
+  s.op->newline() << "}";
+
+  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 = sdp->address;";
+  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;";
+  CHECK_STMT("kp->u.krp.kp");
+  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.pre_handler = NULL;";
+  s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
+  CHECK_STMT("kp->dummy");
+  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;";
+  CHECK_STMT("kp->u.kp");
+  s.op->newline(1) << "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;";
+  CHECK_STMT("kp->dummy");
+  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 OR addr = %p, rc = %d \", sdp->symbol_string, sdp->address, rc);";
+  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
+#undef CHECK_STMT
+}
+
+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, module_string_val;
+  int64_t statement_num_val = 0;
+  bool has_function_str, has_module_str, has_statement_num, has_absolute, has_return;
+
+  has_function_str = this->get_param(parameters, TOK_FUNCTION, function_string_val);
+  has_module_str = this->get_param(parameters, TOK_MODULE, module_string_val);
+  has_return = this->has_null_param (parameters, TOK_RETURN);
+  has_statement_num = this->get_param(parameters, TOK_STATEMENT, statement_num_val);
+  has_absolute = this->has_null_param (parameters, TOK_ABSOLUTE);
+
+  if ( has_function_str )
+	{
+	  if ( has_module_str )
+	  	function_string_val = module_string_val + ":" + function_string_val;
+          finished_results.push_back ( new kprobe_derived_probe ( base,
+						location, function_string_val,
+						0, has_return,
+						has_statement_num) );
+	}
+  else
+	{
+	  // assert guru mode for absolute probes
+	  if ( has_statement_num && has_absolute && !base->privileged )
+        	  throw semantic_error ("absolute statement probe in unprivileged script", base->tok);
+
+	  finished_results.push_back(new kprobe_derived_probe ( base,
+						location,"",
+						statement_num_val, has_return,
+						has_statement_num));
+	}
+}
 // ------------------------------------------------------------------------
 // timer derived probes
 // ------------------------------------------------------------------------
@@ -10685,6 +11126,10 @@ perfmon_derived_probe_group::emit_module
 }
 #endif
 
+// ------------------------------------------------------------------------
+//   kprobes-based probes,which postpone symbol resolution until runtime.
+// ------------------------------------------------------------------------
+
 
 // ------------------------------------------------------------------------
 //  Standard tapset registry.
@@ -10779,6 +11224,18 @@ 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());
+  s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
+     ->bind_str(TOK_FUNCTION)->bind(new kprobe_builder());
+  s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
+     ->bind(new kprobe_builder());
+  s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
+     ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)->bind(new kprobe_builder());
+  s.pattern_root->bind(TOK_KPROBE)->bind_num(TOK_STATEMENT)
+      ->bind(TOK_ABSOLUTE)->bind(new kprobe_builder());
 }
 
 
@@ -10801,6 +11258,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] 8+ messages in thread

* Re: [RFC][Revised Patch 2/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
  2009-04-19 17:51 ` [RFC][Revised Patch 1/5] " Prerna Saxena
@ 2009-04-19 18:00 ` Prerna Saxena
  2009-04-19 18:02 ` [RFC][Revised Patch 3/5] " Prerna Saxena
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 18:00 UTC (permalink / raw)
  To: systemtap; +Cc: Frank Ch. Eigler

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

This patch addresses changes to class systemtap_session to include new 
probe group "kprobe_derived_probe_group".

-- 
Prerna Saxena

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


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

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;
Index: git-24-mar/elaborate.cxx
===================================================================
--- git-24-mar.orig/elaborate.cxx
+++ git-24-mar/elaborate.cxx
@@ -1441,6 +1441,7 @@ systemtap_session::systemtap_session ():
   user_file (0),
   be_derived_probes(0),
   dwarf_derived_probes(0),
+  kprobe_derived_probes(0),
   uprobe_derived_probes(0),
   utrace_derived_probes(0),
   itrace_derived_probes(0),

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

* Re: [RFC][Revised Patch 3/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
  2009-04-19 17:51 ` [RFC][Revised Patch 1/5] " Prerna Saxena
  2009-04-19 18:00 ` [RFC][Revised Patch 2/5] " Prerna Saxena
@ 2009-04-19 18:02 ` Prerna Saxena
  2009-04-21  3:34   ` Ananth N Mavinakayanahalli
  2009-04-19 18:09 ` [RFC][Revised Patch 4/5] " Prerna Saxena
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 18:02 UTC (permalink / raw)
  To: systemtap; +Cc: Frank Ch. Eigler

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

Additions to testsuite to test probe "kprobe"

-- 
Prerna Saxena

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


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

Index: git-19-apr/testsuite/systemtap.base/kprobes.exp
===================================================================
--- /dev/null
+++ git-19-apr/testsuite/systemtap.base/kprobes.exp
@@ -0,0 +1,2 @@
+set test "kprobes"
+stap_run $srcdir/$subdir/$test.stp
Index: git-19-apr/testsuite/systemtap.base/kprobes.stp
===================================================================
--- /dev/null
+++ git-19-apr/testsuite/systemtap.base/kprobes.stp
@@ -0,0 +1,27 @@
+/*
+ * kprobes.stp
+ *
+ * Probe to test the functionality of kprobe-based probes
+ *
+ * (Dwarfless probing)
+ *
+ */
+global count
+
+probe begin
+{
+        println("systemtap starting probe")
+}
+
+probe kprobe.function("sys_open")
+{
+        printf("\n Probe point hit");
+ 	exit();
+}
+
+probe end
+{
+        println("systemtap ending probe")
+        println("count = " . sprint(count));
+}
+

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

* Re: [RFC][Revised Patch 4/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
                   ` (3 preceding siblings ...)
  2009-04-19 18:09 ` [RFC][Revised Patch 4/5] " Prerna Saxena
@ 2009-04-19 18:09 ` Prerna Saxena
  2009-04-19 18:10 ` [RFC][Revised Patch 5/5] " Prerna Saxena
  5 siblings, 0 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 18:09 UTC (permalink / raw)
  To: systemtap; +Cc: Frank Ch. Eigler

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

Documentation updates

-- 
Prerna Saxena

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


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

Index: git-19-apr/stapprobes.3stap.in
===================================================================
--- git-19-apr.orig/stapprobes.3stap.in
+++ git-19-apr/stapprobes.3stap.in
@@ -64,6 +64,7 @@ syscall.*
 kernel.function("no_such_function") ?
 module("awol").function("no_such_function") !
 signal.*? if (switch)
+kprobe.function("foo")
 .ESAMPLE
 
 
@@ -378,6 +379,40 @@ Other local variables are not generally 
 a ".return" probe hits, the probed function will have already returned.
 
 
+.SS DWARFLESS
+In absence of debugging information, entry & exit points of kernel & module
+functions can be probed using the "kprobe" family of probes.
+However, these do not permit looking up the arguments / local variables
+of the function.
+Following constructs are supported :
+.SAMPLE
+kprobe.function(FUNCTION)
+kprobe.function(FUNCTION).return
+kprobe.module(NAME).function(FUNCTION)
+kprobe.module(NAME).function(FUNCTION).return
+kprobe.statement.(ADDRESS).absolute
+.ESAMPLE
+.PP
+Probes of type
+.B function
+are recommended for kernel functions, whereas probes of type
+.B module
+are recommended for probing functions of the specified module.
+In case the absolute address of a kernel or module function is known,
+.B statement
+probes can be utilized.
+.PP
+Note that
+.I FUNCTION
+and
+.I MODULE
+names
+.B must not
+contain wildcards, or the probe will not be registered.
+Also, statement probes must be run under guru-mode only.
+
+
+
 .SS USER-SPACE
 Early prototype support for user-space probing is available in the
 form of a non-symbolic probe point:

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

* Re: [RFC][Revised Patch 4/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
                   ` (2 preceding siblings ...)
  2009-04-19 18:02 ` [RFC][Revised Patch 3/5] " Prerna Saxena
@ 2009-04-19 18:09 ` Prerna Saxena
  2009-04-19 18:09 ` Prerna Saxena
  2009-04-19 18:10 ` [RFC][Revised Patch 5/5] " Prerna Saxena
  5 siblings, 0 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 18:09 UTC (permalink / raw)
  To: systemtap

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

Documentation updates

-- 
Prerna Saxena

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


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

Index: git-19-apr/stapprobes.3stap.in
===================================================================
--- git-19-apr.orig/stapprobes.3stap.in
+++ git-19-apr/stapprobes.3stap.in
@@ -64,6 +64,7 @@ syscall.*
 kernel.function("no_such_function") ?
 module("awol").function("no_such_function") !
 signal.*? if (switch)
+kprobe.function("foo")
 .ESAMPLE
 
 
@@ -378,6 +379,40 @@ Other local variables are not generally 
 a ".return" probe hits, the probed function will have already returned.
 
 
+.SS DWARFLESS
+In absence of debugging information, entry & exit points of kernel & module
+functions can be probed using the "kprobe" family of probes.
+However, these do not permit looking up the arguments / local variables
+of the function.
+Following constructs are supported :
+.SAMPLE
+kprobe.function(FUNCTION)
+kprobe.function(FUNCTION).return
+kprobe.module(NAME).function(FUNCTION)
+kprobe.module(NAME).function(FUNCTION).return
+kprobe.statement.(ADDRESS).absolute
+.ESAMPLE
+.PP
+Probes of type
+.B function
+are recommended for kernel functions, whereas probes of type
+.B module
+are recommended for probing functions of the specified module.
+In case the absolute address of a kernel or module function is known,
+.B statement
+probes can be utilized.
+.PP
+Note that
+.I FUNCTION
+and
+.I MODULE
+names
+.B must not
+contain wildcards, or the probe will not be registered.
+Also, statement probes must be run under guru-mode only.
+
+
+
 .SS USER-SPACE
 Early prototype support for user-space probing is available in the
 form of a non-symbolic probe point:

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

* Re: [RFC][Revised Patch 5/5] New Probe family : probe kprobe.function()
  2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
                   ` (4 preceding siblings ...)
  2009-04-19 18:09 ` Prerna Saxena
@ 2009-04-19 18:10 ` Prerna Saxena
  5 siblings, 0 replies; 8+ messages in thread
From: Prerna Saxena @ 2009-04-19 18:10 UTC (permalink / raw)
  To: systemtap; +Cc: Frank Ch. Eigler

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

NEWS updates

-- 
Prerna Saxena

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


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

Index: git-19-apr/NEWS
===================================================================
--- git-19-apr.orig/NEWS
+++ git-19-apr/NEWS
@@ -10,6 +10,12 @@
   Such accesses can originate from $context expressions fueled by
   erroneous debug data, or by kernel_{long,string,...}() tapset calls.
 
+- New probes kprobe.function(FUNCTION) and kprobe.function(FUNCTION).return
+  for dwarfless probing. These postpone function address resolution to
+  run-time and use the kprobe symbol-resolution mechanism.
+  Probing of absolute statements can be done using the
+  kprobe.statement(ADDRESS).absolute construct.
+
 * What's new in version 0.9.5
 
 - New probes process().insn and process().insn.block that allows

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

* Re: [RFC][Revised Patch 3/5] New Probe family : probe  kprobe.function()
  2009-04-19 18:02 ` [RFC][Revised Patch 3/5] " Prerna Saxena
@ 2009-04-21  3:34   ` Ananth N Mavinakayanahalli
  0 siblings, 0 replies; 8+ messages in thread
From: Ananth N Mavinakayanahalli @ 2009-04-21  3:34 UTC (permalink / raw)
  To: Prerna Saxena; +Cc: systemtap, fche

On Sun, Apr 19, 2009 at 11:34:24PM +0530, Prerna Saxena wrote:

Hi Prerna,

> +/*
> + * kprobes.stp
> + *
> + * Probe to test the functionality of kprobe-based probes
> + *
> + * (Dwarfless probing)
> + *
> + */
> +global count
> +
> +probe begin
> +{
> +        println("systemtap starting probe")
> +}
> +
> +probe kprobe.function("sys_open")

This is a red herring for SYSCALL_WRAPPER architectures. Can you please
choose a different function? vfs_read?

> +{
> +        printf("\n Probe point hit");
> + 	exit();

And you don't really update the count here.

Ananth

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

end of thread, other threads:[~2009-04-21  3:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-19 17:37 [RFC][Revised Patch 0/5] New Probe family : probe kprobe.function() Prerna Saxena
2009-04-19 17:51 ` [RFC][Revised Patch 1/5] " Prerna Saxena
2009-04-19 18:00 ` [RFC][Revised Patch 2/5] " Prerna Saxena
2009-04-19 18:02 ` [RFC][Revised Patch 3/5] " Prerna Saxena
2009-04-21  3:34   ` Ananth N Mavinakayanahalli
2009-04-19 18:09 ` [RFC][Revised Patch 4/5] " Prerna Saxena
2009-04-19 18:09 ` Prerna Saxena
2009-04-19 18:10 ` [RFC][Revised Patch 5/5] " Prerna Saxena

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).