]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - tools/perf/util/callchain.c
perf report: Enable sorting by srcline as key
[karo-tx-linux.git] / tools / perf / util / callchain.c
index aba953421a0329d0de0f2adc5ce1a4599d0fe320..d78776a20e8002da76ff0195e243769df2444e49 100644 (file)
@@ -80,6 +80,10 @@ static int parse_callchain_sort_key(const char *value)
                callchain_param.key = CCKEY_ADDRESS;
                return 0;
        }
+       if (!strncmp(value, "srcline", strlen(value))) {
+               callchain_param.key = CCKEY_SRCLINE;
+               return 0;
+       }
        if (!strncmp(value, "branch", strlen(value))) {
                callchain_param.branch_callstack = 1;
                return 0;
@@ -510,14 +514,51 @@ enum match_result {
        MATCH_GT,
 };
 
+static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
+                                            struct callchain_list *cnode)
+{
+       char *left = get_srcline(cnode->ms.map->dso,
+                                map__rip_2objdump(cnode->ms.map, cnode->ip),
+                                cnode->ms.sym, true, false);
+       char *right = get_srcline(node->map->dso,
+                                 map__rip_2objdump(node->map, node->ip),
+                                 node->sym, true, false);
+       enum match_result ret = MATCH_EQ;
+       int cmp;
+
+       if (left && right)
+               cmp = strcmp(left, right);
+       else if (!left && right)
+               cmp = 1;
+       else if (left && !right)
+               cmp = -1;
+       else if (cnode->ip == node->ip)
+               cmp = 0;
+       else
+               cmp = (cnode->ip < node->ip) ? -1 : 1;
+
+       if (cmp != 0)
+               ret = cmp < 0 ? MATCH_LT : MATCH_GT;
+
+       free_srcline(left);
+       free_srcline(right);
+       return ret;
+}
+
 static enum match_result match_chain(struct callchain_cursor_node *node,
                                     struct callchain_list *cnode)
 {
        struct symbol *sym = node->sym;
        u64 left, right;
 
-       if (cnode->ms.sym && sym &&
-           callchain_param.key == CCKEY_FUNCTION) {
+       if (callchain_param.key == CCKEY_SRCLINE) {
+               enum match_result match = match_chain_srcline(node, cnode);
+
+               if (match != MATCH_ERROR)
+                       return match;
+       }
+
+       if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) {
                left = cnode->ms.sym->start;
                right = sym->start;
        } else {
@@ -911,15 +952,16 @@ out:
 char *callchain_list__sym_name(struct callchain_list *cl,
                               char *bf, size_t bfsize, bool show_dso)
 {
+       bool show_addr = callchain_param.key == CCKEY_ADDRESS;
+       bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
        int printed;
 
        if (cl->ms.sym) {
-               if (callchain_param.key == CCKEY_ADDRESS &&
-                   cl->ms.map && !cl->srcline)
+               if (show_srcline && cl->ms.map && !cl->srcline)
                        cl->srcline = get_srcline(cl->ms.map->dso,
                                                  map__rip_2objdump(cl->ms.map,
                                                                    cl->ip),
-                                                 cl->ms.sym, false);
+                                                 cl->ms.sym, false, show_addr);
                if (cl->srcline)
                        printed = scnprintf(bf, bfsize, "%s %s",
                                        cl->ms.sym->name, cl->srcline);