diff options
-rw-r--r-- | tools/perf/util/callchain.c | 54 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 4 |
2 files changed, 58 insertions, 0 deletions
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 2775b752f2fa..d356e73c5622 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1613,3 +1613,57 @@ void callchain_param_setup(u64 sample_type) callchain_param.record_mode = CALLCHAIN_FP; } } + +static bool chain_match(struct callchain_list *base_chain, + struct callchain_list *pair_chain) +{ + enum match_result match; + + match = match_chain_strings(base_chain->srcline, + pair_chain->srcline); + if (match != MATCH_ERROR) + return match == MATCH_EQ; + + match = match_chain_dso_addresses(base_chain->ms.map, + base_chain->ip, + pair_chain->ms.map, + pair_chain->ip); + + return match == MATCH_EQ; +} + +bool callchain_cnode_matched(struct callchain_node *base_cnode, + struct callchain_node *pair_cnode) +{ + struct callchain_list *base_chain, *pair_chain; + bool match = false; + + pair_chain = list_first_entry(&pair_cnode->val, + struct callchain_list, + list); + + list_for_each_entry(base_chain, &base_cnode->val, list) { + if (&pair_chain->list == &pair_cnode->val) + return false; + + if (!base_chain->srcline || !pair_chain->srcline) { + pair_chain = list_next_entry(pair_chain, list); + continue; + } + + match = chain_match(base_chain, pair_chain); + if (!match) + return false; + + pair_chain = list_next_entry(pair_chain, list); + } + + /* + * Say chain1 is ABC, chain2 is ABCD, we consider they are + * not fully matched. + */ + if (pair_chain && (&pair_chain->list != &pair_cnode->val)) + return false; + + return match; +} diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index fe36a9e5ccd1..ad27fc8c7948 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -298,4 +298,8 @@ int callchain_branch_counts(struct callchain_root *root, u64 *abort_count, u64 *cycles_count); void callchain_param_setup(u64 sample_type); + +bool callchain_cnode_matched(struct callchain_node *base_cnode, + struct callchain_node *pair_cnode); + #endif /* __PERF_CALLCHAIN_H */ |