Since the branch ip has been added to call stack for easier browsing, this patch adds more branch information. For example, add a flag to indicate this ip is a branch, and also add with the branch flag.
Then we can know if the cursor node represents a branch and know what the branch flag it has. Signed-off-by: Jin Yao <yao....@linux.intel.com> --- tools/perf/util/callchain.c | 11 +++++++-- tools/perf/util/callchain.h | 5 +++- tools/perf/util/machine.c | 56 +++++++++++++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 07fd30b..342ef20 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -730,7 +730,8 @@ merge_chain_branch(struct callchain_cursor *cursor, list_for_each_entry_safe(list, next_list, &src->val, list) { callchain_cursor_append(cursor, list->ip, - list->ms.map, list->ms.sym); + list->ms.map, list->ms.sym, + false, NULL); list_del(&list->list); free(list); } @@ -767,7 +768,8 @@ int callchain_merge(struct callchain_cursor *cursor, } int callchain_cursor_append(struct callchain_cursor *cursor, - u64 ip, struct map *map, struct symbol *sym) + u64 ip, struct map *map, struct symbol *sym, + bool branch, struct branch_flags *flags) { struct callchain_cursor_node *node = *cursor->last; @@ -782,6 +784,11 @@ int callchain_cursor_append(struct callchain_cursor *cursor, node->ip = ip; node->map = map; node->sym = sym; + node->branch = branch; + + if (flags) + memcpy(&node->branch_flags, flags, + sizeof(struct branch_flags)); cursor->nr++; diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 13e7554..40ecf25 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -129,6 +129,8 @@ struct callchain_cursor_node { u64 ip; struct map *map; struct symbol *sym; + bool branch; + struct branch_flags branch_flags; struct callchain_cursor_node *next; }; @@ -183,7 +185,8 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor) } int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, - struct map *map, struct symbol *sym); + struct map *map, struct symbol *sym, + bool branch, struct branch_flags *flags); /* Close a cursor writing session. Initialize for the reader */ static inline void callchain_cursor_commit(struct callchain_cursor *cursor) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 18e4519..adf09ae 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1616,7 +1616,9 @@ static int add_callchain_ip(struct thread *thread, struct symbol **parent, struct addr_location *root_al, u8 *cpumode, - u64 ip) + u64 ip, + bool branch, + struct branch_flags *flags) { struct addr_location al; @@ -1668,7 +1670,8 @@ static int add_callchain_ip(struct thread *thread, if (symbol_conf.hide_unresolved && al.sym == NULL) return 0; - return callchain_cursor_append(cursor, al.addr, al.map, al.sym); + return callchain_cursor_append(cursor, al.addr, al.map, al.sym, + branch, flags); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample, @@ -1747,7 +1750,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, struct ip_callchain *chain = sample->callchain; int chain_nr = min(max_stack, (int)chain->nr); u8 cpumode = PERF_RECORD_MISC_USER; - int i, j, err; + int i, j, err, k; u64 ip; for (i = 0; i < chain_nr; i++) { @@ -1770,25 +1773,45 @@ static int resolve_lbr_callchain_sample(struct thread *thread, * in callchain__printf */ int mix_chain_nr = i + 1 + lbr_nr + 1; + bool branch; + struct branch_flags *flags; for (j = 0; j < mix_chain_nr; j++) { + branch = false; + flags = NULL; + if (callchain_param.order == ORDER_CALLEE) { if (j < i + 1) ip = chain->ips[j]; - else if (j > i + 1) - ip = lbr_stack->entries[j - i - 2].from; - else + else if (j > i + 1) { + k = j - i - 2; + ip = lbr_stack->entries[k].from; + branch = true; + flags = &lbr_stack->entries[k].flags; + } else { ip = lbr_stack->entries[0].to; + branch = true; + flags = &lbr_stack->entries[0].flags; + } } else { - if (j < lbr_nr) - ip = lbr_stack->entries[lbr_nr - j - 1].from; + if (j < lbr_nr) { + k = lbr_nr - j - 1; + ip = lbr_stack->entries[k].from; + branch = true; + flags = &lbr_stack->entries[k].flags; + } else if (j > lbr_nr) ip = chain->ips[i + 1 - (j - lbr_nr)]; - else + else { ip = lbr_stack->entries[0].to; + branch = true; + flags = &lbr_stack->entries[0].flags; + } } - err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); + err = add_callchain_ip(thread, cursor, parent, + root_al, &cpumode, ip, + branch, flags); if (err) return (err < 0) ? err : 0; } @@ -1872,10 +1895,12 @@ static int thread__resolve_callchain_sample(struct thread *thread, for (i = 0; i < nr; i++) { err = add_callchain_ip(thread, cursor, parent, root_al, - NULL, be[i].to); + NULL, be[i].to, + true, &be[i].flags); if (!err) err = add_callchain_ip(thread, cursor, parent, root_al, - NULL, be[i].from); + NULL, be[i].from, + true, &be[i].flags); if (err == -EINVAL) break; if (err) @@ -1903,7 +1928,9 @@ check_calls: if (ip < PERF_CONTEXT_MAX) ++nr_entries; - err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); + err = add_callchain_ip(thread, cursor, parent, + root_al, &cpumode, ip, + false, NULL); if (err) return (err < 0) ? err : 0; @@ -1919,7 +1946,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) if (symbol_conf.hide_unresolved && entry->sym == NULL) return 0; return callchain_cursor_append(cursor, entry->ip, - entry->map, entry->sym); + entry->map, entry->sym, + false, NULL); } static int thread__resolve_callchain_unwind(struct thread *thread, -- 2.7.4