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] fix incorrect multiple probes for single statement


Given this statement:

probe kernel.statement("*@block/bsg.c:144")

Systemtap is currently dropping four probes in the same location:

Pass 1: parsed user script and 43 library script(s) in 340usr/10sys/356real ms.
probe bsg_release@block/bsg.c:146 kernel section=.text pc=0xc01e96ad
probe bsg_io_schedule@block/bsg.c:144 kernel section=.text pc=0xc01e96ad
probe bsg_complete_all_commands@block/bsg.c:144 kernel section=.text pc=0xc01e96ad
probe bsg_put_device@block/bsg.c:144 kernel section=.text pc=0xc01e96ad
Pass 2: analyzed script: 4 probe(s), 0 function(s), 0 embed(s), 0 global(s) in 440usr/1010sys/1487real ms.

This is because the four functions have overlapping ranges with the
location because of optimisation.  The fix for this is to try to
select heuristically the most likely candidate.  The logical choice
for the heuristic is the function with the smallest overlapping range.
Since the inline and non-inline functions have separate caches, we
look separately for the smallest range of overlap and then choose the
actual smallest function (since an inline must be inside the
instantiated function).

The above statement with this fix applied correctly produces:

Pass 1: parsed user script and 43 library script(s) in 360usr/10sys/375real ms.
probe bsg_io_schedule@block/bsg.c:144 kernel section=.text pc=0xc01e96ad
Pass 2: analyzed script: 1 probe(s), 0 function(s), 0 embed(s), 0 global(s) in 460usr/1100sys/3888real ms.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 tapsets.cxx |   67 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/tapsets.cxx b/tapsets.cxx
index 28e9579..77b21bc 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3431,6 +3431,10 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
 
   int lineno = line.lineno();
 
+  func_info *fi = NULL;
+  inline_instance_info *ii = NULL;
+  Dwarf_Addr f_start = 0, f_end = ~0, i_start = 0, i_end = ~0;
+
   for (func_info_map_t::iterator i = q->filtered_functions.begin();
        i != q->filtered_functions.end(); ++i)
     {
@@ -3438,12 +3442,21 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
 	{
 	  if (q->sess.verbose>3)
 	    clog << "function DIE lands on srcfile\n";
-	  if (q->has_statement_str)
-	    query_statement (i->name, i->decl_file,
-			     lineno, // NB: not q->line !
-                             &(i->die), addr, q);
-	  else
-	    query_func_info (i->entrypc, *i, q);
+
+	  Dwarf_Addr base, start, end;
+	  ptrdiff_t offset = 0;
+	  while ((offset = dwarf_ranges(&i->die, offset, &base,
+					&start, &end)) > 0)
+	    if (addr >= start && addr <= end)
+	      break;
+	  cout << "FUNC " << i->name << " HAS RANGE 0x" << hex
+	       << start << "-" << end << dec << endl;
+	  if (f_start < start && f_end > end)
+	    {
+	      f_end = end;
+	      f_start = start;
+	      fi = &*i;
+	    }
 	}
     }
 
@@ -3455,13 +3468,45 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
 	{
 	  if (q->sess.verbose>3)
 	    clog << "inline instance DIE lands on srcfile\n";
-	  if (q->has_statement_str)
-	    query_statement (i->name, i->decl_file,
-			     q->line[0], &(i->die), addr, q);
-	  else
-	    query_inline_instance_info (*i, q);
+	  Dwarf_Addr base, start, end;
+	  ptrdiff_t offset = 0;
+	  while ((offset = dwarf_ranges(&i->die, offset, &base,
+					&start, &end)) > 0)
+	    if (addr >= start && addr <= end)
+	      break;
+	  cout << "INLINE " << i->name << " HAS RANGE 0x" << hex
+	       << start << "-" << end << dec << endl;
+	  if (i_start < start && i_end > end)
+	    {
+	      i_end = end;
+	      i_start = start;
+	      ii = &*i;
+	    }
 	}
     }
+  // chose the tiniest range we found
+  if (i_end - i_start < f_end - f_start)
+    fi = NULL;
+  else
+    ii = NULL;
+
+  if (fi)
+    {
+      if (q->has_statement_str)
+	query_statement (fi->name, fi->decl_file,
+			 lineno, // NB: not q->line !
+			 &(fi->die), addr, q);
+      else
+	query_func_info (fi->entrypc, *fi, q);
+    }
+  else if (ii)
+    {
+      if (q->has_statement_str)
+	query_statement (ii->name, ii->decl_file,
+			 q->line[0], &(ii->die), addr, q);
+      else
+	query_inline_instance_info (*ii, q);
+    }
 }
 
 
-- 
1.5.6




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