diff options
author | Josh Stone <jistone@redhat.com> | 2009-08-11 17:01:35 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-08-11 17:13:49 -0700 |
commit | 857bdfd1bec07003d3d92aaacf6ba578057324ef (patch) | |
tree | 370fb15a1865f9cba0c8129141d543d9093d3ef7 | |
parent | 9922bd3d9ce58712cf570abefbafebaf3f407ffe (diff) | |
download | systemtap-steved-857bdfd1bec07003d3d92aaacf6ba578057324ef.tar.gz systemtap-steved-857bdfd1bec07003d3d92aaacf6ba578057324ef.tar.xz systemtap-steved-857bdfd1bec07003d3d92aaacf6ba578057324ef.zip |
PR10461: Probe identical functions only once
In C++ especially, a function definition in a header may be compiled
into multiple CUs, but the linker will merge those into a single output
function. We don't want to place multiple probes on the same function.
The dupe-detection from the alias code (commit 1c6b77e5) already tracks
identical functions within a CU, so I've just lifted this to instead
track function entrypcs at the module level.
* dwflpp.cxx (dwflpp::iterate_over_functions): Remove dupe checks.
* tapsets.cxx (dwarf_query): Add alias_dupes set to the query.
(dwarf_query::handle_query_module): Reset the dupes for each module.
(query_dwarf_func): Check that we only probe each entrypc once.
-rw-r--r-- | dwflpp.cxx | 10 | ||||
-rw-r--r-- | tapsets.cxx | 14 |
2 files changed, 14 insertions, 10 deletions
@@ -629,9 +629,6 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * } else if (name_has_wildcard (function)) { - // track addresses we've already seen - set<Dwarf_Addr> alias_dupes; - for (it = v->begin(); it != v->end(); it++) { if (pending_interrupts) return DWARF_CB_ABORT; @@ -643,13 +640,6 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * clog << "function cache " << key << " match " << func_name << " vs " << function << endl; - // make sure that this function address hasn't - // already been matched under an aliased name - Dwarf_Addr addr; - if (dwarf_entrypc(&die, &addr) == 0 && - !alias_dupes.insert(addr).second) - continue; - rc = (*callback)(& die, q); if (rc != DWARF_CB_OK) break; } diff --git a/tapsets.cxx b/tapsets.cxx index 8d0e0ab2..9884860a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -548,6 +548,9 @@ struct dwarf_query : public base_query Dwarf_Die *scope_die, Dwarf_Addr addr); + // Track addresses we've already seen in a given module + set<Dwarf_Addr> alias_dupes; + // Extracted parameters. string function_val; @@ -854,6 +857,9 @@ dwarf_query::handle_query_module() // prebuild the symbol table to resolve aliases dw.mod_info->get_symtab(this); + // reset the dupe-checking for each new module + alias_dupes.clear(); + if (dw.mod_info->dwarf_status == info_present) query_module_dwarf(); @@ -1272,6 +1278,14 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) { q->dw.focus_on_function (func); + // make sure that this function address hasn't + // already been matched under an aliased name + Dwarf_Addr addr; + if (!q->dw.func_is_inline() && + dwarf_entrypc(func, &addr) == 0 && + !q->alias_dupes.insert(addr).second) + return DWARF_CB_OK; + if (q->dw.func_is_inline () && (! q->has_call) && (! q->has_return) && (q->has_statement_str || q->has_function_str)) |