From 7d6d0afc24b43829511f3f1d0aeff0fefff56b54 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 16 Sep 2009 19:38:20 -0700 Subject: PR10461: Match C++ scopes for namespaces and classes The function spec for dwarf probes now supports scopes, so you can limit the probes to specific namespaces or classes. Multiple scopes can be specified, and they will be matched progressively outward. probe process("foo").function("std::vector<*>::*") { ... } probe process("foo").function("::global_function") { ... } * dwflpp.cxx (dwflpp::get_parent_scope): New, finds the containing scopes of the specified DIE. (dwflpp::function_scope_matches): New, checks that the scopes containing the function all match the given scope patterns. * tapsets.cxx (dwarf_query::parse_function_spec): Rewrite, now handles multiple scope separators too. (query_dwarf_func): Check that the functions scopes match. --- dwflpp.cxx | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 68e6e97b..a73c3c4c 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -266,6 +266,33 @@ dwflpp::function_name_matches(const string& pattern) } +bool +dwflpp::function_scope_matches(const vector scopes) +{ + // walk up the containing scopes + Dwarf_Die* die = function; + for (int i = scopes.size() - 1; i >= 0; --i) + { + die = get_parent_scope(die); + + // check if this scope matches, and prepend it if so + // NB: a NULL die is the global scope, compared as "" + string name = dwarf_diename(die) ?: ""; + if (name_has_wildcard(scopes[i]) ? + function_name_matches_pattern(name, scopes[i]) : + name == scopes[i]) + function_name = name + "::" + function_name; + else + return false; + + // make sure there's no more if we're at the global scope + if (!die && i > 0) + return false; + } + return true; +} + + static const char *offline_search_modname = NULL; static int offline_search_match_p = 0; @@ -591,6 +618,9 @@ dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die) case DW_TAG_entry_point: case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: parents->insert(make_pair(child.addr, *die)); cache_die_parents(parents, &child); break; @@ -743,6 +773,34 @@ dwflpp::getscopes(Dwarf_Addr pc) } +Dwarf_Die* +dwflpp::get_parent_scope(Dwarf_Die* die) +{ + Dwarf_Die specification; + if (dwarf_attr_die(die, DW_AT_specification, &specification)) + die = &specification; + + cu_die_parent_cache_t *parents = get_die_parents(); + cu_die_parent_cache_t::iterator it = parents->find(die->addr); + while (it != parents->end()) + { + Dwarf_Die* scope = &it->second; + switch (dwarf_tag (scope)) + { + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: + return scope; + + default: + break; + } + it = parents->find(scope->addr); + } + return NULL; +} + + int dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg) { -- cgit