diff options
author | Josh Stone <jistone@redhat.com> | 2009-09-16 19:38:20 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-09-16 19:38:20 -0700 |
commit | 7d6d0afc24b43829511f3f1d0aeff0fefff56b54 (patch) | |
tree | fa0e55f71448e92074c5c5ef8bde4098bdf76fb7 /dwflpp.cxx | |
parent | 04ddd303348c0ffb71c6f57eacb2282bd1d61b3a (diff) | |
download | systemtap-steved-7d6d0afc24b43829511f3f1d0aeff0fefff56b54.tar.gz systemtap-steved-7d6d0afc24b43829511f3f1d0aeff0fefff56b54.tar.xz systemtap-steved-7d6d0afc24b43829511f3f1d0aeff0fefff56b54.zip |
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.
Diffstat (limited to 'dwflpp.cxx')
-rw-r--r-- | dwflpp.cxx | 58 |
1 files changed, 58 insertions, 0 deletions
@@ -266,6 +266,33 @@ dwflpp::function_name_matches(const string& pattern) } +bool +dwflpp::function_scope_matches(const vector<string> 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) { |