summaryrefslogtreecommitdiffstats
path: root/dwflpp.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-09-16 19:38:20 -0700
committerJosh Stone <jistone@redhat.com>2009-09-16 19:38:20 -0700
commit7d6d0afc24b43829511f3f1d0aeff0fefff56b54 (patch)
treefa0e55f71448e92074c5c5ef8bde4098bdf76fb7 /dwflpp.cxx
parent04ddd303348c0ffb71c6f57eacb2282bd1d61b3a (diff)
downloadsystemtap-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.cxx58
1 files changed, 58 insertions, 0 deletions
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<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)
{