summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStan Cox <scox@redhat.com>2008-06-23 12:37:06 -0400
committerStan Cox <scox@redhat.com>2008-06-23 12:37:06 -0400
commit879eb9e932d2ffac5c67e5e2b9bbedfc7b92a229 (patch)
treed9a15179728b68913a47c3a1be76a4e3516c1478
parentdac6e2425733594e44450188d7e4446285d7c71e (diff)
downloadsystemtap-steved-879eb9e932d2ffac5c67e5e2b9bbedfc7b92a229.tar.gz
systemtap-steved-879eb9e932d2ffac5c67e5e2b9bbedfc7b92a229.tar.xz
systemtap-steved-879eb9e932d2ffac5c67e5e2b9bbedfc7b92a229.zip
Add kernel.statement("Func@File:*) and kernel.statement("Func@File:X-Y)
-rw-r--r--ChangeLog8
-rw-r--r--tapsets.cxx194
-rw-r--r--testsuite/ChangeLog5
-rw-r--r--testsuite/systemtap.base/stmt_rel.exp1
-rw-r--r--testsuite/systemtap.base/stmt_rel.stp29
5 files changed, 150 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index e80c6465..6db66597 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-06-23 Stan Cox <scox@redhat.com>
+
+ * tapsets.cxx (enum line_t): Add RANGE and WILDCARD.
+ (iterate_over_srcfile_lines): Change lineno parm to lines[].
+ Support RANGE and WILDCARD.
+ (dwarf_query): Change line to line[]
+ (dwarf_query::parse_function_spec): Parse RANGE and WILDCARD.
+
2008-06-20 wcohen <wcohen@redhat.com>
* stapfuncs.5.in: Add documentation for tapset/dev.stp functions.
diff --git a/tapsets.cxx b/tapsets.cxx
index 7bfe8b4e..3f9291f2 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -608,6 +608,8 @@ dwarf_diename_integrate (Dwarf_Die *die)
return dwarf_formstring (dwarf_attr_integrate (die, DW_AT_name, &attr_mem));
}
+enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD };
+
struct dwflpp
{
systemtap_session & sess;
@@ -1135,9 +1137,9 @@ struct dwflpp
bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno);
void iterate_over_srcfile_lines (char const * srcfile,
- int lineno,
+ int lines[2],
bool need_single_match,
- bool line_type_relative,
+ enum line_t line_type,
void (* callback) (const dwarf_line_t& line,
void * arg),
void *data)
@@ -1145,10 +1147,11 @@ struct dwflpp
Dwarf_Line **srcsp = NULL;
size_t nsrcs = 0;
dwarf_query * q = static_cast<dwarf_query *>(data);
+ int lineno = lines[0];
get_module_dwarf();
- if (line_type_relative)
+ if (line_type == RELATIVE)
{
Dwarf_Addr addr;
Dwarf_Line *line;
@@ -1160,95 +1163,95 @@ struct dwflpp
dwarf_assert ("dwarf_lineno", dwarf_lineno (line, &line_number));
lineno += line_number;
}
+ else if (line_type == WILDCARD)
+ function_line (&lineno);
+
+ for (int l = lineno; ; l = l + 1)
+ {
+ dwarf_assert ("dwarf_getsrc_file",
+ dwarf_getsrc_file (module_dwarf,
+ srcfile, l, 0,
+ &srcsp, &nsrcs));
- dwarf_assert ("dwarf_getsrc_file",
- dwarf_getsrc_file (module_dwarf,
- srcfile, lineno, 0,
- &srcsp, &nsrcs));
+ if (line_type == WILDCARD || line_type == RANGE)
+ {
+ Dwarf_Addr line_addr;
+ dwarf_lineno (srcsp [0], &lineno);
+ if (lineno != l)
+ continue;
+ dwarf_lineaddr (srcsp [0], &line_addr);
+ if (dwarf_haspc (function, line_addr) != 1)
+ break;
+ }
- // NB: Formerly, we used to filter, because:
+ // NB: Formerly, we used to filter, because:
- // dwarf_getsrc_file gets one *near hits* for line numbers, not
- // exact matches. For example, an existing file but a nonexistent
- // line number will be rounded up to the next definition in that
- // file. This may be similar to the GDB breakpoint algorithm, but
- // we don't want to be so fuzzy in systemtap land. So we filter.
+ // dwarf_getsrc_file gets one *near hits* for line numbers, not
+ // exact matches. For example, an existing file but a nonexistent
+ // line number will be rounded up to the next definition in that
+ // file. This may be similar to the GDB breakpoint algorithm, but
+ // we don't want to be so fuzzy in systemtap land. So we filter.
- // But we now see the error of our ways, and skip this filtering.
+ // But we now see the error of our ways, and skip this filtering.
- // XXX: the code also fails to match e.g. inline function
- // definitions when the srcfile is a header file rather than the
- // CU name.
+ // XXX: the code also fails to match e.g. inline function
+ // definitions when the srcfile is a header file rather than the
+ // CU name.
- size_t remaining_nsrcs = nsrcs;
-#if 0
- for (size_t i = 0; i < nsrcs; ++i)
- {
- int l_no;
- Dwarf_Line* l = srcsp[i];
- dwarf_assert ("dwarf_lineno", dwarf_lineno (l, & l_no));
- if (l_no != lineno)
- {
- if (sess.verbose > 3)
- clog << "skipping line number mismatch "
- << "(" << l_no << " vs " << lineno << ")"
- << " in file '" << srcfile << "'"
- << "\n";
- srcsp[i] = 0;
- remaining_nsrcs --;
- }
- }
-#endif
+ size_t remaining_nsrcs = nsrcs;
- if (need_single_match && remaining_nsrcs > 1)
- {
- // We wanted a single line record (a unique address for the
- // line) and we got a bunch of line records. We're going to
- // skip this probe (throw an exception) but before we throw
- // we're going to look around a bit to see if there's a low or
- // high line number nearby which *doesn't* have this problem,
- // so we can give the user some advice.
-
- int lo_try = -1;
- int hi_try = -1;
- for (size_t i = 1; i < 6; ++i)
+ if (need_single_match && remaining_nsrcs > 1)
{
- if (lo_try == -1 && has_single_line_record(q, srcfile, lineno - i))
- lo_try = lineno - i;
+ // We wanted a single line record (a unique address for the
+ // line) and we got a bunch of line records. We're going to
+ // skip this probe (throw an exception) but before we throw
+ // we're going to look around a bit to see if there's a low or
+ // high line number nearby which *doesn't* have this problem,
+ // so we can give the user some advice.
+
+ int lo_try = -1;
+ int hi_try = -1;
+ for (size_t i = 1; i < 6; ++i)
+ {
+ if (lo_try == -1 && has_single_line_record(q, srcfile, lineno - i))
+ lo_try = lineno - i;
- if (hi_try == -1 && has_single_line_record(q, srcfile, lineno + i))
- hi_try = lineno + i;
- }
+ if (hi_try == -1 && has_single_line_record(q, srcfile, lineno + i))
+ hi_try = lineno + i;
+ }
- stringstream advice;
- advice << "multiple addresses for " << srcfile << ":" << lineno;
- if (lo_try > 0 || hi_try > 0)
- {
- advice << " (try ";
- if (lo_try > 0)
- advice << srcfile << ":" << lo_try;
- if (lo_try > 0 && hi_try > 0)
- advice << " or ";
- if (hi_try > 0)
- advice << srcfile << ":" << hi_try;
- advice << ")";
- }
- throw semantic_error (advice.str());
- }
+ stringstream advice;
+ advice << "multiple addresses for " << srcfile << ":" << lineno;
+ if (lo_try > 0 || hi_try > 0)
+ {
+ advice << " (try ";
+ if (lo_try > 0)
+ advice << srcfile << ":" << lo_try;
+ if (lo_try > 0 && hi_try > 0)
+ advice << " or ";
+ if (hi_try > 0)
+ advice << srcfile << ":" << hi_try;
+ advice << ")";
+ }
+ throw semantic_error (advice.str());
+ }
- try
- {
- for (size_t i = 0; i < nsrcs; ++i)
+ try
{
- if (pending_interrupts) return;
- if (srcsp [i]) // skip over mismatched lines
- callback (dwarf_line_t(srcsp[i]), data);
+ for (size_t i = 0; i < nsrcs; ++i)
+ {
+ if (pending_interrupts) return;
+ if (srcsp [i]) // skip over mismatched lines
+ callback (dwarf_line_t(srcsp[i]), data);
+ }
}
- }
- catch (...)
- {
- free (srcsp);
- throw;
+ catch (...)
+ {
+ free (srcsp);
+ throw;
+ }
+ if (line_type != WILDCARD || l == lines[1])
+ break;
}
free (srcsp);
}
@@ -2338,8 +2341,6 @@ base_query::get_number_param(literal_map_t const & params,
typedef map<Dwarf_Addr, inline_instance_info> inline_instance_map_t;
typedef map<Dwarf_Addr, func_info> func_info_map_t;
-enum line_t { ABSOLUTE, RELATIVE };
-
struct dwarf_query : public base_query
{
dwarf_query(systemtap_session & sess,
@@ -2407,7 +2408,7 @@ struct dwarf_query : public base_query
string function;
string file;
line_t line_type;
- int line;
+ int line[2];
bool query_done; // Found exact match
set<char const *> filtered_srcfiles;
@@ -2873,7 +2874,8 @@ dwarf_query::parse_function_spec(string & spec)
function.clear();
file.clear();
- line = 0;
+ line[0] = 0;
+ line[1] = 0;
while (i != e && *i != '@')
{
@@ -2897,7 +2899,12 @@ dwarf_query::parse_function_spec(string & spec)
while (i != e && *i != ':' && *i != '+')
file += *i++;
if (*i == ':')
- line_type = ABSOLUTE;
+ {
+ if (*(i + 1) == '*')
+ line_type = WILDCARD;
+ else
+ line_type = ABSOLUTE;
+ }
else if (*i == '+')
line_type = RELATIVE;
@@ -2916,7 +2923,22 @@ dwarf_query::parse_function_spec(string & spec)
try
{
- line = lex_cast<int>(string(i, e));
+ if (line_type != WILDCARD)
+ {
+ string::const_iterator dash = i;
+
+ while (dash != e && *dash != '-')
+ dash++;
+ if (dash == e)
+ line[0] = line[1] = lex_cast<int>(string(i, e));
+ else
+ {
+ line_type = RANGE;
+ line[0] = lex_cast<int>(string(i, dash));
+ line[1] = lex_cast<int>(string(dash + 1, e));
+ }
+ }
+
if (sess.verbose>2)
clog << "parsed '" << spec
<< "' -> func '"<< function
@@ -3308,7 +3330,7 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
clog << "inline instance DIE lands on srcfile\n";
if (q->has_statement_str)
query_statement (i->second.name, i->second.decl_file,
- q->line, &(i->second.die), addr, q);
+ q->line[0], &(i->second.die), addr, q);
else
query_inline_instance_info (i->first, i->second, q);
}
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index 9ab2a353..4fda9c5f 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-06-23 Stan Cox <scox@redhat.com>
+
+ * systemtap.base/stmt_rel.stp: Added test for
+ kernel.statement("Func@File:*")
+
2008-06-18 Josh Stone <joshua.i.stone@intel.com>
* systemtap.base/optim_voidstmt.stp: Add tests for various statement
diff --git a/testsuite/systemtap.base/stmt_rel.exp b/testsuite/systemtap.base/stmt_rel.exp
index e929b292..a13631e6 100644
--- a/testsuite/systemtap.base/stmt_rel.exp
+++ b/testsuite/systemtap.base/stmt_rel.exp
@@ -4,6 +4,7 @@ set test "stmt_rel"
set ::result_string {PASS bio_init
PASS line number
PASS address
+PASS wildcard
}
stap_run2 $srcdir/$subdir/$test.stp
diff --git a/testsuite/systemtap.base/stmt_rel.stp b/testsuite/systemtap.base/stmt_rel.stp
index a5f1cc2a..43c38594 100644
--- a/testsuite/systemtap.base/stmt_rel.stp
+++ b/testsuite/systemtap.base/stmt_rel.stp
@@ -1,4 +1,5 @@
-global stack2, stack2pp, stack2func
+global stack2, stack2pp, stack2func, stack3, stack3pp, stack3func
+global wildcardpp, wild_count
probe kernel.statement("bio_init@fs/bio.c+2") {
stack2 = tokenize(backtrace(), " ")
@@ -9,6 +10,17 @@ probe kernel.statement("bio_init@fs/bio.c+3") {
stack3 = tokenize(backtrace(), " " )
stack3func = probefunc()
stack3pp = pp()
+}
+
+probe kernel.statement("bio_put@fs/bio.c:*") {
+ line = tokenize(pp(),":")
+ line = tokenize("",":")
+ line = substr(line,0,strlen(line)-2)
+ wildcardpp[strtol(line,10)]++
+
+ if (wild_count++ <= 10) {
+ next
+ }
stack2pp = tokenize(stack2pp,":")
stack2pp = tokenize("",":")
@@ -18,6 +30,7 @@ probe kernel.statement("bio_init@fs/bio.c+3") {
stack2line = strtol (substr(stack2pp,0,strlen(stack2pp)-2), 10)
stack3line = strtol (substr(stack3pp,0,strlen(stack3pp)-2), 10)
+ # Did functions for both bio_init probes match?
if (stack2func == stack3func) {
printf ("PASS %s\n", stack2func)
}
@@ -25,6 +38,7 @@ probe kernel.statement("bio_init@fs/bio.c+3") {
printf ("FAIL %s %s\n", stack2func, stack3func)
}
+ # Was line # for bio_init probe +2 < line # for bio_init probe +3?
if ((stack2line + 1) == stack3line) {
printf ("PASS line number\n")
}
@@ -32,6 +46,7 @@ probe kernel.statement("bio_init@fs/bio.c+3") {
printf ("FAIL line number %d %d\n", stack2line, stack3line)
}
+ # Was address for bio_init probe +2 < address for bio_init probe +3?
if (stack2 < stack3) {
printf ("PASS address\n")
}
@@ -39,5 +54,17 @@ probe kernel.statement("bio_init@fs/bio.c+3") {
printf ("FAIL address %s %s\n", stack2, stack3)
}
+ # Did wildcard probe hit at least 5 different statements?
+ foreach ([i] in wildcardpp) {
+ statement_count += 1
+ }
+ if (statement_count >= 5) {
+ printf ("PASS wildcard\n")
+ }
+ else
+ {
+ printf ("FAIL wildcard %d\n", statement_count)
+ }
+
exit()
}