summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-03-20 09:35:44 +0100
committerMark Wielaard <mjw@redhat.com>2009-03-20 09:35:44 +0100
commit9ba817408c6eb81d9ed470314cff1d2d412c4b68 (patch)
tree81cdd381dc4a9c8007102ce4465a7a2c6c016a4e /tapsets.cxx
parent5e94ef56760c087784e485c35521a6e438cfc3e5 (diff)
parent0cf9ea606eb7677a1241595f7568dd4a6c243ef2 (diff)
downloadsystemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.tar.gz
systemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.tar.xz
systemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.zip
Merge branch 'master' into pr6866
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx128
1 files changed, 86 insertions, 42 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 89e011c4..d7b55e33 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3521,9 +3521,17 @@ dwarf_query::blacklisted_p(const string& funcname,
if (! (goodfn && goodfile))
{
- if (sess.verbose>1)
- clog << " skipping - blacklisted";
- return true;
+ if (sess.guru_mode)
+ {
+ if (sess.verbose>1)
+ clog << " guru mode enabled - ignoring blacklist";
+ }
+ else
+ {
+ if (sess.verbose>1)
+ clog << " skipping - blacklisted";
+ return true;
+ }
}
// This probe point is not blacklisted.
@@ -5059,7 +5067,8 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
// cast_op to the next pass. We hope that this value ends
// up not being referenced after all, so it can be optimized out
// quietly.
- semantic_error* er = new semantic_error ("type definition not found", e->tok);
+ string msg = "type definition '" + e->type + "' not found";
+ semantic_error* er = new semantic_error (msg, e->tok);
// NB: we can have multiple errors, since a @cast
// may be expanded in several different contexts:
// function ("*") { @cast(...) }
@@ -6240,6 +6249,9 @@ task_finder_derived_probe_group::emit_module_exit (systemtap_session& s)
// ------------------------------------------------------------------------
+static string TOK_INSN("insn");
+static string TOK_BLOCK("block");
+
struct itrace_derived_probe: public derived_probe
{
bool has_path;
@@ -6314,7 +6326,7 @@ struct itrace_builder: public derived_probe_builder
// XXX: PR 6445 needs !has_path && !has_pid support
assert (has_path || has_pid);
- single_step = 1;
+ single_step = ! has_null_param (parameters, TOK_BLOCK);
// If we have a path, we need to validate it.
if (has_path)
@@ -9269,10 +9281,10 @@ mark_builder::build(systemtap_session & sess,
struct tracepoint_arg
{
- string name, c_type;
- bool used, isptr;
+ string name, c_type, typecast;
+ bool usable, used, isptr;
Dwarf_Die type_die;
- tracepoint_arg(): used(false), isptr(false) {}
+ tracepoint_arg(): usable(false), used(false), isptr(false) {}
};
struct tracepoint_derived_probe: public derived_probe
@@ -9324,7 +9336,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
// search for a tracepoint parameter matching this name
tracepoint_arg *arg = NULL;
for (unsigned i = 0; i < args.size(); ++i)
- if (args[i].name == argname)
+ if (args[i].usable && args[i].name == argname)
{
arg = &args[i];
arg->used = true;
@@ -9372,6 +9384,9 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
if (lvalue && (!dw.sess.guru_mode || e->components.empty()))
throw semantic_error("write to tracepoint variable '" + e->base_name
+ "' not permitted", e->tok);
+ // XXX: if a struct/union arg is passed by value, then writing to its fields
+ // is also meaningless until you dereference past a pointer member. It's
+ // harder to detect and prevent that though...
if (e->components.empty())
{
@@ -9543,6 +9558,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
for (unsigned i = 0; i < args.size(); ++i)
{
+ if (!args[i].usable)
+ continue;
if (i > 0)
pf->raw_components += " ";
pf->raw_components += args[i].name;
@@ -9625,32 +9642,39 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s,
static bool
dwarf_type_name(Dwarf_Die& type_die, string& c_type)
{
- // if this die has a direct name, then we're done
- const char *diename = dwarf_diename_integrate(&type_die);
- if (diename != NULL)
+ // if we've gotten down to a basic type, then we're done
+ bool done = true;
+ switch (dwarf_tag(&type_die))
{
- switch (dwarf_tag(&type_die))
- {
- case DW_TAG_structure_type:
- c_type.append("struct ");
- break;
- case DW_TAG_union_type:
- c_type.append("union ");
- break;
- }
- c_type.append(diename);
+ case DW_TAG_structure_type:
+ c_type.append("struct ");
+ break;
+ case DW_TAG_union_type:
+ c_type.append("union ");
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ break;
+ default:
+ done = false;
+ break;
+ }
+ if (done)
+ {
+ c_type.append(dwarf_diename_integrate(&type_die));
return true;
}
// otherwise, this die is a type modifier.
// recurse into the referent type
+ // if it can't be named, just call it "void"
Dwarf_Attribute subtype_attr;
Dwarf_Die subtype_die;
if (!dwarf_attr_integrate(&type_die, DW_AT_type, &subtype_attr)
|| !dwarf_formref_die(&subtype_attr, &subtype_die)
|| !dwarf_type_name(subtype_die, c_type))
- return false;
+ c_type = "void";
const char *suffix = NULL;
switch (dwarf_tag(&type_die))
@@ -9671,33 +9695,47 @@ dwarf_type_name(Dwarf_Die& type_die, string& c_type)
return false;
}
c_type.append(suffix);
+
+ // XXX HACK! The va_list isn't usable as found in the debuginfo...
+ if (c_type == "struct __va_list_tag*")
+ c_type = "va_list";
+
return true;
}
static bool
-resolve_tracepoint_arg_type(Dwarf_Die& type_die, bool& isptr)
+resolve_tracepoint_arg_type(tracepoint_arg& arg)
{
Dwarf_Attribute type_attr;
- switch (dwarf_tag(&type_die))
+ switch (dwarf_tag(&arg.type_die))
{
case DW_TAG_typedef:
case DW_TAG_const_type:
case DW_TAG_volatile_type:
// iterate on the referent type
- return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &type_die)
- && resolve_tracepoint_arg_type(type_die, isptr));
+ return (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
+ && dwarf_formref_die(&type_attr, &arg.type_die)
+ && resolve_tracepoint_arg_type(arg));
case DW_TAG_base_type:
// base types will simply be treated as script longs
- isptr = false;
+ arg.isptr = false;
return true;
case DW_TAG_pointer_type:
- // pointers can be either script longs,
- // or dereferenced with their referent type
- isptr = true;
- return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &type_die));
+ // pointers can be treated as script longs,
+ // and if we know their type, they can also be dereferenced
+ if (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
+ && dwarf_formref_die(&type_attr, &arg.type_die))
+ arg.isptr = true;
+ arg.typecast = "(intptr_t)";
+ return true;
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ // for structs/unions which are passed by value, we turn it into
+ // a pointer that can be dereferenced.
+ arg.isptr = true;
+ arg.typecast = "(intptr_t)&";
+ return true;
default:
// should we consider other types too?
return false;
@@ -9721,12 +9759,12 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die)
Dwarf_Attribute type_attr;
if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr)
|| !dwarf_formref_die (&type_attr, &tparg.type_die)
- || !dwarf_type_name(tparg.type_die, tparg.c_type)
- || !resolve_tracepoint_arg_type(tparg.type_die, tparg.isptr))
+ || !dwarf_type_name(tparg.type_die, tparg.c_type))
throw semantic_error ("cannot get type of tracepoint '"
+ tracepoint_name + "' parameter '"
+ tparg.name + "'");
+ tparg.usable = resolve_tracepoint_arg_type(tparg);
args.push_back(tparg);
if (sess.verbose > 4)
clog << "found parameter for tracepoint '" << tracepoint_name
@@ -9739,8 +9777,9 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die)
void
tracepoint_derived_probe::printargs(std::ostream &o) const
{
- for (unsigned i = 0; i < args.size(); ++i)
- o << " $" << args[i].name << ":" << args[i].c_type;
+ for (unsigned i = 0; i < args.size(); ++i)
+ if (args[i].usable)
+ o << " $" << args[i].name << ":" << args[i].c_type;
}
void
@@ -9778,6 +9817,8 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
// don't provide any sort of context pointer.
s.op->newline() << "#include <" << p->header << ">";
s.op->newline() << "static void enter_tracepoint_probe_" << i << "(";
+ if (p->args.size() == 0)
+ s.op->line() << "void";
for (unsigned j = 0; j < p->args.size(); ++j)
{
if (j > 0)
@@ -9796,8 +9837,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
{
s.op->newline() << "c->locals[0]." << p->name << ".__tracepoint_arg_"
<< p->args[j].name << " = (int64_t)";
- if (p->args[j].isptr)
- s.op->line() << "(intptr_t)";
+ s.op->line() << p->args[j].typecast;
s.op->line() << "__tracepoint_arg_" << p->args[j].name << ";";
}
s.op->newline() << p->name << " (c);";
@@ -10812,9 +10852,13 @@ register_standard_tapsets(systemtap_session & s)
->bind(new utrace_builder ());
// itrace user-space probes
- s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace")
+ s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
+ ->bind(new itrace_builder ());
+ s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
+ ->bind(new itrace_builder ());
+ s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
->bind(new itrace_builder ());
- s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace")
+ s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
->bind(new itrace_builder ());
// marker-based parts