This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCH] dwflpp: register statement.nearest suffix
- From: Honggyu Kim <hong dot gyu dot kim at lge dot com>
- To: systemtap at sourceware dot org
- Cc: Honggyu Kim <hong dot gyu dot kim at lge dot com>
- Date: Mon, 4 Aug 2014 22:18:40 +0900
- Subject: [PATCH] dwflpp: register statement.nearest suffix
- Authentication-results: sourceware.org; auth=none
If a line number is given in 'statement', line records in dwarf may not
be found for a given line number.
In this case, alternative line numbers were suggested and exited.
With statement.nearest suffix, a kprobe is inserted into the nearest
line number that is available in dwarf line record.
* dwflpp.cxx(dwflpp.cxx::insert_alternative_linenos): Add a new method,
Add an arg "has_nearest" in dwflpp::iterate_over_srcfile_lines
* dwflpp.h(dwflpp.cxx::insert_alternative_linenos): Ditto.
* tapsets.cxx: Add a new suffix statement.nearest
Signed-off-by: Honggyu Kim <hong.gyu.kim@lge.com>
---
dwflpp.cxx | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
dwflpp.h | 9 +++++++
tapsets.cxx | 10 +++++++-
3 files changed, 92 insertions(+), 2 deletions(-)
diff --git a/dwflpp.cxx b/dwflpp.cxx
index e53d5f2..c0b3834 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -1776,6 +1776,72 @@ get_funcs_in_srcfile(base_func_info_map_t& funcs,
return matching_funcs;
}
+void
+dwflpp::insert_alternative_linenos(char const * srcfile,
+ int lineno,
+ base_func_info_map_t& funcs,
+ void (* callback) (Dwarf_Addr,
+ int, void*),
+ void *data)
+{
+ assert(cu);
+ lines_t *cu_lines = get_cu_lines_sorted_by_lineno(srcfile);
+
+ // Look around lineno for linenos with LRs.
+ int lo_try = -1;
+ int hi_try = -1;
+ for (size_t i = 1; i < 6; ++i)
+ {
+ if (lo_try == -1 && functions_have_lineno(funcs, cu_lines, lineno-i))
+ lo_try = lineno - i;
+ if (hi_try == -1 && functions_have_lineno(funcs, cu_lines, lineno+i))
+ hi_try = lineno + i;
+ }
+
+ int new_lineno;
+ if (lo_try > 0 && hi_try > 0)
+ {
+ // pick the nearest line number
+ if (lineno - lo_try < lineno - hi_try)
+ new_lineno = lo_try;
+ else
+ new_lineno = hi_try;
+ }
+ else if (lo_try > 0)
+ {
+ new_lineno = lo_try;
+ }
+ else if (hi_try > 0)
+ {
+ new_lineno = hi_try;
+ }
+ else
+ {
+ stringstream advice;
+ advice << _F("no line records for %s:%d [man error::dwarf]", srcfile, lineno);
+ throw SEMANTIC_ERROR (advice.str());
+ }
+ clog << _F("insert a kprobe at %s:%d (no line record at %s:%d)\n",
+ srcfile, new_lineno, srcfile, lineno);
+
+ // collect lines
+ lines_t matching_lines;
+ collect_lines_for_single_lineno(srcfile, new_lineno, false, /* is_relative */
+ funcs, matching_lines);
+ // call back with matching lines
+ assert (!matching_lines.empty());
+ set<Dwarf_Addr> probed_addrs;
+ for (lines_t::iterator line = matching_lines.begin();
+ line != matching_lines.end(); ++line)
+ {
+ int near_lineno = DWARF_LINENO(*line);
+ Dwarf_Addr addr = DWARF_LINEADDR(*line);
+ bool is_new_addr = probed_addrs.insert(addr).second;
+ if (is_new_addr)
+ callback(addr, near_lineno, data);
+ }
+}
+
template<> void
dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
const vector<int>& linenos,
@@ -1783,6 +1849,7 @@ dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
base_func_info_map_t& funcs,
void (* callback) (Dwarf_Addr,
int, void*),
+ bool has_nearest,
void *data)
{
/* Matching line records (LRs) to user-provided linenos is trickier than it
@@ -1850,7 +1917,13 @@ dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
if (lineno_type == RELATIVE)
// just pick the first function and make it relative to that
lineno += current_funcs[0].decl_line;
- suggest_alternative_linenos(srcfile, lineno, current_funcs);
+
+ if (has_nearest) {
+ // This function inserts a kprobe into the nearest line number
+ // rather than suggesting near line numbers and exiting.
+ insert_alternative_linenos(srcfile, lineno, current_funcs, callback, data);
+ } else
+ suggest_alternative_linenos(srcfile, lineno, current_funcs);
}
}
diff --git a/dwflpp.h b/dwflpp.h
index 2546acf..80dc829 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -323,6 +323,7 @@ struct dwflpp
base_func_info_map_t& funcs,
void (*callback) (Dwarf_Addr,
int, T*),
+ bool has_nearest,
T *data)
{
// See comment block in iterate_over_modules()
@@ -332,6 +333,7 @@ struct dwflpp
funcs,
(void (*)(Dwarf_Addr,
int, void*))callback,
+ has_nearest,
(void*)data);
}
@@ -559,6 +561,12 @@ private:
void suggest_alternative_linenos(char const * srcfile,
int lineno,
base_func_info_map_t& funcs);
+ void insert_alternative_linenos(char const * srcfile,
+ int lineno,
+ base_func_info_map_t& funcs,
+ void (* callback) (Dwarf_Addr,
+ int, void*),
+ void *data);
static int external_function_cu_callback (Dwarf_Die* cu, external_function_query *efq);
static int external_function_func_callback (Dwarf_Die* func, external_function_query *efq);
@@ -710,6 +718,7 @@ dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
base_func_info_map_t& funcs,
void (* callback) (Dwarf_Addr,
int, void*),
+ bool has_nearest,
void *data);
template<> void
dwflpp::iterate_over_labels<void>(Dwarf_Die *begin_die,
diff --git a/tapsets.cxx b/tapsets.cxx
index b7e1c4b..058941d 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -369,6 +369,7 @@ static const string TOK_METHOD("method");
static const string TOK_CLASS("class");;
static const string TOK_CALLEE("callee");;
static const string TOK_CALLEES("callees");;
+static const string TOK_NEAREST("nearest");;
// Can we handle this query with just symbol-table info?
enum dbinfo_reqt
@@ -832,6 +833,8 @@ struct dwarf_query : public base_query
bool has_inline;
bool has_return;
+ bool has_nearest;
+
bool has_maxactive;
long maxactive_val;
@@ -991,6 +994,7 @@ dwarf_query::dwarf_query(probe * base_probe,
has_exported = has_null_param(params, TOK_EXPORTED);
has_inline = has_null_param(params, TOK_INLINE);
has_return = has_null_param(params, TOK_RETURN);
+ has_nearest = has_null_param(params, TOK_NEAREST);
has_maxactive = get_number_param(params, TOK_MAXACTIVE, maxactive_val);
has_absolute = has_null_param(params, TOK_ABSOLUTE);
has_mark = false;
@@ -2169,7 +2173,8 @@ query_cu (Dwarf_Die * cudie, dwarf_query * q)
srcfile != q->filtered_srcfiles.end(); ++srcfile)
q->dw.iterate_over_srcfile_lines(srcfile->c_str(), q->linenos,
q->lineno_type, bfis,
- query_srcfile_line, q);
+ query_srcfile_line,
+ q->has_nearest, q);
}
else
{
@@ -5269,6 +5274,9 @@ dwarf_derived_probe::register_statement_variants(match_node * root,
root
->bind_privilege(privilege)
->bind(dw);
+ root->bind(TOK_NEAREST)
+ ->bind_privilege(privilege)
+ ->bind(dw);
}
void
--
1.7.9.5