summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--NEWS5
-rw-r--r--stapprobes.5.in16
-rw-r--r--tapsets.cxx121
-rwxr-xr-xtestsuite/semok/thirtytwo.stp5
5 files changed, 108 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index 397308a7..ac800e8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-08-15 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 6836.
+ * tapsets.cxx (dwarf_var...visit_target_symbol): Show
+ "var=?" for unlocatable variables. Support $$return.
+ Make sure $$parms/etc. work in .return probes too.
+ * testsuite/semok/thirtytwo.stp: New test.
+ * NEWS, stapprobes.5.in: Document them.
+
2008-08-15 Michael Meeks <michael.meeks@novell.com>
* configure.ac: suggest (SUSE) package name for dwfl.
diff --git a/NEWS b/NEWS
index 0cdc2aa3..d6d220a0 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,10 @@
- A formatted string representation of the variables, parameters, or local
variables at a probe point is now supported via the special $$vars,
- $$parms, and $$locals context variables.
+ $$parms, and $$locals context variables, which expand to a string
+ containing a list "var1=0xdead var2=0xbeef var3=?". (Here, var3 exists
+ but is for some reason unavailable.) In return probes only, $$return
+ expands to an empty string for a void function, or "$return=0xf00".
* What's new in version 0.7
diff --git a/stapprobes.5.in b/stapprobes.5.in
index c71f79d3..f1626166 100644
--- a/stapprobes.5.in
+++ b/stapprobes.5.in
@@ -334,6 +334,11 @@ $var\->field
traversal to a structure's field. The indirection operator
may be repeated to follow more levels of pointers.
.TP
+$return
+is available in return probes only for functions that are declared
+with a return value.
+.TP
+.TP
$var[N]
indexes into an array. The index is given with a
literal number.
@@ -344,12 +349,15 @@ sprintf("parm1=%x ... parmN=%x var1=%x ... varN=%x", parm1, ..., parmN,
var1, ..., varN)
.TP
$$locals
-expands to a character string that is equivalent to
-sprintf("var1=%x ... varN=%x", var1, ..., varN)
+expands to a subset of $$vars for only local variables.
.TP
$$parms
-expands to a character string that is equivalent to
-sprintf("parm1=%x ... parmN=%x", parm1, ..., parmN)
+expands to a subset of $$vars for only function parameters.
+.TP
+$$return
+is available in return probes only. It expands to a string that
+is equivalent to sprintf("$return=%x", $return)
+if the probed function has a return value, or else an empty string.
.PP
For ".return" probes, context variables other than the "$return"
value itself are only available for the function call parameters.
diff --git a/tapsets.cxx b/tapsets.cxx
index 664dfb1f..1f7d2555 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -4002,7 +4002,11 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
if (lvalue && !q.sess.guru_mode)
throw semantic_error("write to target variable not permitted", e->tok);
- if (q.has_return && e->base_name != "$return")
+ // See if we need to generate a new probe to save/access function
+ // parameters from a return probe. PR 1382.
+ if (q.has_return
+ && e->base_name != "$return" // not the special return-value variable handled below
+ && e->base_name != "$$return") // nor the other special variable handled below
{
if (lvalue)
throw semantic_error("write to target variable not permitted in .return probes", e->tok);
@@ -4287,7 +4291,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
if (e->base_name == "$$vars"
|| e->base_name == "$$parms"
- || e->base_name == "$$locals")
+ || e->base_name == "$$locals"
+ || (q.has_return && (e->base_name == "$$return")))
{
Dwarf_Die *scopes;
if (dwarf_getscopes_die (scope_die, &scopes) == 0)
@@ -4298,55 +4303,85 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
// Convert $$parms to sprintf of a list of parms and active local vars
// which we recursively evaluate
- token* tmp_tok = new token;
- tmp_tok->type = tok_identifier;
- tmp_tok->content = "sprintf";
- pf->tok = tmp_tok;
+
+ // NB: we synthesize a new token here rather than reusing
+ // e->tok, because print_format::print likes to use
+ // its tok->content.
+ token* pf_tok = new token;
+ pf_tok->location = e->tok->location;
+ pf_tok->type = tok_identifier;
+ pf_tok->content = "sprint";
+
+ pf->tok = pf_tok;
pf->print_to_stream = false;
pf->print_with_format = true;
pf->print_with_delim = false;
pf->print_with_newline = false;
pf->print_char = false;
- Dwarf_Die result;
- if (dwarf_child (&scopes[0], &result) == 0)
- do
- {
- switch (dwarf_tag (&result))
- {
- case DW_TAG_variable:
- if (e->base_name == "$$parms")
- continue;
- break;
- case DW_TAG_formal_parameter:
- if (e->base_name == "$$locals")
- continue;
- break;
-
- default:
- continue;
- }
+ if (q.has_return && (e->base_name == "$$return"))
+ {
+ tsym->tok = e->tok;
+ tsym->base_name = "$return";
+
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ this->visit_target_symbol(tsym); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
+ {
- const char *diename = dwarf_diename (&result);
- token* sym_tok = new token;
- sym_tok->location = e->get_tok()->location;
- sym_tok->type = tok_identifier;
- sym_tok->content = diename;
- tsym->tok = sym_tok;
- tsym->base_name = "$";
- tsym->base_name += diename;
-
- // Ignore any variable that isn't accessible.
- tsym->saved_conversion_error = 0;
- this->visit_target_symbol(tsym); // NB: throws nothing ...
- if (! tsym->saved_conversion_error) // ... but this is how we know it happened.
+ }
+ else
+ {
+ pf->raw_components += "$return";
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(*(expression**)this->targets.top());
+ }
+ }
+ else
+ {
+ // non-.return probe: support $$parms, $$vars, $$locals
+ Dwarf_Die result;
+ if (dwarf_child (&scopes[0], &result) == 0)
+ do
{
- pf->raw_components += diename;
- pf->raw_components += "=%#x ";
- pf->args.push_back(*(expression**)this->targets.top());
+ switch (dwarf_tag (&result))
+ {
+ case DW_TAG_variable:
+ if (e->base_name == "$$parms")
+ continue;
+ break;
+ case DW_TAG_formal_parameter:
+ if (e->base_name == "$$locals")
+ continue;
+ break;
+
+ default:
+ continue;
+ }
+
+ const char *diename = dwarf_diename (&result);
+ tsym->tok = e->tok;
+ tsym->base_name = "$";
+ tsym->base_name += diename;
+
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ this->visit_target_symbol(tsym); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
+ {
+ pf->raw_components += diename;
+ pf->raw_components += "=? ";
+ }
+ else
+ {
+ pf->raw_components += diename;
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(*(expression**)this->targets.top());
+ }
}
- }
- while (dwarf_siblingof (&result, &result) == 0);
+ while (dwarf_siblingof (&result, &result) == 0);
+ }
pf->components = print_format::string_to_components(pf->raw_components);
provide <print_format*> (this, pf);
@@ -4366,7 +4401,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
try
{
- if (q.has_return && e->base_name == "$return")
+ if (q.has_return && (e->base_name == "$return"))
{
ec->code = q.dw.literal_stmt_for_return (scope_die,
addr,
diff --git a/testsuite/semok/thirtytwo.stp b/testsuite/semok/thirtytwo.stp
new file mode 100755
index 00000000..2a69b8cd
--- /dev/null
+++ b/testsuite/semok/thirtytwo.stp
@@ -0,0 +1,5 @@
+#! stap -p2
+
+# PR 6836
+
+probe kernel.function("sys_open").return { log($$return . $$parms) }