From 3bd0d4df7ccfd9afe7771441b26d8baaaf180e29 Mon Sep 17 00:00:00 2001 From: Rajan Arora Date: Wed, 11 Mar 2009 18:44:21 -0400 Subject: PR 7071: Optional $context variables fix * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Substitute erroneous target symbol with literal 0 if session level flag, skip_badvars is set. * session.h (struct systemtap_session): New flag: skip_badvars. * main.cxx: Command line argument --skip-badvars added. * stap.1.in: Entry for new option --skip-badvars. * NEWS: Added blurb for new option now available. * testsuite/semok/badvar.stp: Test case to check added functionality. --- tapsets.cxx | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index b1d0b04e..dce73534 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4842,18 +4842,31 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) } catch (const semantic_error& er) { - // We suppress this error message, and pass the unresolved - // target_symbol to the next pass. We hope that this value ends - // up not being referenced after all, so it can be optimized out - // quietly. - provide (e); - semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines - // NB: we can have multiple errors, since a $target variable - // may be expanded in several different contexts: - // function ("*") { $var } - saveme->chain = e->saved_conversion_error; - e->saved_conversion_error = saveme; + if (!q.sess.skip_badvars) + { + // We suppress this error message, and pass the unresolved + // target_symbol to the next pass. We hope that this value ends + // up not being referenced after all, so it can be optimized out + // quietly. + provide (e); + semantic_error* saveme = new semantic_error (er); // copy it + saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines + // NB: we can have multiple errors, since a $target variable + // may be expanded in several different contexts: + // function ("*") { $var } + saveme->chain = e->saved_conversion_error; + e->saved_conversion_error = saveme; + } + else + { + // Upon user request for ignoring context, the symbol is replaced + // with a literal 0 and a warning message displayed + literal_number* ln_zero = new literal_number (0); + ln_zero->tok = e->tok; + provide (ln_zero); + q.sess.print_warning ("Bad variable being substituted with literal 0", + e->tok); + } delete fdecl; delete ec; return; -- cgit From 139dee87b8824df4d7562a980e886a6e6f0b8308 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Mar 2009 20:07:22 -0700 Subject: Fix @cast module splitting The new semok testcase exposed that the module splitting wasn't properly setting substr boundaries. Instead of passing the end position, it's supposed to pass the number of characters (end - begin). Oops. --- tapsets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index dce73534..7f6ca721 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5017,7 +5017,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) // split the module string by ':' for alternatives size_t mod_begin = mod_end + 1; mod_end = e->module.find(':', mod_begin); - string module = e->module.substr(mod_begin, mod_end); + string module = e->module.substr(mod_begin, mod_end - mod_begin); // NB: This uses '/' to distinguish between kernel modules and userspace, // which means that userspace modules won't get any PATH searching. -- cgit From 96b030fe8a0bb0297d23638e2975a3e9eb2b85b6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 12 Mar 2009 10:11:59 -0700 Subject: Simplify tracepoint registrations Instead of registering tracepoints with the deeply-nested if-tree, which was cluttering the module_init/exit, this now emits normalized reg/unreg functions for each tracepoint probes. Now the module_init/exit can be a simple loop like all of the other probe types. --- tapsets.cxx | 71 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 28 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 7f6ca721..b02e2cce 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9732,12 +9732,15 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) if (probes.empty()) return; - s.op->newline() << "/* ---- tracepointer probes ---- */"; + s.op->newline() << "/* ---- tracepoint probes ---- */"; + s.op->newline(); for (unsigned i = 0; i < probes.size(); ++i) { tracepoint_derived_probe *p = probes[i]; - s.op->newline(); + + // emit a separate entry function for each probe, since tracepoints + // don't provide any sort of context pointer. s.op->newline() << "#include <" << p->header << ">"; s.op->newline() << "static void enter_tracepoint_probe_" << i << "("; for (unsigned j = 0; j < p->args.size(); ++j) @@ -9765,8 +9768,34 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << p->name << " (c);"; common_probe_entryfn_epilogue (s.op); s.op->newline(-1) << "}"; + + // emit normalized registration functions + s.op->newline() << "static int register_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "return register_trace_" << p->tracepoint_name + << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline(-1) << "}"; + s.op->newline() << "static int unregister_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "return unregister_trace_" << p->tracepoint_name + << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline(-1) << "}"; s.op->newline(); } + + // emit an array of registration functions for easy init/shutdown + s.op->newline() << "static struct stap_tracepoint_probe {"; + s.op->newline(1) << "int (*reg)(void);"; + s.op->newline(0) << "int (*unreg)(void);"; + s.op->newline(-1) << "} stap_tracepoint_probes[] = {"; + s.op->indent(1); + for (unsigned i = 0; i < probes.size(); ++i) + { + s.op->newline () << "{"; + s.op->line() << " .reg=®ister_tracepoint_probe_" << i << ","; + s.op->line() << " .unreg=&unregister_tracepoint_probe_" << i; + s.op->line() << " },"; + } + s.op->newline(-1) << "};"; + s.op->newline(); } @@ -9777,28 +9806,14 @@ tracepoint_derived_probe_group::emit_module_init (systemtap_session &s) return; s.op->newline() << "/* init tracepoint probes */"; - - // We can't use a simple runtime loop because the probe registration - // functions are distinct inlines. Instead, this will generate nesting as - // deep as the number of probe points. Gotos are also possible, but the end - // result is the same. - - for (unsigned i = 0; i < probes.size(); ++i) - { - s.op->newline() << "if (!rc) {"; - s.op->newline(1) << "probe_point = " - << lex_cast_qstring (*probes[i]->sole_location()) << ";"; - s.op->newline() << "rc = register_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; - } - - for (unsigned i = probes.size() - 1; i < probes.size(); --i) - { - s.op->newline() << "if (rc)"; - s.op->newline(1) << "unregister_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; - s.op->newline(-2) << "}"; - } + s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; + s.op->newline(1) << "rc = stap_tracepoint_probes[i].reg();"; + s.op->newline() << "if (rc) {"; + s.op->newline(1) << "for (j=i-1; j>=0; j--)"; // partial rollback + s.op->newline(1) << "stap_tracepoint_probes[j].unreg();"; + s.op->newline(-1) << "break;"; // don't attempt to register any more probes + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; // This would be technically proper (on those autoconf-detectable // kernels that include this function in tracepoint.h), however we @@ -9817,10 +9832,10 @@ tracepoint_derived_probe_group::emit_module_exit (systemtap_session& s) if (probes.empty()) return; - s.op->newline() << "/* deregister tracepointer probes */"; - for (unsigned i = 0; i < probes.size(); ++i) - s.op->newline() << "unregister_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline() << "/* deregister tracepoint probes */"; + s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)"; + s.op->newline(1) << "stap_tracepoint_probes[i].unreg();"; + s.op->indent(-1); // Not necessary: see above. -- cgit From bb64f40b58a64a9ae065dba5058463ac604c3896 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 15 Mar 2009 15:29:01 +0100 Subject: Move vma module tracking from pr6866 branch to master. * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Always emit vm callback probe for __stp_tf_vm_cb. * runtime/task_finder.c (__stp_tf_vm_cb): Always expose, move _stp_dbug statements under ifdef DEBUG_TASK_FINDER_VMA. Find and record corresponding module when vm_path not NULL. * runtime/task_finder_vma.c (struct __stp_tf_vma_entry): Add _stp_module. (stap_add_vma_map_info): Add _stp_module argument and assign. (__stp_tf_get_vma_entry_addr): New static function to get the __stp_tf_vma_entry given an address. --- tapsets.cxx | 4 ---- 1 file changed, 4 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index b02e2cce..6efcb3af 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7172,10 +7172,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. string path = it->first; - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, true, path, (int64_t)0, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { @@ -7193,10 +7191,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, false, "", it->first, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { -- cgit From 86758d5f2b838d5769c7ace15269a4ebc422f94a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Mar 2009 18:13:07 -0700 Subject: Fix regression in tracepoint unregistration Commit 96b030fe reorganized the tracepoint registration calls by creating generic wrappers that return int. However, the older tracepoint implementation (as found in RHEL5.3) returned void for unreg, so this was failing pass-4. Since we can't handle unregistration failures anyway, this change just makes the generic unregister function return void instead. As noted in the newly-added comment, it should be safe for us to ignore unreg failures. --- tapsets.cxx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 6efcb3af..2f940b29 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9770,8 +9770,13 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(1) << "return register_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << ");"; s.op->newline(-1) << "}"; - s.op->newline() << "static int unregister_tracepoint_probe_" << i << "(void) {"; - s.op->newline(1) << "return unregister_trace_" << p->tracepoint_name + + // NB: we're not prepared to deal with unreg failures. However, failures + // can only occur if the tracepoint doesn't exist (yet?), or if we + // weren't even registered. The former should be OKed by the initial + // registration call, and the latter is safe to ignore. + s.op->newline() << "static void unregister_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "(void) unregister_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << ");"; s.op->newline(-1) << "}"; s.op->newline(); @@ -9780,7 +9785,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) // emit an array of registration functions for easy init/shutdown s.op->newline() << "static struct stap_tracepoint_probe {"; s.op->newline(1) << "int (*reg)(void);"; - s.op->newline(0) << "int (*unreg)(void);"; + s.op->newline(0) << "void (*unreg)(void);"; s.op->newline(-1) << "} stap_tracepoint_probes[] = {"; s.op->indent(1); for (unsigned i = 0; i < probes.size(); ++i) -- cgit From 8df306c4443bd9dd1397bab6cba7f61cb2d88af9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 18:51:17 -0700 Subject: Support tracepoints with no arguments LTTng has a few tracepoints without any arguments, which caused our compile to fail, claiming that our entry function was not a declaration. This just adds an explicit (void) argument list for that case. --- tapsets.cxx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 2f940b29..2548625b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9739,6 +9739,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) -- cgit From 219e62c7eeca850d2898fdbfb6b74719195274a6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 19:04:54 -0700 Subject: PR9959: improve tracepoint arg type-naming dwarf_type_name now works with more argument types. There were three cases that I needed to improve: - For "const struct foo*", the debuginfo has a const-DIE named "foo" chained to a struct-DIE named "foo", so we can't assume that seeing a name means we're down to the base type. The recursion now decends until it explicitly sees a base_type, typedef, struct, or union. - For "void*", the debuginfo has a pointer-DIE without any DW_AT_type after. Now I'm just catching that failed lookup and writing in "void". - For "va_list", the debuginfo actually resolves to an internal type "struct __va_list_tag*", but that struct has no declaration at the source level. I'm just hacking that exact case to say "va_list" instead, but it would be nice to find something cleaner... We'll probably still have problems if any tracepoint uses a function- pointer argument, but so far I've only seen that as a "void*", which we now handle ok. --- tapsets.cxx | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 2548625b..a4da7811 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9586,32 +9586,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)) @@ -9632,6 +9639,11 @@ 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; } -- cgit From dcaa1a657cef72dec518f7376b5d856ef8f01076 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 20:05:56 -0700 Subject: PR9959: hide tracepoint arguments of unknown type We always have to know the type name of tracepoint arguments, so we can declare the right function callback, but we can suppress access to those types which we don't (yet) know how to read. --- tapsets.cxx | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index a4da7811..42be4556 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9231,9 +9231,9 @@ mark_builder::build(systemtap_session & sess, struct tracepoint_arg { string name, c_type; - bool used, isptr; + 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 @@ -9285,7 +9285,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; @@ -9504,6 +9504,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; @@ -9649,28 +9651,29 @@ dwarf_type_name(Dwarf_Die& type_die, string& c_type) 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; + return true; default: // should we consider other types too? return false; @@ -9694,12 +9697,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 @@ -9712,8 +9715,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 -- cgit From 0afb7073fa08980ecf9a80018d18a5148c2f686e Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Thu, 19 Mar 2009 11:32:48 -0400 Subject: rename process().itrace -> process().insn introduce process().insn.block --- tapsets.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 42be4556..894a7447 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6240,6 +6240,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 +6317,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) @@ -10791,9 +10794,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 -- cgit From e2ae0696f7b8cbbafad87a8739c0cc450f7ee887 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 19 Mar 2009 13:02:19 -0400 Subject: Disable kprobe blacklist in guru mode. --- tapsets.cxx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 894a7447..6de6271b 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. -- cgit From d0cd971e70eba3781a95862223d1f7d45e2f5135 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 22:22:25 +0100 Subject: Throw type into semantic_error message of @cast when not found. * tapsets.cxx (dwarf_cast_expanding_visitor::visit_cast_op): Add type to msg added to semantic_error when thrown. --- tapsets.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 6de6271b..103c39fa 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5067,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(...) } -- cgit From ad370dccd460ebfc66f21d3d16f44807d789484f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 19 Mar 2009 16:23:02 -0700 Subject: PR9960: support tracepoint struct/union value arg If a tracepoint arg is a structure or union that is passed by value, then this takes the address of the parameter so it can be used like a pointer in the rest of our code. --- tapsets.cxx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 103c39fa..a8653d8a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9242,7 +9242,7 @@ mark_builder::build(systemtap_session & sess, struct tracepoint_arg { - string name, c_type; + string name, c_type, typecast; bool usable, used, isptr; Dwarf_Die type_die; tracepoint_arg(): usable(false), used(false), isptr(false) {} @@ -9345,6 +9345,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()) { @@ -9685,6 +9688,14 @@ resolve_tracepoint_arg_type(tracepoint_arg& arg) 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? @@ -9787,8 +9798,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);"; -- cgit From 9c73606142525f521a44c4907832b2d1e1f3c659 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 16:30:02 -0400 Subject: PR9967: don't count -DINTERRUPTIBLE=1 reentrancy against MAXSKIPPED * tapsets.cxx (common_probe_entryfn_prologue): Become conditional on !INTERRUPTIBLE. * translate.cxx (emit_module_exit): Still print skipped_count_reentrant with -t, even if skipped_count was zero. --- tapsets.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index a8653d8a..bc567491 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -206,7 +206,9 @@ common_probe_entryfn_prologue (translator_output* o, string statestr, o->newline() << "c = per_cpu_ptr (contexts, smp_processor_id());"; o->newline() << "if (atomic_inc_return (& c->busy) != 1) {"; - o->newline(1) << "atomic_inc (& skipped_count);"; + o->newline(1) << "#if !INTERRUPTIBLE"; + o->newline() << "atomic_inc (& skipped_count);"; + o->newline() << "#endif"; o->newline() << "#ifdef STP_TIMING"; o->newline() << "atomic_inc (& skipped_count_reentrant);"; o->newline() << "#ifdef DEBUG_REENTRANCY"; -- cgit From b278033a7e4632a414502b63ba51fcce36f44f94 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 16:35:06 -0700 Subject: Cache the tracepoint query results To use tracepoints, we build a "tracequery" module that compiles debuginfo for all available tracepoints in the user's kernel. That's a bit of a cumbersome step to do during pass-2 though. This change adds tracequery caching so we only need to compile it once. --- tapsets.cxx | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index bc567491..e9ade595 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -18,6 +18,7 @@ #include "buildrun.h" #include "dwarf_wrappers.h" #include "auto_free.h" +#include "hash.h" #include #include @@ -9993,12 +9994,43 @@ tracepoint_builder::init_dw(systemtap_session& s) if (dw != NULL) return true; + if (s.use_cache) + { + // see if the cached module exists + find_tracequery_hash(s); + if (!s.tracequery_path.empty()) + { + int fd = open(s.tracequery_path.c_str(), O_RDONLY); + if (fd != -1) + { + if (s.verbose > 2) + clog << "Pass 2: using cached " << s.tracequery_path << endl; + + dw = new dwflpp(s); + dw->setup_user(s.tracequery_path); + close(fd); + return true; + } + } + } + + // no cached module, time to make it string tracequery_ko; int rc = make_tracequery(s, tracequery_ko); if (rc != 0) return false; - // TODO cache tracequery.ko + if (s.use_cache) + { + // try to save tracequery in the cache + if (s.verbose > 2) + clog << "Copying " << tracequery_ko + << " to " << s.tracequery_path << endl; + if (copy_file(tracequery_ko.c_str(), + s.tracequery_path.c_str()) != 0) + cerr << "Copy failed (\"" << tracequery_ko << "\" to \"" + << s.tracequery_path << "\"): " << strerror(errno) << endl; + } dw = new dwflpp(s); dw->setup_user(tracequery_ko); -- cgit