diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/annotate.c | 23 | ||||
-rw-r--r-- | tools/perf/util/auxtrace.c | 4 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 8 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 52 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 3 | ||||
-rw-r--r-- | tools/perf/util/header.c | 8 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 5 | ||||
-rw-r--r-- | tools/perf/util/map.c | 3 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 16 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 1 | ||||
-rw-r--r-- | tools/perf/util/srcline.c | 246 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 5 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 7 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 5 | ||||
-rw-r--r-- | tools/perf/util/trace-event-read.c | 4 | ||||
-rw-r--r-- | tools/perf/util/util.h | 20 |
16 files changed, 347 insertions, 63 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 22cd1dbe724b..11af5f0d56cc 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1307,6 +1307,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil { char linkname[PATH_MAX]; char *build_id_filename; + char *build_id_path = NULL; if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) @@ -1322,8 +1323,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil goto fallback; } + build_id_path = strdup(filename); + if (!build_id_path) + return -1; + + dirname(build_id_path); + if (dso__is_kcore(dso) || - readlink(filename, linkname, sizeof(linkname)) < 0 || + readlink(build_id_path, linkname, sizeof(linkname)) < 0 || strstr(linkname, DSO__NAME_KALLSYMS) || access(filename, R_OK)) { fallback: @@ -1335,6 +1342,7 @@ fallback: __symbol__join_symfs(filename, filename_size, dso->long_name); } + free(build_id_path); return 0; } @@ -1663,18 +1671,23 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, src_line->nr_pcnt = nr_pcnt; for (k = 0; k < nr_pcnt; k++) { + double percent = 0.0; + h = annotation__histogram(notes, evidx + k); - src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum; + if (h->sum) + percent = 100.0 * h->addr[i] / h->sum; - if (src_line->samples[k].percent > percent_max) - percent_max = src_line->samples[k].percent; + if (percent > percent_max) + percent_max = percent; + src_line->samples[k].percent = percent; } if (percent_max <= 0.5) 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/auxtrace.c b/tools/perf/util/auxtrace.c index c5a6e0b12452..78bd632f144d 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1826,7 +1826,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt) filt->addr = start; if (filt->range && !filt->size && !filt->sym_to) { filt->size = size; - no_size = !!size; + no_size = !size; } } @@ -1840,7 +1840,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt) if (err) return err; filt->size = start + size - filt->addr; - no_size = !!size; + no_size = !size; } /* The very last symbol in kallsyms does not imply a particular size */ diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index e528c40739cc..33af67530d30 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -182,13 +182,17 @@ char *build_id_cache__origname(const char *sbuild_id) char buf[PATH_MAX]; char *ret = NULL, *p; size_t offs = 5; /* == strlen("../..") */ + ssize_t len; linkname = build_id_cache__linkname(sbuild_id, NULL, 0); if (!linkname) return NULL; - if (readlink(linkname, buf, PATH_MAX) < 0) + len = readlink(linkname, buf, sizeof(buf) - 1); + if (len <= 0) goto out; + buf[len] = '\0'; + /* The link should be "../..<origpath>/<sbuild_id>" */ p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */ if (p && (p > buf + offs)) { @@ -690,7 +694,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, err = 0; /* Update SDT cache : error is just warned */ - if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) + if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) pr_debug4("Failed to update/scan SDT cache for %s\n", realname); out_free: diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index aba953421a03..d78776a20e80 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 4f4b60f1558a..c56c23dbbf72 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/header.c b/tools/perf/util/header.c index 05714d548584..ef09f26e67da 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -370,15 +370,11 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist __maybe_unused) { char buf[MAXPATHLEN]; - char proc[32]; u32 n; int i, ret; - /* - * actual atual path to perf binary - */ - sprintf(proc, "/proc/%d/exe", getpid()); - ret = readlink(proc, buf, sizeof(buf)); + /* actual path to perf binary */ + ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); if (ret <= 0) return -1; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e3b38f629504..3c4d4d00cb2c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1136,6 +1136,11 @@ void hist_entry__delete(struct hist_entry *he) zfree(&he->mem_info); } + if (he->inline_node) { + inline_node__delete(he->inline_node); + he->inline_node = NULL; + } + zfree(&he->stat_acc); free_srcline(he->srcline); if (he->srcfile && he->srcfile[0]) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 1d9ebcf9e38e..c1870ac365a3 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 8b0d4e39f640..73f3ec1cf2a0 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/sort.h b/tools/perf/util/sort.h index baf20a399f34..e35fb186d048 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -128,6 +128,7 @@ struct hist_entry { }; char *srcline; char *srcfile; + struct inline_node *inline_node; struct symbol *parent; struct branch_info *branch_info; struct hists *hists; diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index b4db3f48e3b0..778ccb5d99d1 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -7,11 +7,58 @@ #include "util/dso.h" #include "util/util.h" #include "util/debug.h" +#include "util/callchain.h" #include "symbol.h" bool srcline_full_filename; +static const char *dso__name(struct dso *dso) +{ + const char *dso_name; + + if (dso->symsrc_filename) + dso_name = dso->symsrc_filename; + else + dso_name = dso->long_name; + + if (dso_name[0] == '[') + return NULL; + + if (!strncmp(dso_name, "/tmp/perf-", 10)) + return NULL; + + return dso_name; +} + +static int inline_list__append(char *filename, char *funcname, int line_nr, + struct inline_node *node, struct dso *dso) +{ + struct inline_list *ilist; + char *demangled; + + ilist = zalloc(sizeof(*ilist)); + if (ilist == NULL) + return -1; + + ilist->filename = filename; + ilist->line_nr = line_nr; + + if (dso != NULL) { + demangled = dso__demangle_sym(dso, 0, funcname); + if (demangled == NULL) { + ilist->funcname = funcname; + } else { + ilist->funcname = demangled; + free(funcname); + } + } + + list_add_tail(&ilist->list, &node->val); + + return 0; +} + #ifdef HAVE_LIBBFD_SUPPORT /* @@ -151,9 +198,17 @@ static void addr2line_cleanup(struct a2l_data *a2l) #define MAX_INLINE_NEST 1024 +static void inline_list__reverse(struct inline_node *node) +{ + struct inline_list *ilist, *n; + + list_for_each_entry_safe_reverse(ilist, n, &node->val, list) + list_move_tail(&ilist->list, &node->val); +} + static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line, struct dso *dso, - bool unwind_inlines) + bool unwind_inlines, struct inline_node *node) { int ret = 0; struct a2l_data *a2l = dso->a2l; @@ -178,8 +233,21 @@ static int addr2line(const char *dso_name, u64 addr, while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, &a2l->funcname, &a2l->line) && - cnt++ < MAX_INLINE_NEST) - ; + cnt++ < MAX_INLINE_NEST) { + + if (node != NULL) { + if (inline_list__append(strdup(a2l->filename), + strdup(a2l->funcname), + a2l->line, node, + dso) != 0) + return 0; + } + } + + if ((node != NULL) && + (callchain_param.order != ORDER_CALLEE)) { + inline_list__reverse(node); + } } if (a2l->found && a2l->filename) { @@ -205,18 +273,68 @@ void dso__free_a2l(struct dso *dso) dso->a2l = NULL; } +static struct inline_node *addr2inlines(const char *dso_name, u64 addr, + struct dso *dso) +{ + char *file = NULL; + unsigned int line = 0; + struct inline_node *node; + + node = zalloc(sizeof(*node)); + if (node == NULL) { + perror("not enough memory for the inline node"); + return NULL; + } + + INIT_LIST_HEAD(&node->val); + node->addr = addr; + + if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node)) + goto out_free_inline_node; + + if (list_empty(&node->val)) + goto out_free_inline_node; + + return node; + +out_free_inline_node: + inline_node__delete(node); + return NULL; +} + #else /* HAVE_LIBBFD_SUPPORT */ +static int filename_split(char *filename, unsigned int *line_nr) +{ + char *sep; + + sep = strchr(filename, '\n'); + if (sep) + *sep = '\0'; + + if (!strcmp(filename, "??:0")) + return 0; + + sep = strchr(filename, ':'); + if (sep) { + *sep++ = '\0'; + *line_nr = strtoul(sep, NULL, 0); + return 1; + } + + return 0; +} + static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line_nr, struct dso *dso __maybe_unused, - bool unwind_inlines __maybe_unused) + bool unwind_inlines __maybe_unused, + struct inline_node *node __maybe_unused) { FILE *fp; char cmd[PATH_MAX]; char *filename = NULL; size_t len; - char *sep; int ret = 0; scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, @@ -233,23 +351,14 @@ static int addr2line(const char *dso_name, u64 addr, goto out; } - sep = strchr(filename, '\n'); - if (sep) - *sep = '\0'; - - if (!strcmp(filename, "??:0")) { - pr_debug("no debugging info in %s\n", dso_name); + ret = filename_split(filename, line_nr); + if (ret != 1) { free(filename); goto out; } - sep = strchr(filename, ':'); - if (sep) { - *sep++ = '\0'; - *file = filename; - *line_nr = strtoul(sep, NULL, 0); - ret = 1; - } + *file = filename; + out: pclose(fp); return ret; @@ -259,6 +368,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused) { } +static struct inline_node *addr2inlines(const char *dso_name, u64 addr, + struct dso *dso __maybe_unused) +{ + FILE *fp; + char cmd[PATH_MAX]; + struct inline_node *node; + char *filename = NULL; + size_t len; + unsigned int line_nr = 0; + + scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, + dso_name, addr); + + fp = popen(cmd, "r"); + if (fp == NULL) { + pr_err("popen failed for %s\n", dso_name); + return NULL; + } + + node = zalloc(sizeof(*node)); + if (node == NULL) { + perror("not enough memory for the inline node"); + goto out; + } + + INIT_LIST_HEAD(&node->val); + node->addr = addr; + + while (getline(&filename, &len, fp) != -1) { + if (filename_split(filename, &line_nr) != 1) { + free(filename); + goto out; + } + + if (inline_list__append(filename, NULL, line_nr, node, + NULL) != 0) + goto out; + + filename = NULL; + } + +out: + pclose(fp); + + if (list_empty(&node->val)) { + inline_node__delete(node); + return NULL; + } + + return node; +} + #endif /* HAVE_LIBBFD_SUPPORT */ /* @@ -268,7 +429,7 @@ void dso__free_a2l(struct dso *dso __maybe_unused) #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; @@ -278,18 +439,11 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, if (!dso->has_srcline) goto out; - if (dso->symsrc_filename) - dso_name = dso->symsrc_filename; - else - dso_name = dso->long_name; - - if (dso_name[0] == '[') - goto out; - - if (!strncmp(dso_name, "/tmp/perf-", 10)) + dso_name = dso__name(dso); + if (dso_name == NULL) goto out; - if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines)) + if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL)) goto out; if (asprintf(&srcline, "%s:%u", @@ -309,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) @@ -325,7 +484,32 @@ 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, show_addr, false); +} + +struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr) { - return __get_srcline(dso, addr, sym, show_sym, false); + const char *dso_name; + + dso_name = dso__name(dso); + if (dso_name == NULL) + return NULL; + + return addr2inlines(dso_name, addr, dso); +} + +void inline_node__delete(struct inline_node *node) +{ + struct inline_list *ilist, *tmp; + + list_for_each_entry_safe(ilist, tmp, &node->val, list) { + list_del_init(&ilist->list); + zfree(&ilist->filename); + zfree(&ilist->funcname); + free(ilist); + } + + free(node); } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 0e660dba58ad..d1a40bb642ff 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -390,6 +390,11 @@ out_elf_end: return 0; } +char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name) +{ + return demangle_sym(dso, kmodule, elf_name); +} + /* * Align offset to 4 bytes as needed for note name and descriptor data. */ diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 11cdde980545..870ef0f0659c 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -373,3 +373,10 @@ int kcore_copy(const char *from_dir __maybe_unused, void symbol__elf_init(void) { } + +char *dso__demangle_sym(struct dso *dso __maybe_unused, + int kmodule __maybe_unused, + char *elf_name __maybe_unused) +{ + return NULL; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 9222c7e702f3..5245d2fb1a0a 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -118,7 +118,8 @@ struct symbol_conf { show_ref_callgraph, hide_unresolved, raw_trace, - report_hierarchy; + report_hierarchy, + inline_name; const char *vmlinux_name, *kallsyms_name, *source_prefix, @@ -305,6 +306,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map); +char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name); + void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel); void symbols__insert(struct rb_root *symbols, struct symbol *sym); void symbols__fixup_duplicate(struct rb_root *symbols); diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 27420159bf69..8a9a677f7576 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -192,7 +192,7 @@ static int read_ftrace_printk(struct pevent *pevent) if (!size) return 0; - buf = malloc(size); + buf = malloc(size + 1); if (buf == NULL) return -1; @@ -201,6 +201,8 @@ static int read_ftrace_printk(struct pevent *pevent) return -1; } + buf[size] = '\0'; + parse_ftrace_printk(pevent, buf, size); free(buf); diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b2cfa47990dc..7cf5752b38fd 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); @@ -364,4 +364,20 @@ int is_printable_array(char *p, unsigned int len); int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); int unit_number__scnprintf(char *buf, size_t size, u64 n); + +struct inline_list { + char *filename; + char *funcname; + unsigned int line_nr; + struct list_head list; +}; + +struct inline_node { + u64 addr; + struct list_head val; +}; + +struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr); +void inline_node__delete(struct inline_node *node); + #endif /* GIT_COMPAT_UTIL_H */ |