summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-09-03 11:32:59 -0700
committerJosh Stone <jistone@redhat.com>2009-09-03 11:32:59 -0700
commit7fdd3e2c61874abd631de5038d846dffb6f5bc5f (patch)
tree7c24c2e3bc361032b46ef4e119b5378ed7187378
parentb74789646bfe59131327716357c8b7c1521fa14a (diff)
downloadsystemtap-steved-7fdd3e2c61874abd631de5038d846dffb6f5bc5f.tar.gz
systemtap-steved-7fdd3e2c61874abd631de5038d846dffb6f5bc5f.tar.xz
systemtap-steved-7fdd3e2c61874abd631de5038d846dffb6f5bc5f.zip
PR10573: Squash duplicate inline instances
In C++, identical functions included in multiple CUs will get merged at link time into a single instance. We need to make sure that inlines within those merged functions are not probed multiple times. * tapsets.cxx (inline_instance_info::operator<): Used for set support. (dwarf_query::handle_query_module): Clear inline_dupes on each module. (query_dwarf_inline_instance): Squash this inline instance if it's already in the inline_dupes set.
-rw-r--r--dwflpp.h1
-rw-r--r--tapsets.cxx27
2 files changed, 27 insertions, 1 deletions
diff --git a/dwflpp.h b/dwflpp.h
index 431f3c4b..34531071 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -139,6 +139,7 @@ struct inline_instance_info
{
std::memset(&die, 0, sizeof(die));
}
+ bool operator<(const inline_instance_info& other) const;
std::string name;
char const * decl_file;
int decl_line;
diff --git a/tapsets.cxx b/tapsets.cxx
index c136ea0f..15491d55 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -552,6 +552,10 @@ struct dwarf_query : public base_query
// Track addresses we've already seen in a given module
set<Dwarf_Addr> alias_dupes;
+ // Track inlines we've already seen as well
+ // NB: this can't be compared just by entrypc, as inlines can overlap
+ set<inline_instance_info> inline_dupes;
+
// Extracted parameters.
string function_val;
@@ -850,6 +854,7 @@ dwarf_query::handle_query_module()
// reset the dupe-checking for each new module
alias_dupes.clear();
+ inline_dupes.clear();
if (dw.mod_info->dwarf_status == info_present)
query_module_dwarf();
@@ -1248,6 +1253,22 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
}
+bool
+inline_instance_info::operator<(const inline_instance_info& other) const
+{
+ if (entrypc != other.entrypc)
+ return entrypc < other.entrypc;
+
+ if (decl_line != other.decl_line)
+ return decl_line < other.decl_line;
+
+ int cmp = name.compare(other.name);
+ if (!cmp)
+ cmp = strcmp(decl_file, other.decl_file);
+ return cmp < 0;
+}
+
+
static int
query_dwarf_inline_instance (Dwarf_Die * die, void * arg)
{
@@ -1275,7 +1296,11 @@ query_dwarf_inline_instance (Dwarf_Die * die, void * arg)
inl.entrypc = entrypc;
q->dw.function_file (&inl.decl_file);
q->dw.function_line (&inl.decl_line);
- q->filtered_inlines.push_back(inl);
+
+ // make sure that this inline hasn't already
+ // been matched from a different CU
+ if (q->inline_dupes.insert(inl).second)
+ q->filtered_inlines.push_back(inl);
}
}
return DWARF_CB_OK;