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 if 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 df85b9e..c2d9d9f 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,
@@ -1757,7 +1760,9 @@ static int resolve_lbr_callchain_sample(struct thread 
*thread,
        /* LBR only affects the user callchain */
        if (i != chain_nr) {
                struct branch_stack *lbr_stack = sample->branch_stack;
-               int lbr_nr = lbr_stack->nr, j;
+               int lbr_nr = lbr_stack->nr, j, k;
+               bool branch;
+               struct branch_flags *flags;
                /*
                 * LBR callstack can only get user call chain.
                 * The mix_chain_nr is kernel call chain
@@ -1772,23 +1777,41 @@ static int resolve_lbr_callchain_sample(struct thread 
*thread,
 
                for (j = 0; j < mix_chain_nr; j++) {
                        int err;
+                       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

Reply via email to