]> sourceware.org Git - systemtap.git/commitdiff
Change python probe generation to derive synthetic procfs probes.
authorDavid Smith <dsmith@redhat.com>
Thu, 20 Oct 2016 17:20:15 +0000 (12:20 -0500)
committerDavid Smith <dsmith@redhat.com>
Thu, 20 Oct 2016 17:20:15 +0000 (12:20 -0500)
* tapset-python.cxx (python_builder::build): Derive synthetic procfs
  probes that contain probe information.
  (python_derived_probe_group::emit_module_decls): No longer reuse procfs
  probe buffer machinery.
  (python_derived_probe_group::emit_kernel_module_init):
  Removed unneeded function.
  (python_derived_probe_group::emit_kernel_module_exit): Ditto.
  (python_derived_probe_group::emit_module_init): Ditto.
  (python_derived_probe_group::emit_module_exit): Ditto.
* elaborate.h (derived_probe): Add use_internal_buffer() virtual
  function.
* tapset-procfs.cxx (procfs_derived_probe::use_internal_buffer): New
  function.
  (procfs_derived_probe_group::emit_module_decls): If we're using an
  internal buffer instead of user-generated content, output code
  accordingly.
  (procfs_derived_probe_group::emit_module_init): Ditto.
* tapsets.cxx (all_session_groups): Set up python probes before procfs
  probes.

elaborate.h
tapset-procfs.cxx
tapset-python.cxx
tapsets.cxx

index 50e933ab09de49f16f4c560ddb0e028e7f471f52..a7b4d56a515959f598d156c2c38b185e151cd584 100644 (file)
@@ -236,6 +236,8 @@ public:
   // List of other derived probes whose conditions may be affected by
   // this probe.
   std::set<derived_probe*> probes_with_affected_conditions;
+
+  virtual void use_internal_buffer(const std::string&) {}
 };
 
 // ------------------------------------------------------------------------
index d9367cb82f8b3040d48dcfe915868133093b7a4f..f0f1d7fc1f54e34ab8728d9c63f0a061fbbf7f9b 100644 (file)
@@ -40,10 +40,15 @@ struct procfs_derived_probe: public derived_probe
   bool target_symbol_seen;
   int64_t maxsize_val;
   int64_t umask; 
+  string variable_name;
 
 
   procfs_derived_probe (systemtap_session &, probe* p, probe_point* l, string ps, bool w, int64_t m, int64_t umask); 
   void join_group (systemtap_session& s);
+
+  // Set up this procfs probe to use a static C variable as input
+  // instead using the probe body.
+  void use_internal_buffer(const std::string& var);
 };
 
 
@@ -122,6 +127,15 @@ procfs_derived_probe::join_group (systemtap_session& s)
 }
 
 
+void
+procfs_derived_probe::use_internal_buffer(const std::string& var)
+{
+    // We're going to mangle this procfs probe to read from an
+    // internal buffer instead of executing the probe body.
+    variable_name = var;
+}
+
+
 void
 procfs_derived_probe_group::enroll (procfs_derived_probe* p)
 {
@@ -226,30 +240,46 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
       s.op->newline() << "{";
       s.op->line() << " .path=" << lex_cast_qstring (it->first) << ",";
 
-      if (pset->read_probe != NULL)
-        s.op->line() << " .read_probe=" << common_probe_init (pset->read_probe) << ",";
-
-      if (pset->write_probe != NULL)
-        s.op->line() << " .write_probe=" << common_probe_init (pset->write_probe) << ",";
-
-      s.op->line() << " .buffer=stap_procfs_probe_buffers.buf_" << buf_index++ << ",";
-      if (pset->read_probe != NULL)
-       {
-         if (pset->read_probe->maxsize_val == 0)
-           s.op->line() << " .bufsize=STP_PROCFS_BUFSIZE,";
-         else
-           s.op->line() << " .bufsize="
-                        << pset->read_probe->maxsize_val << ",";
+      if (pset->read_probe && !pset->read_probe->variable_name.empty())
+        {
+         s.op->line() << " .buffer=(char *)"
+                      << pset->read_probe->variable_name << ",";
+         s.op->line() << " .bufsize=sizeof("
+                      << pset->read_probe->variable_name << "),";
+         s.op->line() << " .count=(sizeof("
+                      << pset->read_probe->variable_name << ") - 1),";
+         s.op->line() << " .permissions=0444,";
        }
       else
-       s.op->line() << " .bufsize=MAXSTRINGLEN,";
-
-       s.op->line() << " .permissions=" << (((pset->read_probe ? 0444 : 0) 
-                                        | (pset->write_probe ? 0222 : 0)) &~ 
-                                          ((pset->read_probe ? pset->read_probe->umask : 0) 
-                                        | (pset->write_probe ? pset->write_probe->umask : 0))) 
-                                       << ",";
-
+        {
+         if (pset->read_probe != NULL)
+           s.op->line() << " .read_probe="
+                        << common_probe_init (pset->read_probe) << ",";
+
+         if (pset->write_probe != NULL)
+           s.op->line() << " .write_probe=" 
+                        << common_probe_init (pset->write_probe) << ",";
+
+         s.op->line() << " .buffer=stap_procfs_probe_buffers.buf_"
+                      << buf_index++ << ",";
+         if (pset->read_probe != NULL)
+           {
+             if (pset->read_probe->maxsize_val == 0)
+               s.op->line() << " .bufsize=STP_PROCFS_BUFSIZE,";
+             else
+               s.op->line() << " .bufsize="
+                            << pset->read_probe->maxsize_val << ",";
+           }
+         else
+           s.op->line() << " .bufsize=MAXSTRINGLEN,";
+
+         s.op->line() << " .permissions="
+                      << (((pset->read_probe ? 0444 : 0) 
+                           | (pset->write_probe ? 0222 : 0)) &~ 
+                          ((pset->read_probe ? pset->read_probe->umask : 0) 
+                           | (pset->write_probe ? pset->write_probe->umask : 0))) 
+                      << ",";
+       }
       s.op->line() << " },";
     }
   s.op->newline(-1) << "};";
@@ -367,8 +397,10 @@ procfs_derived_probe_group::emit_module_init (systemtap_session& s)
 
   s.op->newline() << "if (spp->read_probe)";
   s.op->newline(1) << "probe_point = spp->read_probe->pp;";
-  s.op->newline(-1) << "else";
+  s.op->newline(-1) << "else if (spp->write_probe)";
   s.op->newline(1) << "probe_point = spp->write_probe->pp;";
+  s.op->newline(-1) << "else";
+  s.op->newline(1) << "probe_point = \"internal buffer\";";
   s.op->indent(-1);
 
   s.op->newline() << "_spp_init(spp);";
index 3f82759d8750809ab86cd7ad0d7c327e842b2a7e..a66e82b1d209c23c5434e0aae616e79871ca08de 100644 (file)
@@ -69,11 +69,7 @@ public:
   python_derived_probe_group () {}
 
   void enroll (python_derived_probe* probe);
-  void emit_kernel_module_init (systemtap_session& s);
-  void emit_kernel_module_exit (systemtap_session& s);
   void emit_module_decls (systemtap_session& s);
-  void emit_module_init (systemtap_session& s);
-  void emit_module_exit (systemtap_session& s);
 };
 
 
@@ -85,21 +81,26 @@ private:
              interned_string module,
              interned_string function,
              vector<python_probe_info *> &results);
-  bool python2_procfs_probe_derived_p;
-  bool python3_procfs_probe_derived_p;
+
+  // python2 related synthetic probes
+  derived_probe* python2_procfs_probe;
   probe* python2_call_probe;
   probe* python2_line_probe;
   probe* python2_return_probe;
+
+  // python3 related synthetic probes
+  derived_probe* python3_procfs_probe;
+  probe* python3_procfs_probe;
   probe* python3_call_probe;
   probe* python3_line_probe;
   probe* python3_return_probe;
 
 public:
-  python_builder() : python2_procfs_probe_derived_p(false),
-                    python3_procfs_probe_derived_p(false),
+  python_builder() : python2_procfs_probe(NULL),
                     python2_call_probe(NULL),
                     python2_line_probe(NULL),
                     python2_return_probe(NULL),
+                    python3_procfs_probe(NULL),
                     python3_call_probe(NULL),
                     python3_line_probe(NULL),
                     python3_return_probe(NULL) {}
@@ -170,33 +171,6 @@ python_derived_probe_group::enroll (python_derived_probe* p)
 }
 
 
-void
-python_derived_probe_group::emit_kernel_module_init (systemtap_session& s)
-{
-  if (python2_probes.empty() && python3_probes.empty())
-    return;
-  // Note that we're OK here, since _stp_mkdir_proc_module() can be
-  // called twice without issue (in case the script also contains real
-  // procfs probes).
-  s.op->newline() << "rc = _stp_mkdir_proc_module();";
-}
-
-
-void
-python_derived_probe_group::emit_kernel_module_exit (systemtap_session& s)
-{
-  if (python2_probes.empty() && python3_probes.empty())
-    return;
-
-  // If we're using the original transport, it uses the
-  // '/proc/systemtap/{module_name}' directory to store control
-  // files. Let the transport layer clean up that directory.
-  s.op->newline() << "#if (STP_TRANSPORT_VERSION != 1)";
-  s.op->newline() << "_stp_rmdir_proc_module();";
-  s.op->newline() << "#endif";
-}
-
-
 void
 python_derived_probe_group::emit_module_decls (systemtap_session& s)
 {
@@ -205,25 +179,6 @@ python_derived_probe_group::emit_module_decls (systemtap_session& s)
 
   s.op->newline();
   s.op->newline() << "/* ---- python probes ---- */";
-  // We're reusing the procfs probe buffer machinery.
-  s.op->newline() << "#include \"procfs.c\"";
-  s.op->newline() << "#include \"procfs-probes.c\"";
-
-  // The procfs probe buffer machinery emits 2 functions. We're not
-  // going to use them, but runtime/procfs-probes.c wants a definition
-  // of them. So, if we don't have any procfs probes, we'll have to
-  // emit those functions ourselves.
-  if (!s.runtime_usermode_p() && s.procfs_derived_probes == NULL)
-    {
-      s.op->newline() << "static int _stp_proc_fill_read_buffer(struct stap_procfs_probe *spp) {";
-      s.op->indent(1);
-      s.op->newline() << "return 0;";
-      s.op->newline(-1) << "}";
-      s.op->newline() << "static int _stp_process_write_buffer(struct stap_procfs_probe *spp, const char __user *buf, size_t count) {";
-      s.op->indent(1);
-      s.op->newline() << "return 0;";
-      s.op->newline(-1) << "}";
-    }  
 
   // Output the probe info buffer.
   if (python2_probes.size())
@@ -250,89 +205,6 @@ python_derived_probe_group::emit_module_decls (systemtap_session& s)
       s.op->line() << ";";
       s.op->indent(-1);
     }
-
-  // Output the procfs file information.
-  s.op->newline() << "static struct stap_procfs_probe stap_python_procfs_probes[] = {";
-  s.op->indent(1);
-  if (python2_probes.size())
-    {
-      s.op->newline() << "{";
-      s.op->line() << " .path=\"_stp_python2_probes\",";
-      s.op->line() << " .buffer=(char *)python2_probe_info,";
-      s.op->line() << " .bufsize=sizeof(python2_probe_info),";
-      s.op->line() << " .count=(sizeof(python2_probe_info) - 1),";
-      s.op->line() << " .permissions=0444,";
-      s.op->line() << " },";
-    }
-  if (python3_probes.size())
-    {
-      s.op->newline() << "{";
-      s.op->line() << " .path=\"_stp_python3_probes\",";
-      s.op->line() << " .buffer=(char *)python3_probe_info,";
-      s.op->line() << " .bufsize=(sizeof(python3_probe_info) - 1),";
-      s.op->line() << " .count=(sizeof(python3_probe_info) - 1),";
-      s.op->line() << " .permissions=0444,";
-      s.op->line() << " },";
-    }
-  s.op->newline(-1) << "};";
-}
-
-
-void
-python_derived_probe_group::emit_module_init (systemtap_session& s)
-{
-  if (python2_probes.empty() && python3_probes.empty())
-    return;
-
-  if (!s.runtime_usermode_p())
-    {
-      // FIXME: We've got a problem here. We need to add code
-      // somewhere so that the user can't create procfs probes
-      // with the same filenames. (If he did, we'd just error out
-      // at startup I believe, so it isn't a real big problem.)
-      s.op->newline() << "for (i = 0; i < ARRAY_SIZE(stap_python_procfs_probes); i++) {";
-      s.op->newline(1) << "struct stap_procfs_probe *spp = &stap_python_procfs_probes[i];";
-
-      // FIXME: This really isn't right, but it is the best we have at
-      // the moment.
-      s.op->newline() << "probe_point = spp->path;";
-
-      s.op->newline() << "_spp_init(spp);";
-      s.op->newline() << "rc = _stp_create_procfs(spp->path, &_stp_proc_fops, spp->permissions, spp);";
-      s.op->newline() << "if (rc) {";
-      s.op->newline(1) << "_stp_close_procfs();";
-
-      // FIXME: The problem here is that if there are any "real"
-      // procfs probes that have already been created,
-      // _stp_close_procfs() above will clean them up, but
-      // _spp_shutdown() won't get called. Now that isn't the end of
-      // the world, since _spp_shutdown() just calls mutex_destroy()
-      // which doesn't do any deallocation.
-      s.op->newline() << "for (i = 0; i < ARRAY_SIZE(stap_python_procfs_probes); i++) {";
-      s.op->newline(1) << "spp = &stap_python_procfs_probes[i];";
-      s.op->newline() << "_spp_shutdown(spp);";
-      s.op->newline(-1) << "}";
-      s.op->newline() << "break;";
-      s.op->newline(-1) << "}";
-      s.op->newline(-1) << "}"; // for loop
-    }
-}
-
-
-void
-python_derived_probe_group::emit_module_exit (systemtap_session& s)
-{
-  if (python2_probes.empty() && python3_probes.empty())
-    return;
-
-  if (!s.runtime_usermode_p())
-    {
-      s.op->newline() << "_stp_close_procfs();";
-      s.op->newline() << "for (i = 0; i < ARRAY_SIZE(stap_python_procfs_probes); i++) {";
-      s.op->newline(1) << "struct stap_procfs_probe *spp = &stap_python_procfs_probes[i];";
-      s.op->newline() << "_spp_shutdown(spp);";
-      s.op->newline(-1) << "}";
-    }
 }
 
 
@@ -457,6 +329,35 @@ python_builder::build(systemtap_session & sess, probe * base,
 
       if (python_version == 2)
         {
+         // Create (if necessary) the python 2 procfs probe which the
+         // HelperSDT python module reads to get probe information.
+         if (python2_procfs_probe == NULL)
+         {
+             stringstream code;
+             const token* tok = base->body->tok;
+
+             // Notice this synthetic probe has no body. That's OK,
+             // since we'll point it at our internal buffer.
+             code << "probe procfs(\"_stp_python2_probes\").read {" << endl;
+             code << "}" << endl;
+             probe *base_probe = parse_synthetic_probe (sess, code, tok);
+             if (!base_probe)
+               throw SEMANTIC_ERROR (_("can't create python2 procfs probe"),
+                                     tok);
+             vector<derived_probe *> results;
+             derive_probes(sess, base_probe, results);
+             if (results.size() != 1)
+                 throw SEMANTIC_ERROR (_F("wrong number of probes derived (%d), should be 1",
+                                          results.size()));
+             python2_procfs_probe = results[0];
+             finished_results.push_back(results[0]);
+             
+             // Now that we've got our procfs derived probe, point it
+             // at our internal buffer that we're going to output in
+             // python_derived_probe_group::emit_module_decls().
+             python2_procfs_probe->use_internal_buffer("python2_probe_info");
+         }
+
          if (has_return && python2_return_probe == NULL)
            {
              stringstream code;
@@ -514,6 +415,35 @@ python_builder::build(systemtap_session & sess, probe * base,
        }
       else
         {
+         // Create (if necessary) the python 3 procfs probe which the
+         // HelperSDT python module reads to get probe information.
+         if (python3_procfs_probe == NULL)
+         {
+             stringstream code;
+             const token* tok = base->body->tok;
+
+             // Notice this synthetic probe has no body. That's OK,
+             // since we'll point it at our internal buffer.
+             code << "probe procfs(\"_stp_python3_probes\").read {" << endl;
+             code << "}" << endl;
+             probe *base_probe = parse_synthetic_probe (sess, code, tok);
+             if (!base_probe)
+               throw SEMANTIC_ERROR (_("can't create python3 procfs probe"),
+                                     tok);
+             vector<derived_probe *> results;
+             derive_probes(sess, base_probe, results);
+             if (results.size() != 1)
+                 throw SEMANTIC_ERROR (_F("wrong number of probes derived (%d), should be 1",
+                                          results.size()));
+             python3_procfs_probe = results[0];
+             finished_results.push_back(results[0]);
+             
+             // Now that we've got our procfs derived probe, point it
+             // at our internal buffer that we're going to output in
+             // python_derived_probe_group::emit_module_decls().
+             python3_procfs_probe->use_internal_buffer("python3_probe_info");
+         }
+
          if (has_return && python3_return_probe == NULL)
            {
              stringstream code;
index 6cf3f858a200405282e5500b3f827c6cf694c9c1..1a795f2eaa990ae1fa02c70fc27add0c634a1441 100644 (file)
@@ -11928,7 +11928,13 @@ all_session_groups(systemtap_session& s)
   DOONE(hwbkpt);
   DOONE(perf);
   DOONE(hrtimer);
+
+  // Another "order is important" item. Python probes create synthetic
+  // procfs probes and the python probes' emit_module_decls() needs to
+  // be called first.
+  DOONE(python);
   DOONE(procfs);
+
   DOONE(netfilter);
 
   // Another "order is important" item.  We want to make sure we
@@ -11937,7 +11943,6 @@ all_session_groups(systemtap_session& s)
   DOONE(utrace);
   DOONE(itrace);
   DOONE(dynprobe);
-  DOONE(python);
   DOONE(task_finder);
 #undef DOONE
   return g;
This page took 0.044137 seconds and 5 git commands to generate.