summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2009-09-15 18:29:45 -0400
committerFrank Ch. Eigler <fche@elastic.org>2009-09-15 18:29:45 -0400
commitda23eceb71cc70668ab9dfd80d318b3837703d9d (patch)
treedcfb85f50cf035213bde1836d2167ceca00c8205 /tapsets.cxx
parent2260f4e32eb4c0b4cc95e4bef8ccdc5dc66261af (diff)
parent24fcff20ed7a4a9f2b772c572db28ee8df49161f (diff)
downloadsystemtap-steved-da23eceb71cc70668ab9dfd80d318b3837703d9d.tar.gz
systemtap-steved-da23eceb71cc70668ab9dfd80d318b3837703d9d.tar.xz
systemtap-steved-da23eceb71cc70668ab9dfd80d318b3837703d9d.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
* 'master' of ssh://sources.redhat.com/git/systemtap: (34 commits) Update the langref copyright notice Fix some probe examples in the language reference Remove automatic authorization of servers started by root as trusted signers. docs: add abnormal termination section to PROCESSING Remove unneeded header file Get the module to sign from -p4's stdout Move --unprivileged support news to the top. Firther updates to NEWS regarding signing and unprivileged users. Authorize new certificates created for servers started by root as authorized signers. 2009-09-14 Dave Brolley <brolley@redhat.com> Allow remaining process.* probes for unprivileged users. Use the sched_switch tracepoint if available. PR10608: mark test cases untested once compilation failed Make check.exp not sleep so much in test_installcheck. Make tracepoints.exp test more efficient by running as one giant script. Only test highest optimization for exelib.exp test. Replace small exelib.exp testcases with one jumbo testcase. Remove duplicate uprobe_derived_probe code Add semaphores for use with the forthcoming sdt marker checks. Add actual pc address to semantic error about inaccessible variables. ... Conflicts: tapsets.cxx
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx376
1 files changed, 120 insertions, 256 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 95c0deb9..f5be7a4e 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -351,11 +351,8 @@ struct dwarf_derived_probe: public derived_probe
bool access_vars;
void printsig (std::ostream &o) const;
- void join_group (systemtap_session& s);
+ virtual void join_group (systemtap_session& s);
void emit_probe_local_init(translator_output * o);
-
- string args;
- void saveargs(Dwarf_Die* scope_die);
void printargs(std::ostream &o) const;
// Pattern registration helpers.
@@ -369,42 +366,48 @@ struct dwarf_derived_probe: public derived_probe
dwarf_builder * dw,
bool unprivileged_ok_p = false);
static void register_patterns(systemtap_session& s);
+
+protected:
+ dwarf_derived_probe(probe *base,
+ probe_point *location,
+ Dwarf_Addr addr,
+ bool has_return):
+ derived_probe(base, location), addr(addr), has_return(has_return),
+ has_maxactive(0), maxactive_val(0), access_vars(false)
+ {}
+
+private:
+ string args;
+ void saveargs(dwarf_query& q, Dwarf_Die* scope_die);
};
-struct uprobe_derived_probe: public derived_probe
+struct uprobe_derived_probe: public dwarf_derived_probe
{
- bool return_p;
- string module; // * => unrestricted
int pid; // 0 => unrestricted
- string section; // empty => absolute address
- Dwarf_Addr address;
- // bool has_maxactive;
- // long maxactive_val;
uprobe_derived_probe (const string& function,
const string& filename,
int line,
const string& module,
- int pid,
const string& section,
Dwarf_Addr dwfl_addr,
Dwarf_Addr addr,
dwarf_query & q,
- Dwarf_Die* scope_die);
+ Dwarf_Die* scope_die):
+ dwarf_derived_probe(function, filename, line, module, section,
+ dwfl_addr, addr, q, scope_die), pid(0)
+ {}
// alternate constructor for process(PID).statement(ADDR).absolute
uprobe_derived_probe (probe *base,
probe_point *location,
int pid,
Dwarf_Addr addr,
- bool return_p);
-
- string args;
- void saveargs(Dwarf_Die* scope_die);
- void printargs(std::ostream &o) const;
+ bool has_return):
+ dwarf_derived_probe(base, location, addr, has_return), pid(pid)
+ {}
- void printsig (std::ostream &o) const;
void join_group (systemtap_session& s);
};
@@ -1003,7 +1006,7 @@ dwarf_query::add_probe_point(const string& funcname,
if (has_process)
{
results.push_back (new uprobe_derived_probe(funcname, filename, line,
- module, 0, reloc_section, addr, reloc_addr,
+ module, reloc_section, addr, reloc_addr,
*this, scope_die));
}
else
@@ -1761,7 +1764,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
Dwarf_Addr addr;
block *add_block;
block *add_call_probe; // synthesized from .return probes with saved $vars
- std::map<std::string, symbol *> return_ts_map;
+ map<std::string, symbol *> return_ts_map;
+ vector<Dwarf_Die> scopes;
bool visited;
dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a):
@@ -1770,6 +1774,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
void visit_target_symbol_context (target_symbol* e);
void visit_target_symbol (target_symbol* e);
void visit_cast_op (cast_op* e);
+private:
+ vector<Dwarf_Die>& getscopes(target_symbol *e);
};
@@ -2084,10 +2090,8 @@ dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e)
void
dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
{
- Dwarf_Die *scopes;
- if (dwarf_getscopes_die (scope_die, &scopes) == 0)
+ if (null_die(scope_die))
return;
- auto_free free_scopes(scopes);
target_symbol *tsym = new target_symbol;
print_format* pf = new print_format;
@@ -2135,6 +2139,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
// non-.return probe: support $$parms, $$vars, $$locals
bool first = true;
Dwarf_Die result;
+ vector<Dwarf_Die> scopes = q.dw.getscopes_die(scope_die);
if (dwarf_child (&scopes[0], &result) == 0)
do
{
@@ -2256,7 +2261,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
}
else
{
- ec->code = q.dw.literal_stmt_for_local (scope_die,
+ ec->code = q.dw.literal_stmt_for_local (getscopes(e),
addr,
e->base_name.substr(1),
e,
@@ -2366,6 +2371,35 @@ dwarf_var_expanding_visitor::visit_cast_op (cast_op *e)
}
+vector<Dwarf_Die>&
+dwarf_var_expanding_visitor::getscopes(target_symbol *e)
+{
+ if (scopes.empty())
+ {
+ // If the address is at the beginning of the scope_die, we can do a fast
+ // getscopes from there. Otherwise we need to look it up by address.
+ Dwarf_Addr entrypc;
+ if (q.dw.die_entrypc(scope_die, &entrypc) && entrypc == addr)
+ scopes = q.dw.getscopes(scope_die);
+ else
+ scopes = q.dw.getscopes(addr);
+
+ if (scopes.empty())
+ throw semantic_error ("unable to find any scopes containing "
+ + lex_cast_hex(addr)
+ + ((scope_die == NULL) ? ""
+ : (string (" in ")
+ + (dwarf_diename(scope_die) ?: "<unknown>")
+ + "(" + (dwarf_diename(q.dw.cu) ?: "<unknown>")
+ + ")"))
+ + " while searching for local '"
+ + e->base_name.substr(1) + "'",
+ e->tok);
+ }
+ return scopes;
+}
+
+
struct dwarf_cast_query : public base_query
{
cast_op& e;
@@ -2673,16 +2707,25 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
module (module), section (section), addr (addr),
has_return (q.has_return),
has_maxactive (q.has_maxactive),
- maxactive_val (q.maxactive_val)
+ maxactive_val (q.maxactive_val),
+ access_vars(false)
{
- // Assert relocation invariants
- if (section == "" && dwfl_addr != addr) // addr should be absolute
- throw semantic_error ("missing relocation base against", q.base_loc->tok);
- if (section != "" && dwfl_addr == addr) // addr should be an offset
- throw semantic_error ("inconsistent relocation address", q.base_loc->tok);
-
- this->tok = q.base_probe->tok;
- this->access_vars = false;
+ if (q.has_process)
+ {
+ // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN.
+ // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas
+ // ET_DYN ones do (addr += run-time mmap base address). We tell these apart
+ // by the incoming section value (".absolute" vs. ".dynamic").
+ // XXX Assert invariants here too?
+ }
+ else
+ {
+ // Assert kernel relocation invariants
+ if (section == "" && dwfl_addr != addr) // addr should be absolute
+ throw semantic_error ("missing relocation base against", tok);
+ if (section != "" && dwfl_addr == addr) // addr should be an offset
+ throw semantic_error ("inconsistent relocation address", tok);
+ }
// XXX: hack for strange g++/gcc's
#ifndef USHRT_MAX
@@ -2690,7 +2733,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
#endif
// Range limit maxactive() value
- if (q.has_maxactive && (q.maxactive_val < 0 || q.maxactive_val > USHRT_MAX))
+ if (has_maxactive && (maxactive_val < 0 || maxactive_val > USHRT_MAX))
throw semantic_error ("maxactive value out of range [0,"
+ lex_cast(USHRT_MAX) + "]",
q.base_loc->tok);
@@ -2698,9 +2741,11 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
// Expand target variables in the probe body
if (!null_die(scope_die))
{
+ // XXX: user-space deref's for q.has_process!
dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr);
v.replace (this->body);
- this->access_vars = v.visited;
+ if (!q.has_process)
+ access_vars = v.visited;
// If during target-variable-expanding the probe, we added a new block
// of code, add it to the start of the probe.
@@ -2720,11 +2765,21 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
q.base_probe->body = v.add_call_probe;
q.has_return = false;
q.has_call = true;
-
- dwarf_derived_probe *synthetic = new dwarf_derived_probe (funcname, filename, line,
- module, section, dwfl_addr,
- addr, q, scope_die);
- q.results.push_back (synthetic);
+
+ if (q.has_process)
+ {
+ uprobe_derived_probe *synthetic = new uprobe_derived_probe (funcname, filename, line,
+ module, section, dwfl_addr,
+ addr, q, scope_die);
+ q.results.push_back (synthetic);
+ }
+ else
+ {
+ dwarf_derived_probe *synthetic = new dwarf_derived_probe (funcname, filename, line,
+ module, section, dwfl_addr,
+ addr, q, scope_die);
+ q.results.push_back (synthetic);
+ }
q.has_return = true;
q.has_call = false;
@@ -2735,7 +2790,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
// Save the local variables for listing mode
if (q.sess.listing_mode_vars)
- saveargs(scope_die);
+ saveargs(q, scope_die);
// Reset the sole element of the "locations" vector as a
// "reverse-engineered" form of the incoming (q.base_loc) probe
@@ -2802,12 +2857,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
void
-dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
+dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die)
{
- Dwarf_Die *scopes;
- if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0)
+ if (null_die(scope_die))
return;
- auto_free free_scopes(scopes);
stringstream argstream;
string type_name;
@@ -2819,6 +2872,7 @@ dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
argstream << " $return:" << type_name;
Dwarf_Die arg;
+ vector<Dwarf_Die> scopes = q.dw.getscopes_die(scope_die);
if (dwarf_child (&scopes[0], &arg) == 0)
do
{
@@ -2905,12 +2959,21 @@ dwarf_derived_probe::register_patterns(systemtap_session& s)
register_function_and_statement_variants(root->bind(TOK_KERNEL), dw);
register_function_and_statement_variants(root->bind_str(TOK_MODULE), dw);
- root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(dw);
- root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
- root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
- register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw, false/*!unprivileged_ok_p*/);
- root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)->bind(dw);
- root->bind_str(TOK_PROCESS)->bind_num(TOK_MARK)->bind(dw);
+ root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
+ ->bind(dw);
+ root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)
+ ->bind(dw);
+
+ register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw, true/*unprivileged_ok_p*/);
+ root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)
+ ->allow_unprivileged()
+ ->bind(dw);
+ root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)
+ ->allow_unprivileged()
+ ->bind(dw);
+ root->bind_str(TOK_PROCESS)->bind_num(TOK_MARK)
+ ->allow_unprivileged()
+ ->bind(dw);
}
void
@@ -3812,8 +3875,7 @@ dwarf_builder::build(systemtap_session & sess,
symbol_table::~symbol_table()
{
- for (iterator_t i = map_by_addr.begin(); i != map_by_addr.end(); ++i)
- delete i->second;
+ delete_map(map_by_addr);
}
void
@@ -4178,206 +4240,6 @@ public:
};
-uprobe_derived_probe::uprobe_derived_probe (const string& function,
- const string& filename,
- int line,
- const string& module,
- int pid,
- const string& section,
- Dwarf_Addr dwfl_addr,
- Dwarf_Addr addr,
- dwarf_query & q,
- Dwarf_Die* scope_die /* may be null */):
- derived_probe (q.base_probe, new probe_point (*q.base_loc) /* .components soon rewritten */ ),
- return_p (q.has_return), module (module), pid (pid), section (section), address (addr)
-{
- // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN.
- // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas
- // ET_DYN ones do (addr += run-time mmap base address). We tell these apart
- // by the incoming section value (".absolute" vs. ".dynamic").
-
- this->tok = q.base_probe->tok;
-
- // Expand target variables in the probe body
- if (!null_die(scope_die))
- {
- dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's!
- v.replace (this->body);
-
- // If during target-variable-expanding the probe, we added a new block
- // of code, add it to the start of the probe.
- if (v.add_block)
- this->body = new block(v.add_block, this->body);
-
- // If when target-variable-expanding the probe, we added a new
- // probe, add it in a new file to the list of files to be processed.
- if (v.add_call_probe)
- {
- assert (q.has_return && !q.has_call);
-
- // We temporarily replace q.base_probe.
- statement* old_body = q.base_probe->body;
- q.base_probe->body = v.add_call_probe;
- q.has_return = false;
- q.has_call = true;
-
- uprobe_derived_probe *synthetic = new uprobe_derived_probe (function, filename, line,
- module, pid, section, dwfl_addr,
- addr, q, scope_die);
- q.results.push_back (synthetic);
-
- q.has_return = true;
- q.has_call = false;
- q.base_probe->body = old_body;
- }
- }
- // else - null scope_die - $target variables will produce an error during translate phase
-
- // Save the local variables for listing mode
- if (q.sess.listing_mode_vars)
- saveargs(scope_die);
-
- // Reset the sole element of the "locations" vector as a
- // "reverse-engineered" form of the incoming (q.base_loc) probe
- // point. This allows a user to see what function / file / line
- // number any particular match of the wildcards.
-
- vector<probe_point::component*> comps;
- if(q.has_process)
- comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(module)));
- else
- assert (0);
-
- string fn_or_stmt;
- if (q.has_function_str || q.has_function_num)
- fn_or_stmt = "function";
- else
- fn_or_stmt = "statement";
-
- if (q.has_function_str || q.has_statement_str)
- {
- string retro_name = function;
- if (filename != "")
- {
- retro_name += ("@" + string (filename));
- if (line > 0)
- retro_name += (":" + lex_cast (line));
- }
- comps.push_back
- (new probe_point::component
- (fn_or_stmt, new literal_string (retro_name)));
- }
- else if (q.has_function_num || q.has_statement_num)
- {
- Dwarf_Addr retro_addr;
- if (q.has_function_num)
- retro_addr = q.function_num_val;
- else
- retro_addr = q.statement_num_val;
- comps.push_back (new probe_point::component
- (fn_or_stmt,
- new literal_number(retro_addr))); // XXX: should be hex if possible
-
- if (q.has_absolute)
- comps.push_back (new probe_point::component (TOK_ABSOLUTE));
- }
-
- if (q.has_call)
- comps.push_back (new probe_point::component(TOK_CALL));
- if (q.has_inline)
- comps.push_back (new probe_point::component(TOK_INLINE));
- if (return_p)
- comps.push_back (new probe_point::component(TOK_RETURN));
- /*
- if (has_maxactive)
- comps.push_back (new probe_point::component
- (TOK_MAXACTIVE, new literal_number(maxactive_val)));
- */
-
- // Overwrite it.
- this->sole_location()->components = comps;
-}
-
-
-uprobe_derived_probe::uprobe_derived_probe (probe *base,
- probe_point *location,
- int pid,
- Dwarf_Addr addr,
- bool has_return):
- derived_probe (base, location), // location is not rewritten here
- return_p (has_return), pid (pid), address (addr)
-{
-}
-
-
-void
-uprobe_derived_probe::saveargs(Dwarf_Die* scope_die)
-{
- // same as dwarf_derived_probe::saveargs
-
- Dwarf_Die *scopes;
- if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0)
- return;
- auto_free free_scopes(scopes);
-
- stringstream argstream;
- string type_name;
- Dwarf_Die type_die;
-
- if (return_p &&
- dwarf_attr_die (scope_die, DW_AT_type, &type_die) &&
- dwarf_type_name(&type_die, type_name))
- argstream << " $return:" << type_name;
-
- Dwarf_Die arg;
- if (dwarf_child (&scopes[0], &arg) == 0)
- do
- {
- switch (dwarf_tag (&arg))
- {
- case DW_TAG_variable:
- case DW_TAG_formal_parameter:
- break;
-
- default:
- continue;
- }
-
- const char *arg_name = dwarf_diename (&arg);
- if (!arg_name)
- continue;
-
- type_name.clear();
- if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) ||
- !dwarf_type_name(&type_die, type_name))
- continue;
-
- argstream << " $" << arg_name << ":" << type_name;
- }
- while (dwarf_siblingof (&arg, &arg) == 0);
-
- args = argstream.str();
-}
-
-
-void
-uprobe_derived_probe::printargs(std::ostream &o) const
-{
- // same as dwarf_derived_probe::printargs
- o << args;
-}
-
-
-void
-uprobe_derived_probe::printsig (ostream& o) const
-{
- // Same as dwarf_derived_probe.
- sole_location()->print (o);
- o << " /* pc=" << section << "+0x" << hex << address << dec << " */";
- printsig_nested (o);
-}
-
-
void
uprobe_derived_probe::join_group (systemtap_session& s)
{
@@ -4525,10 +4387,10 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
string key = make_pbm_key (p);
unsigned value = module_index[key];
s.op->line() << " .tfi=" << value << ",";
- s.op->line() << " .address=(unsigned long)0x" << hex << p->address << dec << "ULL,";
+ s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
s.op->line() << " .ph=&" << p->name << ",";
- if (p->return_p) s.op->line() << " .return_p=1,";
+ if (p->has_return) s.op->line() << " .return_p=1,";
s.op->line() << " },";
}
s.op->newline(-1) << "};";
@@ -6222,9 +6084,11 @@ register_standard_tapsets(systemtap_session & s)
// XXX: user-space starter set
s.pattern_root->bind_num(TOK_PROCESS)
->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
+ ->allow_unprivileged()
->bind(new uprobe_builder ());
s.pattern_root->bind_num(TOK_PROCESS)
->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(TOK_RETURN)
+ ->allow_unprivileged()
->bind(new uprobe_builder ());
// kernel tracepoint probes