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);
};
}
+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)
{
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) << "};";
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);";
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);
};
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) {}
}
-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)
{
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())
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) << "}";
- }
}
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;
}
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;