This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] dwflpp: register statement.nearest suffix


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]