diff options
author | Josh Stone <jistone@redhat.com> | 2009-09-02 19:09:50 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-09-02 19:09:50 -0700 |
commit | b74789646bfe59131327716357c8b7c1521fa14a (patch) | |
tree | 90647b22c781da3a38dc5be568ed846280b64193 | |
parent | 7a1921492e38221e1552b7698f001fa70d0e0e8b (diff) | |
download | systemtap-steved-b74789646bfe59131327716357c8b7c1521fa14a.tar.gz systemtap-steved-b74789646bfe59131327716357c8b7c1521fa14a.tar.xz systemtap-steved-b74789646bfe59131327716357c8b7c1521fa14a.zip |
PR10572: Allow duplicate function names in a CU
We can't assume that a given function name will only appear once in a
CU. In C++, two functions may have the same name in different classes
or namespaces, or even in the same scope with overloaded parameters.
Even in C, the compiler may generate multiple copies of a single
function with different optimizations.
We now use a multimap for function names, so we shouldn't miss any.
* dwflpp.h (cu_type_cache_t, mod_cu_type_cache_t): New typedef to keep a
normal map for the global_alias_cache.
(cu_function_cache_t): Use a multimap for function names.
* dwflpp.cxx (dwflpp::iterate_over_functions): Walk over the range of
exactly-matching functions.
* tapsets.cxx (query_dwarf_func): Don't abort after seeing an exact
match -- there could be more to come.
-rw-r--r-- | dwflpp.cxx | 30 | ||||
-rw-r--r-- | dwflpp.h | 13 | ||||
-rw-r--r-- | tapsets.cxx | 10 |
3 files changed, 29 insertions, 24 deletions
@@ -106,7 +106,7 @@ dwflpp::~dwflpp() it != cu_inl_function_cache.end(); ++it) delete it->second; - for (mod_cu_function_cache_t::iterator it = global_alias_cache.begin(); + for (mod_cu_type_cache_t::iterator it = global_alias_cache.begin(); it != global_alias_cache.end(); ++it) delete it->second; @@ -594,7 +594,7 @@ dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * int dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg) { - cu_function_cache_t *cache = static_cast<cu_function_cache_t*>(arg); + cu_type_cache_t *cache = static_cast<cu_type_cache_t*>(arg); const char *name = dwarf_diename(die); if (!name) @@ -616,10 +616,10 @@ dwflpp::declaration_resolve(const char *name) if (!name) return NULL; - cu_function_cache_t *v = global_alias_cache[cu->addr]; + cu_type_cache_t *v = global_alias_cache[cu->addr]; if (v == 0) // need to build the cache, just once per encountered module/cu { - v = new cu_function_cache_t; + v = new cu_type_cache_t; global_alias_cache[cu->addr] = v; iterate_over_globals(global_alias_caching_callback, v); if (sess.verbose > 4) @@ -650,8 +650,7 @@ dwflpp::cu_function_caching_callback (Dwarf_Die* func, void *arg) if (!name) return DWARF_CB_OK; - string function_name = name; - (*v)[function_name] = * func; + v->insert(make_pair(string(name), *func)); return DWARF_CB_OK; } @@ -677,14 +676,19 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * mod_info->update_symtab(v); } - cu_function_cache_t::iterator it = v->find(function); - if (it != v->end()) + cu_function_cache_t::iterator it; + cu_function_cache_range_t range = v->equal_range(function); + if (range.first != range.second) { - Dwarf_Die& die = it->second; - if (sess.verbose > 4) - clog << "function cache " << module_name << ":" << cu_name() - << " hit " << function << endl; - return (*callback)(& die, q); + for (it = range.first; it != range.second; ++it) + { + Dwarf_Die& die = it->second; + if (sess.verbose > 4) + clog << "function cache " << module_name << ":" << cu_name() + << " hit " << function << endl; + rc = (*callback)(& die, q); + if (rc != DWARF_CB_OK) break; + } } else if (name_has_wildcard (function)) { @@ -47,8 +47,17 @@ enum info_status { info_unknown, info_present, info_absent }; // module -> cu die[] typedef unordered_map<Dwarf*, std::vector<Dwarf_Die>*> module_cu_cache_t; +// typename -> die +typedef unordered_map<std::string, Dwarf_Die> cu_type_cache_t; + +// cu die -> (typename -> die) +typedef unordered_map<void*, cu_type_cache_t*> mod_cu_type_cache_t; + // function -> die -typedef unordered_map<std::string, Dwarf_Die> cu_function_cache_t; +typedef unordered_multimap<std::string, Dwarf_Die> cu_function_cache_t; +typedef std::pair<cu_function_cache_t::iterator, + cu_function_cache_t::iterator> + cu_function_cache_range_t; // cu die -> (function -> die) typedef unordered_map<void*, cu_function_cache_t*> mod_cu_function_cache_t; @@ -293,7 +302,7 @@ private: * cache is indexed by name. If other declaration lookups were * added to it, it would have to be indexed by name and tag */ - mod_cu_function_cache_t global_alias_cache; + mod_cu_type_cache_t global_alias_cache; static int global_alias_caching_callback(Dwarf_Die *die, void *arg); int iterate_over_globals (int (* callback)(Dwarf_Die *, void *), void * data); diff --git a/tapsets.cxx b/tapsets.cxx index d5c89a02..c136ea0f 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1319,9 +1319,6 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) clog << "checking instances of inline " << q->dw.function_name << "\n"; q->dw.iterate_over_inline_instances (query_dwarf_inline_instance, q); - - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } else if (!q->dw.func_is_inline () && (! q->has_inline)) { @@ -1382,14 +1379,9 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) func.entrypc -= q->dw.module_bias; q->filtered_functions.push_back (func); - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } else assert(0); - - if (q->dw.function_name_final_match (q->function)) - return DWARF_CB_ABORT; } } return DWARF_CB_OK; @@ -4153,7 +4145,7 @@ module_info::update_symtab(cu_function_cache_t *funcs) // if this function is a new alias, then // save it to merge into the function cache if (it->second != fi) - new_funcs[it->second->name] = it->second->die; + new_funcs.insert(make_pair(it->second->name, it->second->die)); } } |