From a43ba4339f5b291d139e0be59bba4bc46c55ea25 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 15 Aug 2008 12:21:22 -0400 Subject: PR6836: $$vars extensions, $$return --- tapsets.cxx | 121 +++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 43 deletions(-) (limited to 'tapsets.cxx') 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 (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, -- cgit From fd5747054ac2a5c90d209195c55e6310972f969a Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 15 Aug 2008 14:46:27 -0400 Subject: PR6836: tweak $$return formatting --- tapsets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 1f7d2555..f661b7e4 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4333,7 +4333,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) } else { - pf->raw_components += "$return"; + pf->raw_components += "return"; pf->raw_components += "=%#x "; pf->args.push_back(*(expression**)this->targets.top()); } -- cgit From 986e98de88e5a55451aaf24a6ead7f44725124c1 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 15 Aug 2008 14:02:31 -0500 Subject: Change system-wide probes from 'process("*").begin' to 'process.begin'. 2008-08-15 David Smith * tapsets.cxx (utrace_builder::build): Change system-wide probes from 'process("*").begin' to 'process.begin'. (register_standard_tapsets): Add new 'process' binding. * stapprobes.5.in: Change system-wide probes from 'process("*").begin' to 'process.begin'. 2008-08-15 David Smith * systemtap.base/utrace_p4.exp: Change system-wide probes from 'process("*").begin' to 'process.begin'. --- tapsets.cxx | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 1f7d2555..60d9a377 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5945,7 +5945,6 @@ struct utrace_builder: public derived_probe_builder bool has_path = get_param (parameters, TOK_PROCESS, path); bool has_pid = get_param (parameters, TOK_PROCESS, pid); enum utrace_derived_probe_flags flags = UDPF_NONE; - assert (has_path || has_pid); if (has_null_param (parameters, TOK_THREAD)) { @@ -5966,23 +5965,23 @@ struct utrace_builder: public derived_probe_builder else if (has_null_param (parameters, TOK_END)) flags = UDPF_END; + // If we didn't get a path or pid, this means to probe everything. + // Convert this to a pid-based probe. + if (! has_path && ! has_pid) + { + has_path = false; + path.clear(); + has_pid = true; + pid = 0; + } // Validate pid. - if (has_pid) + else if (has_pid) { // We can't probe 'init' (pid 1). if (pid < 2) throw semantic_error ("process pid must be greater than 1", location->tok); } - // If we have a path whose value is "*", this means to probe - // everything. Convert this to a pid-based probe. - else if (has_path && path == "*") - { - has_path = false; - path.clear(); - has_pid = true; - pid = 0; - } // If we have a regular path, we need to validate it. else if (has_path) { @@ -8897,18 +8896,26 @@ register_standard_tapsets(systemtap_session & s) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_BEGIN) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_BEGIN) + ->bind(new utrace_builder ()); s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_END) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_END) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_END) + ->bind(new utrace_builder ()); s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_BEGIN) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_BEGIN) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_BEGIN) + ->bind(new utrace_builder ()); s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_END) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_END) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_END) + ->bind(new utrace_builder ()); // itrace user-space probes s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace") -- cgit From 480f38d3275c87ac5b58a95dd127633babfc7374 Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 18 Aug 2008 15:54:39 -0500 Subject: Add missing 'process' bindings. 2008-08-18 David Smith * tapsets.cxx (register_standard_tapsets): Add missing 'process.syscall' and 'process.syscall.return' bindings. --- tapsets.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 9dcb4290..39fc0074 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -8916,21 +8916,24 @@ register_standard_tapsets(systemtap_session & s) ->bind(new utrace_builder ()); s.pattern_root->bind(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_END) ->bind(new utrace_builder ()); - - // itrace user-space probes - s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace") - ->bind(new itrace_builder ()); - s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace") - ->bind(new itrace_builder ()); - s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_SYSCALL) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_SYSCALL) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_SYSCALL) + ->bind(new utrace_builder ()); s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_SYSCALL)->bind(TOK_RETURN) ->bind(new utrace_builder ()); s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_SYSCALL)->bind(TOK_RETURN) ->bind(new utrace_builder ()); + s.pattern_root->bind(TOK_PROCESS)->bind(TOK_SYSCALL)->bind(TOK_RETURN) + ->bind(new utrace_builder ()); + + // itrace user-space probes + s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace") + ->bind(new itrace_builder ()); + s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace") + ->bind(new itrace_builder ()); // marker-based parts s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_MARK) -- cgit From 930a1798154b9c1caf27009825b2b165ef577a1e Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 19 Aug 2008 12:12:06 -0500 Subject: PR 6841 fix. 2008-08-19 David Smith PR 6841 * tapsets.cxx (utrace_derived_probe_group::emit_probe_decl): Workaround utrace bug by quiescing threads before attaching a utrace syscall engine to them. (utrace_derived_probe_group::emit_module_decls): Emit quiesce handler. 2008-08-19 David Smith PR 6841 * task_finder.c (__stp_utrace_task_finder_target_quiesce): Quiesces thread before turning on syscall tracing. --- tapsets.cxx | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 39fc0074..36601b01 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6096,17 +6096,19 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death // handler isn't strictly necessary. However, it helps to keep - // our attaches/detaches symmetrical. + // our attaches/detaches symmetrical. Notice we're using quiesce + // as a workaround for bug 6841. case UDPF_SYSCALL: s.op->line() << " .flags=(UDPF_SYSCALL),"; - s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; - s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),"; + s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },"; + s.op->line() << " .events=(UTRACE_ACTION_QUIESCE|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),"; break; case UDPF_SYSCALL_RETURN: s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),"; - s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; - s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),"; + s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },"; + s.op->line() << " .events=(UTRACE_ACTION_QUIESCE|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),"; break; + case UDPF_NONE: s.op->line() << " .flags=(UDPF_NONE),"; s.op->line() << " .ops={ },"; @@ -6228,6 +6230,24 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) { + s.op->newline() << "static u32 stap_utrace_probe_syscall_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) {"; + s.op->indent(1); + s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;"; + + // Turn off quiesce handling and turn on either syscall entry + // or exit events. + s.op->newline() << "if (p->flags == UDPF_SYSCALL)"; + s.op->indent(1); + s.op->newline() << "utrace_set_flags(tsk, engine, UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH));"; + s.op->indent(-1); + s.op->newline() << "else if (p->flags == UDPF_SYSCALL_RETURN)"; + s.op->indent(1); + s.op->newline() << "utrace_set_flags(tsk, engine, UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH));"; + s.op->indent(-1); + + s.op->newline() << "return (UTRACE_ACTION_NEWSTATE | UTRACE_ACTION_RESUME);"; + s.op->newline(-1) << "}"; + s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {"; s.op->indent(1); s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;"; -- cgit