diff options
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 1 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 3 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 3 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 3 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 52 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 3 | ||||
-rw-r--r-- | tools/perf/util/map.c | 3 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 16 | ||||
-rw-r--r-- | tools/perf/util/srcline.c | 11 | ||||
-rw-r--r-- | tools/perf/util/util.h | 4 |
10 files changed, 78 insertions, 21 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 248bba4..37a1759 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -235,6 +235,7 @@ OPTIONS sort_key can be: - function: compare on functions (default) - address: compare on individual code addresses + - srcline: compare on source filename and line number branch can be: - branch: include last branch information in callgraph when available. diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 62ecaeb..da24072 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -851,7 +851,8 @@ static int hist_browser__show_inline(struct hist_browser *browser, if (ui_browser__is_current_entry(&browser->b, row)) color = HE_COLORSET_SELECTED; - if (callchain_param.key == CCKEY_ADDRESS) { + if (callchain_param.key == CCKEY_ADDRESS || + callchain_param.key == CCKEY_SRCLINE) { if (ilist->filename != NULL) scnprintf(buf, sizeof(buf), "%s:%d (inline)", diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 6128f48..d52d5f6 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -52,7 +52,8 @@ static size_t inline__fprintf(struct map *map, u64 ip, int left_margin, ret += fprintf(fp, " "); } - if (callchain_param.key == CCKEY_ADDRESS) { + if (callchain_param.key == CCKEY_ADDRESS || + callchain_param.key == CCKEY_SRCLINE) { if (ilist->filename != NULL) ret += fprintf(fp, "%s:%d (inline)", ilist->filename, diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 22cd1db..3d0263e 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1674,7 +1674,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next; offset = start + i; - src_line->path = get_srcline(map->dso, offset, NULL, false); + src_line->path = get_srcline(map->dso, offset, NULL, + false, true); insert_source_line(&tmp_root, src_line); next: diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index aba9534..d78776a 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -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); diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 4f4b60f..c56c23d 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -77,7 +77,8 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *, enum chain_key { CCKEY_FUNCTION, - CCKEY_ADDRESS + CCKEY_ADDRESS, + CCKEY_SRCLINE }; enum chain_value { diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 1d9ebcf..c1870ac 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -405,7 +405,8 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, if (map && map->dso) { srcline = get_srcline(map->dso, - map__rip_2objdump(map, addr), NULL, true); + map__rip_2objdump(map, addr), NULL, + true, true); if (srcline != SRCLINE_UNKNOWN) ret = fprintf(fp, "%s%s", prefix, srcline); free_srcline(srcline); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0d4e3..73f3ec1 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -323,7 +323,7 @@ char *hist_entry__get_srcline(struct hist_entry *he) return SRCLINE_UNKNOWN; return get_srcline(map->dso, map__rip_2objdump(map, he->ip), - he->ms.sym, true); + he->ms.sym, true, true); } static int64_t @@ -366,7 +366,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) left->branch_info->srcline_from = get_srcline(map->dso, map__rip_2objdump(map, left->branch_info->from.al_addr), - left->branch_info->from.sym, true); + left->branch_info->from.sym, + true, true); } if (!right->branch_info->srcline_from) { struct map *map = right->branch_info->from.map; @@ -376,7 +377,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->srcline_from = get_srcline(map->dso, map__rip_2objdump(map, right->branch_info->from.al_addr), - right->branch_info->from.sym, true); + right->branch_info->from.sym, + true, true); } return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); } @@ -407,7 +409,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) left->branch_info->srcline_to = get_srcline(map->dso, map__rip_2objdump(map, left->branch_info->to.al_addr), - left->branch_info->from.sym, true); + left->branch_info->from.sym, + true, true); } if (!right->branch_info->srcline_to) { struct map *map = right->branch_info->to.map; @@ -417,7 +420,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->srcline_to = get_srcline(map->dso, map__rip_2objdump(map, right->branch_info->to.al_addr), - right->branch_info->to.sym, true); + right->branch_info->to.sym, + true, true); } return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); } @@ -448,7 +452,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e) return no_srcfile; sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), - e->ms.sym, false, true); + e->ms.sym, false, true, true); if (!strcmp(sf, SRCLINE_UNKNOWN)) return no_srcfile; p = strchr(sf, ':'); diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 3ce28f7..778ccb5 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -429,7 +429,7 @@ out: #define A2L_FAIL_LIMIT 123 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, - bool show_sym, bool unwind_inlines) + bool show_sym, bool show_addr, bool unwind_inlines) { char *file = NULL; unsigned line = 0; @@ -463,6 +463,11 @@ out: dso->has_srcline = 0; dso__free_a2l(dso); } + + if (!show_addr) + return (show_sym && sym) ? + strndup(sym->name, sym->namelen) : NULL; + if (sym) { if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", addr - sym->start) < 0) @@ -479,9 +484,9 @@ void free_srcline(char *srcline) } char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, - bool show_sym) + bool show_sym, bool show_addr) { - return __get_srcline(dso, addr, sym, show_sym, false); + return __get_srcline(dso, addr, sym, show_sym, show_addr, false); } struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr) diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index cc0700d..7cf5752 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -287,9 +287,9 @@ struct symbol; extern bool srcline_full_filename; char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, - bool show_sym); + bool show_sym, bool show_addr); char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, - bool show_sym, bool unwind_inlines); + bool show_sym, bool show_addr, bool unwind_inlines); void free_srcline(char *srcline); int perf_event_paranoid(void); |