summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog47
-rw-r--r--runtime/staprun/ChangeLog8
-rw-r--r--runtime/staprun/staprun_funcs.c12
-rw-r--r--stapprobes.5.in8
-rw-r--r--tapsets.cxx227
-rw-r--r--testsuite/ChangeLog9
-rw-r--r--testsuite/systemtap.base/beginenderror.exp1
-rw-r--r--testsuite/systemtap.base/marker.exp41
8 files changed, 253 insertions, 100 deletions
diff --git a/ChangeLog b/ChangeLog
index 4306992a..342cb6d5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2008-02-20 David Smith <dsmith@redhat.com>
+
+ * tapsets.cxx (struct mark_derived_probe): Renamed 'probe_sig' to
+ 'probe_format'.
+ (mark_derived_probe::mark_derived_probe): Added new "format" probe
+ point component.
+ (mark_derived_probe::parse_probe_format): Renamed from
+ 'mark_derived_probe::parse_probe_sig'.
+ (struct mark_builder): Added typedefs. Converted mark_cache from
+ a map to a multimap to handle markers with the same name but
+ different formats.
+ (mark_builder::build): Added new 'format' probe parameter.
+ (register_standard_tapsets): Added new 'format' marker probe
+ optional parameter.
+ * stapprobes.5.in (parts): Documented new "format" probe
+ component.
+
+2008-02-19 Roland McGrath <roland@redhat.com>
+
+ * tapsets.cxx (query_module): Use dwfl_module_getdwarf rather
+ than dwfl_module_getelf for e_machine check.
+ (dwarf_query::get_blacklist_section): Likewise for section search.
+ Ignore non-SHF_ALLOC sections.
+
+2008-02-19 Frank Ch. Eigler <fche@elastic.org>
+
+ * tapsets.cxx (query_module): Tweak elf-machine checking to
+ better represent elfutils idioms.
+
2008-02-19 Frank Ch. Eigler <fche@elastic.org>
PR 5766.
@@ -69,7 +98,7 @@
PR5750.
From Eugeniy Meshcheryakov eugen@debian.org:
* configure.ac (HAVE_LIBSQLITE3): Complete AC_DEFINE.
-
+
* configure, INSTALL, missing, compile, depcomp, install-sh:
autoreconf -fi'd.
@@ -102,7 +131,7 @@
"$arg" or "$format".
(mark_derived_probe_group::emit_module_decls): Sets up "$format"
data.
-
+
PR 5650 (parital)
* systemtap.spec.in: Moved %pre section to the systemtap-runtime
rpm.
@@ -185,7 +214,7 @@
* acsite.m4: Removed.
* systemtap.spec.in: Minimum elfutils version number is no longer
filled in by configure.
-
+
PR 5650 (partial).
* configure.ac: Handles sqlite optional functionality correctly.
If enabled/disabled by the user, do the right thing. If not
@@ -493,8 +522,8 @@
* stapex.5.in: Ditto.
* stapfuncs.5.in: Ditto. ALso remove print and printf. They are
documented in stap.1.in.
-
-2007-11-12 Martin Hunt <hunt@redhat.com>
+
+2007-11-12 Martin Hunt <hunt@redhat.com>
* translate.cxx (visit_print_format): Strings without a format or
formatted with "%s" or "%s\n" should be printed with calls to _stp_print().
@@ -508,7 +537,7 @@
* parse.cxx (parse_symbol): Set print_char bool in print_format.
2007-11-12 Martin Hunt <hunt@redhat.com>
-
+
* tapsets.cxx (build_blacklist): Add __raw_spin_is_locked.
2007-10-25 Josh Stone <joshua.i.stone@intel.com>
@@ -557,13 +586,13 @@
* stapprobes.5.in: Removed C label reference.
Clarified source path requirements for probe
- definitions. Fixed some vertical spacing
- issues.
+ definitions. Fixed some vertical spacing
+ issues.
2007-10-18 Mike Mason <mmlnx@us.ibm.com>
* stapfuncs.5.in: Corrected tokenize description.
- Added task_* functions.
+ Added task_* functions.
2007-10-16 Jim Keniston <jkenisto@us.ibm.com>
diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog
index 53545db2..e9ef2e2d 100644
--- a/runtime/staprun/ChangeLog
+++ b/runtime/staprun/ChangeLog
@@ -1,7 +1,11 @@
+2008-02-21 David Smith <dsmith@redhat.com>
+
+ * staprun_funcs.c (check_path): Small security fix.
+
2008-01-21 Martin Hunt <hunt@redhat.com>
- * symbols.c (send_module): Simplify and use new send_data() function to keep
- longword alignment.
+ * symbols.c (send_module): Simplify and use new send_data()
+ function to keep longword alignment.
2008-01-14 Martin Hunt <hunt@redhat.com>
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index 3a678405..34e12c25 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -277,10 +277,20 @@ check_path(void)
/* Use realpath() to canonicalize the module path. */
if (realpath(modpath, module_realpath) == NULL) {
- perr("Unable to canonicalize path \"%s\"",modpath);
+ perr("Unable to canonicalize path \"%s\"", modpath);
return -1;
}
+ /* To make sure the user can't specify something like
+ * /lib/modules/`uname -r`/systemtapmod.ko, put a '/' on the
+ * end of staplib_dir_realpath. */
+ if (strlen(staplib_dir_realpath) < (PATH_MAX - 1))
+ strcat(staplib_dir_realpath, "/");
+ else {
+ err("Path \"%s\" is too long.", modpath);
+ return -1;
+ }
+
/* Now we've got two canonicalized paths. Make sure
* module_realpath starts with staplib_dir_realpath. */
if (strncmp(staplib_dir_realpath, module_realpath,
diff --git a/stapprobes.5.in b/stapprobes.5.in
index 642ed739..55fcb3c7 100644
--- a/stapprobes.5.in
+++ b/stapprobes.5.in
@@ -363,7 +363,10 @@ The next part names the marker itself:
.BR mark("name") .
The marker name string, which may contain the usual wildcard characters,
is matched against the names given to the marker macros when the kernel
-and/or module was compiled.
+and/or module was compiled. Optionally, you can specify
+.BR format("format") .
+Specifying the marker format string allows differentation between two
+markers with the same name but different marker format strings.
The handler associated with a marker-based probe may read the
optional parameters specified at the macro call site. These are
@@ -372,6 +375,9 @@ named
where NN is the number of parameters supplied by the macro. Number
and string parameters are passed in a type-safe manner.
+The marker format string associated with a marker is available in
+.BR $format .
+
.SS PERFORMANCE MONITORING HARDWARE
The perfmon family of probe points is used to access the performance
diff --git a/tapsets.cxx b/tapsets.cxx
index 358478e6..c5ed6ea1 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -92,7 +92,7 @@ struct be_derived_probe: public derived_probe
// This allows the BEGIN/END/ERROR probes to intermingle.
// But that's OK - they're always treversed with a nested
// "if (type==FOO)" conditional.
- return a->priority < b->priority;
+ return a->priority < b->priority;
}
bool needs_global_locks () { return false; }
@@ -341,8 +341,8 @@ be_derived_probe_group::emit_module_decls (systemtap_session& s)
for (unsigned i=0; i < probes.size(); i++)
{
- s.op->newline () << "{";
- s.op->line() << " .pp="
+ s.op->newline () << "{";
+ s.op->line() << " .pp="
<< lex_cast_qstring (*probes[i]->sole_location()) << ",";
s.op->line() << " .ph=&" << probes[i]->name << ",";
s.op->line() << " .type=" << probes[i]->type;
@@ -757,7 +757,7 @@ struct dwflpp
sess.kernel_release +
string(" ") +
sess.architecture +
- string(" debuginfo"),
+ string(" debuginfo"),
rc);
// XXX: it would be nice if we could do a single
@@ -796,12 +796,12 @@ struct dwflpp
struct module_cache_entry {
Dwfl_Module* mod;
const char* name;
- Dwarf_Addr addr;
+ Dwarf_Addr addr;
};
typedef vector<module_cache_entry> module_cache_t;
module_cache_t module_cache;
- static int module_caching_callback(Dwfl_Module * mod,
+ static int module_caching_callback(Dwfl_Module * mod,
void **,
const char *name,
Dwarf_Addr addr,
@@ -1008,7 +1008,7 @@ struct dwflpp
{
if (sess.verbose > 3)
clog << "skipping line number mismatch "
- << "(" << l_no << " vs " << lineno << ")"
+ << "(" << l_no << " vs " << lineno << ")"
<< " in file '" << srcfile << "'"
<< "\n";
srcsp[i] = 0;
@@ -1246,7 +1246,7 @@ struct dwflpp
lookup_method = "dwarf_entrypc";
rc = dwarf_entrypc (die, addr);
- if (rc)
+ if (rc)
{
lookup_method = "dwarf_lowpc";
rc = dwarf_lowpc (die, addr);
@@ -1281,10 +1281,10 @@ struct dwflpp
lookup_method += ", ignored " + lex_cast<string>(extra) + " more";
}
}
-
+
if (sess.verbose > 2)
clog << "entry-pc lookup (" << lookup_method << ") = 0x" << hex << *addr << dec
- << " (rc " << rc << ")"
+ << " (rc " << rc << ")"
<< endl;
return (rc == 0);
}
@@ -1369,7 +1369,7 @@ struct dwflpp
modname, secname, address);
obstack_printf (pool, "addr; })");
}
- else if (n == 1 && module_name == TOK_KERNEL && secname[0] == '\0')
+ else if (n == 1 && module_name == TOK_KERNEL && secname[0] == '\0')
{
// elfutils' way of telling us that this is a relocatable kernel address, which we
// need to treat the same way here as dwarf_query::add_probe_point does: _stext.
@@ -1559,7 +1559,7 @@ struct dwflpp
while (dwarf_tag (die) == DW_TAG_member)
{
const char *member = (dwarf_diename_integrate (die) ?: "<anonymous>");
-
+
o << " " << member;
if (dwarf_siblingof (die, &die_mem) != 0)
@@ -2095,7 +2095,7 @@ base_query::base_query(systemtap_session & sess,
has_kernel = has_null_param(params, TOK_KERNEL);
if (has_kernel)
module_val = "kernel";
- else
+ else
{
bool has_module = get_string_param(params, TOK_MODULE, module_val);
assert (has_module); // no other options are possible by construction
@@ -2220,7 +2220,7 @@ struct dwarf_query : public base_query
// .statement() probes (something we find out in fairly low-level).
//
// An alternative would be to put some more intellgence into query_cu(),
-// and have it print additional suggestions after finding that
+// and have it print additional suggestions after finding that
// q->dw.iterate_over_srcfile_lines resulted in no new finished_results.
bool
@@ -2237,7 +2237,7 @@ dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int linen
srcfile, lineno, 0,
&srcsp, &nsrcs));
- if (nsrcs != 1)
+ if (nsrcs != 1)
{
if (sess.verbose>4)
clog << "alternative line " << lineno << " rejected: nsrcs=" << nsrcs << endl;
@@ -2356,7 +2356,7 @@ dwarf_query::handle_query_module()
addr = function_num_val;
else
addr = statement_num_val;
-
+
// NB: we don't need to add the module base address or bias
// value here (for reasons that may be coincidental).
dw.query_cu_containing_module_address(addr, this);
@@ -2598,7 +2598,7 @@ dwarf_query::blacklisted_p(const string& funcname,
clog << " skipping - __kprobes";
return true;
}
-
+
// Check probe point against blacklist.
int goodfn = regexec (&blacklist_func, funcname.c_str(), 0, NULL, 0);
if (has_return)
@@ -2618,10 +2618,15 @@ dwarf_query::blacklisted_p(const string& funcname,
string dwarf_query::get_blacklist_section(Dwarf_Addr addr)
{
- Dwarf_Addr baseaddr;
string blacklist_section;
- Elf* elf = dwfl_module_getelf (dw.module, & baseaddr);
- Dwarf_Addr offset = addr - baseaddr;
+ Dwarf_Addr bias;
+ // We prefer dwfl_module_getdwarf to dwfl_module_getelf here,
+ // because dwfl_module_getelf can force costly section relocations
+ // we don't really need, while either will do for this purpose.
+ Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (dw.module, &bias))
+ ?: dwfl_module_getelf (dw.module, &bias));
+
+ Dwarf_Addr offset = addr - bias;
if (elf)
{
Elf_Scn* scn = 0;
@@ -2633,6 +2638,9 @@ string dwarf_query::get_blacklist_section(Dwarf_Addr addr)
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
if (! shdr) continue; // XXX error?
+ if (!(shdr->sh_flags & SHF_ALLOC))
+ continue;
+
GElf_Addr start = shdr->sh_addr;
GElf_Addr end = start + shdr->sh_size;
if (! (offset >= start && offset < end))
@@ -2691,7 +2699,7 @@ dwarf_query::add_probe_point(const string& funcname,
if (blacklist_section != "") clog << " section=" << blacklist_section;
clog << " pc=0x" << hex << addr << dec;
}
-
+
bool bad = blacklisted_p (funcname, filename, line, module, blacklist_section, addr);
if (sess.verbose > 1)
clog << endl;
@@ -2705,7 +2713,7 @@ dwarf_query::add_probe_point(const string& funcname,
if (! bad)
{
- probe = new dwarf_derived_probe(funcname, filename, line,
+ probe = new dwarf_derived_probe(funcname, filename, line,
module, reloc_section, addr, reloc_addr, *this, scope_die);
results.push_back(probe);
}
@@ -2886,7 +2894,7 @@ query_dwarf_inline_instance (Dwarf_Die * die, void * arg)
if (q->sess.verbose>2)
clog << "examining inline instance of " << q->dw.function_name << "\n";
- if ((q->has_function_str && ! q->has_call)
+ if ((q->has_function_str && ! q->has_call)
|| q->has_statement_str)
{
if (q->sess.verbose>2)
@@ -3149,15 +3157,22 @@ query_module (Dwfl_Module *mod,
// While we can tell i686 apart from x86-64, unfortunately
// we can't help confusing i586 vs i686 (both EM_386).
- Dwarf_Addr _junk;
- Elf* elf = dwfl_module_getelf (mod, &_junk);
- Ebl* ebl = ebl_openbackend (elf);
- int elf_machine = ebl_get_elfmachine (ebl);
+ Dwarf_Addr bias;
+ // We prefer dwfl_module_getdwarf to dwfl_module_getelf here,
+ // because dwfl_module_getelf can force costly section relocations
+ // we don't really need, while either will do for this purpose.
+ Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
+ ?: dwfl_module_getelf (mod, &bias));
+
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+ if (em == 0) { q->dw.dwfl_assert ("dwfl_getehdr", dwfl_errno()); }
+ int elf_machine = em->e_machine;
const char* debug_filename = "";
const char* main_filename = "";
- (void) dwfl_module_info (mod, NULL, NULL,
+ (void) dwfl_module_info (mod, NULL, NULL,
NULL, NULL, NULL,
- & main_filename,
+ & main_filename,
& debug_filename);
const string& sess_machine = q->sess.architecture;
string expect_machine;
@@ -3174,7 +3189,7 @@ query_module (Dwfl_Module *mod,
// XXX: fill in some more of these
default: expect_machine = "?"; break;
}
-
+
if (! debug_filename) debug_filename = main_filename;
if (! debug_filename) debug_filename = name;
@@ -3191,7 +3206,7 @@ query_module (Dwfl_Module *mod,
clog << "focused on module '" << q->dw.module_name
<< " = [0x" << hex << q->dw.module_start
<< "-0x" << q->dw.module_end
- << ", bias 0x" << q->dw.module_bias << "]" << dec
+ << ", bias 0x" << q->dw.module_bias << "]" << dec
<< " file " << debug_filename
<< " ELF machine " << expect_machine
<< " (code " << elf_machine << ")"
@@ -3472,7 +3487,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
// this:
// if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
// delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
-
+
ds = new delete_statement;
ds->tok = e->tok;
ds->value = ai_ctr;
@@ -3487,7 +3502,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
ifs->condition = ue;
ifs->thenblock = ds;
ifs->elseblock = NULL;
-
+
add_block->statements.push_back (ifs);
// (3) We need an entry probe that saves the value for us in the
@@ -3556,13 +3571,13 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
// = ${param}
arrayindex* ai_tvar_preinc = new arrayindex;
*ai_tvar_preinc = *ai_tvar_base;
-
+
pre_crement* preinc = new pre_crement;
preinc->tok = e->tok;
preinc->op = "++";
preinc->operand = ai_ctr;
ai_tvar_preinc->indexes.push_back(preinc);
-
+
a = new assignment;
a->tok = e->tok;
a->op = "=";
@@ -3724,7 +3739,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
maxactive_val (q.maxactive_val)
{
// Assert relocation invariants
- if (section == "" && dwfl_addr != addr) // addr should be absolute
+ 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);
@@ -3752,7 +3767,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
// of code, add it to the start of the probe.
if (v.add_block)
this->body->statements.insert(this->body->statements.begin(), v.add_block);
-
+
// 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_probe)
@@ -4134,7 +4149,7 @@ dwarf_builder::build(systemtap_session & sess,
sess.sym_kprobes_text_start = lookup_symbol_address (km, "__kprobes_text_start");
sess.sym_kprobes_text_end = lookup_symbol_address (km, "__kprobes_text_end");
sess.sym_stext = lookup_symbol_address (km, "_stext");
-
+
if (sess.verbose > 2)
{
clog << "control symbols:"
@@ -4151,7 +4166,7 @@ dwarf_builder::build(systemtap_session & sess,
if (q.has_absolute)
{
- // assert guru mode for absolute probes
+ // assert guru mode for absolute probes
if (! q.base_probe->privileged)
{
throw semantic_error ("absolute statement probe in unprivileged script", q.base_probe->tok);
@@ -4160,7 +4175,7 @@ dwarf_builder::build(systemtap_session & sess,
// For kernel.statement(NUM).absolute probe points, we bypass
// all the debuginfo stuff: We just wire up a
// dwarf_derived_probe right here and now.
- dwarf_derived_probe* p =
+ dwarf_derived_probe* p =
new dwarf_derived_probe ("", "", 0, "kernel", "",
q.statement_num_val, q.statement_num_val,
q, 0);
@@ -4196,11 +4211,11 @@ public:
};
-uprobe_derived_probe::uprobe_derived_probe (systemtap_session &s,
+uprobe_derived_probe::uprobe_derived_probe (systemtap_session &s,
probe* p, probe_point* l,
uint64_t pp, uint64_t aa, bool rr):
derived_probe(p, l), process(pp), address(aa), return_p (rr)
-{
+{
s.need_uprobes = true;
}
@@ -4229,7 +4244,7 @@ struct uprobe_builder: public derived_probe_builder
bool b2 = get_param (parameters, TOK_STATEMENT, address);
bool rr = has_null_param (parameters, TOK_RETURN);
assert (b1 && b2); // by pattern_root construction
-
+
finished_results.push_back(new uprobe_derived_probe(sess, base, location,
process, address, rr));
}
@@ -4241,7 +4256,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
{
if (probes.empty()) return;
s.op->newline() << "/* ---- user probes ---- */";
-
+
// If uprobes isn't in the kernel, pull it in from the runtime.
s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)";
s.op->newline() << "#include <linux/uprobes.h>";
@@ -4424,8 +4439,8 @@ timer_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(1);
for (unsigned i=0; i < probes.size(); i++)
{
- s.op->newline () << "{";
- s.op->line() << " .pp="
+ s.op->newline () << "{";
+ s.op->line() << " .pp="
<< lex_cast_qstring (*probes[i]->sole_location()) << ",";
s.op->line() << " .ph=&" << probes[i]->name << ",";
s.op->line() << " .intrv=" << probes[i]->interval << ",";
@@ -4515,7 +4530,7 @@ public:
profile_derived_probe::profile_derived_probe (systemtap_session &, probe* p, probe_point* l):
derived_probe(p, l)
-{
+{
}
@@ -4575,7 +4590,7 @@ profile_derived_probe_group::emit_module_decls (systemtap_session& s)
{
if (i > 0)
{
- // Some lightweight inter-probe context resetting
+ // Some lightweight inter-probe context resetting
// XXX: not quite right: MAXERRORS not respected
s.op->newline() << "c->actionremaining = MAXACTION;";
}
@@ -4594,7 +4609,7 @@ profile_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "}";
s.op->newline() << "struct notifier_block stap_profile_notifier = {"
<< " .notifier_call = & enter_profile_probes };";
-
+
s.op->newline() << "#else";
s.op->newline() << "int enter_profile_probes (struct pt_regs *regs) {";
@@ -4913,7 +4928,7 @@ procfs_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline() << "break;";
s.op->newline(-1) << "}";
- if (has_read_probes)
+ if (has_read_probes)
{
s.op->newline() << "if (spp->read_pp)";
s.op->newline(1) << "_stp_procfs_files[i]->read_proc = &_stp_procfs_read;";
@@ -4946,7 +4961,7 @@ procfs_derived_probe_group::emit_module_exit (systemtap_session& s)
if (probes_by_path.empty())
return;
- s.op->newline() << "_stp_close_procfs();";
+ s.op->newline() << "_stp_close_procfs();";
}
@@ -5069,7 +5084,7 @@ procfs_builder::build(systemtap_session & sess,
//
// probe procfs("command").read {}"
// probe procfs.write {}
-
+
if (! has_procfs)
path = "command";
// If we have a path, we need to validate it.
@@ -5128,11 +5143,11 @@ struct mark_arg
struct mark_derived_probe: public derived_probe
{
mark_derived_probe (systemtap_session &s,
- const string& probe_name, const string& probe_sig,
+ const string& probe_name, const string& probe_format,
probe* base_probe, probe_point* location);
systemtap_session& sess;
- string probe_name, probe_sig;
+ string probe_name, probe_format;
vector <struct mark_arg *> mark_args;
bool target_symbol_seen;
@@ -5140,7 +5155,7 @@ struct mark_derived_probe: public derived_probe
void emit_probe_context_vars (translator_output* o);
void initialize_probe_context_vars (translator_output* o);
- void parse_probe_sig ();
+ void parse_probe_format ();
};
@@ -5236,7 +5251,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e)
break;
}
}
-
+
// Remember that we've seen a target variable.
target_symbol_seen = true;
@@ -5298,7 +5313,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_format (target_symbol* e)
break;
}
}
-
+
string fname = string("_mark_format_get");
// Synthesize a function (if not already synthesized).
@@ -5343,20 +5358,21 @@ mark_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e)
mark_derived_probe::mark_derived_probe (systemtap_session &s,
const string& p_n,
- const string& p_s,
+ const string& p_f,
probe* base, probe_point* loc):
derived_probe (base, new probe_point(*loc) /* .components soon rewritten */),
- sess (s), probe_name (p_n), probe_sig (p_s),
+ sess (s), probe_name (p_n), probe_format (p_f),
target_symbol_seen (false)
{
// create synthetic probe point name; preserve condition
vector<probe_point::component*> comps;
comps.push_back (new probe_point::component ("kernel"));
comps.push_back (new probe_point::component ("mark", new literal_string (probe_name)));
+ comps.push_back (new probe_point::component ("format", new literal_string (probe_format)));
this->sole_location()->components = comps;
- // expand the signature string
- parse_probe_sig();
+ // expand the marker format
+ parse_probe_format();
// Now make a local-variable-expanded copy of the probe body
mark_var_expanding_copy_visitor v (sess, name, mark_args);
@@ -5364,7 +5380,8 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s,
target_symbol_seen = v.target_symbol_seen;
if (sess.verbose > 2)
- clog << "marker-based " << name << " signature=" << probe_sig << endl;
+ clog << "marker-based " << name << " mark=" << probe_name
+ << " fmt='" << probe_format << "'" << endl;
}
@@ -5379,9 +5396,9 @@ skip_atoi(const char **s)
void
-mark_derived_probe::parse_probe_sig()
+mark_derived_probe::parse_probe_format()
{
- const char *fmt = probe_sig.c_str();
+ const char *fmt = probe_format.c_str();
int qualifier; // 'h', 'l', or 'L' for integer fields
mark_arg *arg;
@@ -5606,10 +5623,10 @@ mark_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(1);
for (unsigned i=0; i < probes.size(); i++)
{
- s.op->newline () << "{";
+ s.op->newline () << "{";
s.op->line() << " .name=" << lex_cast_qstring(probes[i]->probe_name)
<< ",";
- s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_sig)
+ s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_format)
<< ",";
s.op->line() << " .pp=" << lex_cast_qstring (*probes[i]->sole_location())
<< ",";
@@ -5618,7 +5635,7 @@ mark_derived_probe_group::emit_module_decls (systemtap_session& s)
}
s.op->newline(-1) << "};";
s.op->newline();
-
+
// Emit the marker callback function
s.op->newline();
@@ -5680,7 +5697,11 @@ struct mark_builder: public derived_probe_builder
{
private:
bool cache_initialized;
- map<std::string, std::string> mark_cache;
+ typedef multimap<string, string> mark_cache_t;
+ typedef multimap<string, string>::const_iterator mark_cache_const_iterator_t;
+ typedef pair<mark_cache_const_iterator_t, mark_cache_const_iterator_t>
+ mark_cache_const_iterator_pair_t;
+ mark_cache_t mark_cache;
public:
mark_builder(): cache_initialized(false) {}
@@ -5712,6 +5733,8 @@ mark_builder::build(systemtap_session & sess,
{
string mark_str_val;
bool has_mark_str = get_param (parameters, "mark", mark_str_val);
+ string mark_format_val;
+ bool has_mark_format = get_param (parameters, "format", mark_format_val);
assert (has_mark_str);
if (! cache_initialized)
@@ -5743,26 +5766,60 @@ mark_builder::build(systemtap_session & sess,
if (sess.verbose>3)
clog << "'" << name << "' '" << module << "' '" << format
<< "'" << endl;
-
- mark_cache[name] = format;
+
+ if (mark_cache.count(name) > 0)
+ {
+ // If we have 2 markers with the same we've got 2 cases:
+ // different format strings or duplicate format strings.
+ // If an existing marker in the cache doesn't have the
+ // same format string, add this marker.
+ mark_cache_const_iterator_pair_t ret;
+ mark_cache_const_iterator_t it;
+ bool matching_format_string = false;
+
+ ret = mark_cache.equal_range(name);
+ for (it = ret.first; it != ret.second; ++it)
+ {
+ if (format == it->second)
+ {
+ matching_format_string = true;
+ break;
+ }
+ }
+
+ if (! matching_format_string)
+ mark_cache.insert(pair<string,string>(name, format));
+ }
+ else
+ mark_cache.insert(pair<string,string>(name, format));
}
while (! module_markers.eof());
module_markers.close();
}
// Search marker list for matching markers
- for (map<string,string>::iterator it = mark_cache.begin();
+ for (mark_cache_const_iterator_t it = mark_cache.begin();
it != mark_cache.end(); it++)
{
// Below, "rc" has negative polarity: zero iff matching.
int rc = fnmatch(mark_str_val.c_str(), it->first.c_str(), 0);
if (! rc)
{
- derived_probe *dp
- = new mark_derived_probe (sess,
- it->first, it->second,
- base, loc);
- finished_results.push_back (dp);
+ bool add_result = true;
+
+ // Match format strings (if the user specified one)
+ if (has_mark_format && fnmatch(mark_format_val.c_str(),
+ it->second.c_str(), 0))
+ add_result = false;
+
+ if (add_result)
+ {
+ derived_probe *dp
+ = new mark_derived_probe (sess,
+ it->first, it->second,
+ base, loc);
+ finished_results.push_back (dp);
+ }
}
}
}
@@ -5866,7 +5923,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(1);
for (unsigned i=0; i < probes.size(); i++)
{
- s.op->newline () << "{";
+ s.op->newline () << "{";
s.op->line() << " .pp=" << lex_cast_qstring (*probes[i]->sole_location()) << ",";
s.op->line() << " .ph=&" << probes[i]->name << ",";
s.op->line() << " .intrv=" << probes[i]->interval << "LL,";
@@ -5880,7 +5937,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "#ifdef STAPCONF_HRTIMER_REL";
s.op->newline() << "#define HRTIMER_MODE_REL HRTIMER_REL";
s.op->newline() << "#endif";
-
+
// The function signature changed in 2.6.21.
s.op->newline() << "#ifdef STAPCONF_HRTIMER_REL";
s.op->newline() << "static int ";
@@ -5889,7 +5946,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "#endif";
s.op->newline() << "enter_hrtimer_probe (struct hrtimer *timer) {";
- s.op->newline(1) << "int rc = HRTIMER_NORESTART;";
+ s.op->newline(1) << "int rc = HRTIMER_NORESTART;";
s.op->newline() << "struct stap_hrtimer_probe *stp = container_of(timer, struct stap_hrtimer_probe, hrtimer);";
s.op->newline() << "if ((atomic_read (&session_state) == STAP_SESSION_STARTING) ||";
s.op->newline() << " (atomic_read (&session_state) == STAP_SESSION_RUNNING)) {";
@@ -5897,7 +5954,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(1) << "timer->expires = ktime_add (timer->expires,";
emit_interval (s.op);
s.op->line() << ");";
- s.op->newline() << "rc = HRTIMER_RESTART;";
+ s.op->newline() << "rc = HRTIMER_RESTART;";
s.op->newline(-1) << "}";
s.op->newline() << "{";
s.op->indent(1);
@@ -6056,7 +6113,7 @@ timer_builder::register_patterns(match_node *root)
root->bind_num("jiffies")->bind(builder);
root->bind_num("jiffies")->bind_num("randomize")->bind(builder);
-
+
root->bind_num("hz")->bind(builder);
}
@@ -6119,7 +6176,7 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
}
}
- ec->code = "THIS->__retvalue = _pfm_pmd_x[" +
+ ec->code = "THIS->__retvalue = _pfm_pmd_x[" +
lex_cast<string>(counter_number) + "].reg_num;";
ec->code += "/* pure */";
fdecl->name = fname;
@@ -6184,7 +6241,7 @@ struct perfmon_builder: public derived_probe_builder
sess.perfmon++;
- // XXX: need to revise when doing sampling
+ // XXX: need to revise when doing sampling
finished_results.push_back(new perfmon_derived_probe(base, location,
sess, event,
perfmon_count));
@@ -6404,7 +6461,7 @@ perfmon_derived_probe_group::emit_module_init (translator_output* o)
/* count events both in kernel and user-space */
inp.pfp_dfl_plm = PFM_PLM0 | PFM_PLM3;
- /* XXX: some cases a perfmon register might be used of watch dog
+ /* XXX: some cases a perfmon register might be used of watch dog
this code doesn't handle that case */
/* figure out the pmcs for the events */
@@ -6513,6 +6570,8 @@ register_standard_tapsets(systemtap_session & s)
// marker-based parts
s.pattern_root->bind("kernel")->bind_str("mark")->bind(new mark_builder());
+ s.pattern_root->bind("kernel")->bind_str("mark")->bind_str("format")
+ ->bind(new mark_builder());
// procfs parts
s.pattern_root->bind("procfs")->bind("read")->bind(new procfs_builder());
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index 6811d912..1760d0aa 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2008-02-21 Will Cohen <wcohen@redhat.com>
+
+ * systemtap.base/beginenderror.exp: Increase timeout for slow machines.
+
+2008-02-20 David Smith <dsmith@redhat.com>
+
+ * systemtap.base/marker.exp: Added tests for marker probe
+ ".format" component.
+
2008-02-19 Frank Ch. Eigler <fche@elastic.org>
PR5766.
diff --git a/testsuite/systemtap.base/beginenderror.exp b/testsuite/systemtap.base/beginenderror.exp
index 9ad596cb..1ab50fdb 100644
--- a/testsuite/systemtap.base/beginenderror.exp
+++ b/testsuite/systemtap.base/beginenderror.exp
@@ -7,6 +7,7 @@ set ok1 0
set ok2 0
set ko 0
expect {
+ -timeout 30
-re {^ERROR:[^\r\n]*\r\n} { incr ok1; exp_continue }
-re {^WARNING:[^\r\n]*\r\n} { incr ok1; exp_continue }
-re {^ok[^\r\n]*\r\n} { incr ok2; exp_continue }
diff --git a/testsuite/systemtap.base/marker.exp b/testsuite/systemtap.base/marker.exp
index 59d6fd33..513ddcd6 100644
--- a/testsuite/systemtap.base/marker.exp
+++ b/testsuite/systemtap.base/marker.exp
@@ -46,6 +46,7 @@ proc stap_compile { TEST_NAME compile script args } {
# Initialize variables
set kernel_markers_found 0
set kernel_marker_names {}
+set kernel_marker_formats {}
set num_marker_found 0
set num_marker_name ""
@@ -54,6 +55,7 @@ set kernel_script {"probe kernel.mark(\"%s\") { }"}
set kernel_script_arg {"probe kernel.mark(\"%s\") { print(%s) }"}
set kernel_script_arg2 {"probe kernel.mark(\"%s\") { %s = 0 }"}
set kernel_script_arg3 {"probe kernel.mark(\"%s\") { print(\$arg1%s) }"}
+set kernel_format_script {"probe kernel.mark(\"%s\").format(\"%s\") { }"}
# Try to read in the marker list from the Module.markers file.
set uname [exec /bin/uname -r]
@@ -63,14 +65,15 @@ if {! [catch {open $path RDONLY} fl]} {
while {[gets $fl s] >= 0} {
# This regexp only picks up markers that contain arguments.
# This helps ensure that K_MARKER04 passes correctly.
- if [regexp {^([^ \t]+)\t[^ \t]+.*(%.+)$} $s match name fmt] {
+ if [regexp {^([^ \t]+)\t[^ \t]+\t(.*%.+)$} $s match name fmt] {
set kernel_markers_found 1
lappend kernel_marker_names $name
+ lappend kernel_marker_formats $fmt
# Look for a marker whose first argument is numeric
# (either '%d', '%u', or '%p'). If we find such a marker,
- # we can run K_MARKER09 and K_MARKER10.
- if {$num_marker_found == 0 && [regexp {^%[dup]} $fmt]} {
+ # we can run K_MARKER09, K_MARKER10, etc.
+ if {$num_marker_found == 0 && [regexp {^[^%]*%[dup]} $fmt]} {
set num_marker_found 1
set num_marker_name $name
}
@@ -236,3 +239,35 @@ if {$kernel_markers_found == 0} {
[lindex $kernel_marker_names 0] {\$format\[0\]}]
stap_compile $TEST_NAME 0 $script
}
+
+set TEST_NAME "K_MARKER15"
+if {$kernel_markers_found == 0} {
+ untested "$TEST_NAME : no kernel markers present"
+} else {
+ # Try compiling a script that specifies the marker format as a
+ # wildcard.
+ set script [format $kernel_format_script \
+ [lindex $kernel_marker_names 0] "*"]
+ stap_compile $TEST_NAME 1 $script
+}
+
+set TEST_NAME "K_MARKER16"
+if {$kernel_markers_found == 0} {
+ untested "$TEST_NAME : no kernel markers present"
+} else {
+ # Try compiling a script that specifies the marker format.
+ set script [format $kernel_format_script \
+ [lindex $kernel_marker_names 0] \
+ [lindex $kernel_marker_formats 0]]
+ stap_compile $TEST_NAME 1 $script
+}
+
+set TEST_NAME "K_MARKER17"
+if {$kernel_markers_found == 0} {
+ untested "$TEST_NAME : no kernel markers present"
+} else {
+ # Try compiling a script that specifies the wrong marker format.
+ set script [format $kernel_format_script \
+ [lindex $kernel_marker_names 0] "foo"]
+ stap_compile $TEST_NAME 0 $script
+}