diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r-- | tools/perf/util/annotate.c | 151 |
1 files changed, 66 insertions, 85 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 469eb679fb9d..7eae5488ecea 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -26,10 +26,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp); static void ins__delete(struct ins_operands *ops) { - zfree(&ops->source.raw); - zfree(&ops->source.name); - zfree(&ops->target.raw); - zfree(&ops->target.name); + free(ops->source.raw); + free(ops->source.name); + free(ops->target.raw); + free(ops->target.name); } static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, @@ -185,7 +185,8 @@ static int lock__parse(struct ins_operands *ops) return 0; out_free_ops: - zfree(&ops->locked.ops); + free(ops->locked.ops); + ops->locked.ops = NULL; return 0; } @@ -204,9 +205,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, static void lock__delete(struct ins_operands *ops) { - zfree(&ops->locked.ops); - zfree(&ops->target.raw); - zfree(&ops->target.name); + free(ops->locked.ops); + free(ops->target.raw); + free(ops->target.name); } static struct ins_ops lock_ops = { @@ -255,7 +256,8 @@ static int mov__parse(struct ins_operands *ops) return 0; out_free_source: - zfree(&ops->source.raw); + free(ops->source.raw); + ops->source.raw = NULL; return -1; } @@ -462,12 +464,17 @@ void symbol__annotate_zero_histograms(struct symbol *sym) pthread_mutex_unlock(¬es->lock); } -static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, - struct annotation *notes, int evidx, u64 addr) +int symbol__inc_addr_samples(struct symbol *sym, struct map *map, + int evidx, u64 addr) { unsigned offset; + struct annotation *notes; struct sym_hist *h; + notes = symbol__annotation(sym); + if (notes->src == NULL) + return -ENOMEM; + pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); if (addr < sym->start || addr > sym->end) @@ -484,33 +491,6 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, return 0; } -static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - int evidx, u64 addr) -{ - struct annotation *notes; - - if (sym == NULL || use_browser != 1 || !sort__has_sym) - return 0; - - notes = symbol__annotation(sym); - if (notes->src == NULL) { - if (symbol__alloc_hist(sym) < 0) - return -ENOMEM; - } - - return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); -} - -int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) -{ - return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); -} - -int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) -{ - return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); -} - static void disasm_line__init_ins(struct disasm_line *dl) { dl->ins = ins__find(dl->name); @@ -558,7 +538,8 @@ static int disasm_line__parse(char *line, char **namep, char **rawp) return 0; out_free_name: - zfree(namep); + free(*namep); + *namep = NULL; return -1; } @@ -583,7 +564,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs return dl; out_free_line: - zfree(&dl->line); + free(dl->line); out_delete: free(dl); return NULL; @@ -591,8 +572,8 @@ out_delete: void disasm_line__free(struct disasm_line *dl) { - zfree(&dl->line); - zfree(&dl->name); + free(dl->line); + free(dl->name); if (dl->ins && dl->ins->ops->free) dl->ins->ops->free(&dl->ops); else @@ -844,16 +825,20 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, dl->ops.target.offset = dl->ops.target.addr - map__rip_2objdump(map, sym->start); - /* kcore has no symbols, so add the call target name */ + /* + * kcore has no symbols, so add the call target name if it is on the + * same map. + */ if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) { - struct addr_map_symbol target = { - .map = map, - .addr = dl->ops.target.addr, - }; - - if (!map_groups__find_ams(&target, NULL) && - target.sym->start == target.al_addr) - dl->ops.target.name = strdup(target.sym->name); + struct symbol *s; + u64 ip = dl->ops.target.addr; + + if (ip >= map->start && ip <= map->end) { + ip = map->map_ip(map, ip); + s = map__find_symbol(map, ip, NULL); + if (s && s->start == ip) + dl->ops.target.name = strdup(s->name); + } } disasm__add(¬es->src->source, dl); @@ -894,8 +879,6 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) FILE *file; int err = 0; char symfs_filename[PATH_MAX]; - struct kcore_extract kce; - bool delete_extract = false; if (filename) { snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", @@ -919,7 +902,7 @@ fallback: * cache, or is just a kallsyms file, well, lets hope that this * DSO is the same as when 'perf record' ran. */ - filename = (char *)dso->long_name; + filename = dso->long_name; snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", symbol_conf.symfs, filename); free_filename = false; @@ -957,23 +940,6 @@ fallback: pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso->long_name, sym, sym->name); - if (dso__is_kcore(dso)) { - kce.kcore_filename = symfs_filename; - kce.addr = map__rip_2objdump(map, sym->start); - kce.offs = sym->start; - kce.len = sym->end + 1 - sym->start; - if (!kcore_extract__create(&kce)) { - delete_extract = true; - strlcpy(symfs_filename, kce.extract_filename, - sizeof(symfs_filename)); - if (free_filename) { - free(filename); - free_filename = false; - } - filename = symfs_filename; - } - } - snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 @@ -1006,8 +972,6 @@ fallback: pclose(file); out_free_filename: - if (delete_extract) - kcore_extract__delete(&kce); if (free_filename) free(filename); return err; @@ -1106,21 +1070,24 @@ static void symbol__free_source_line(struct symbol *sym, int len) (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); for (i = 0; i < len; i++) { - free_srcline(src_line->path); + free(src_line->path); src_line = (void *)src_line + sizeof_src_line; } - zfree(¬es->src->lines); + free(notes->src->lines); + notes->src->lines = NULL; } /* Get the filename:line for the colored entries */ static int symbol__get_source_line(struct symbol *sym, struct map *map, struct perf_evsel *evsel, - struct rb_root *root, int len) + struct rb_root *root, int len, + const char *filename) { u64 start; int i, k; int evidx = evsel->idx; + char cmd[PATH_MAX * 2]; struct source_line *src_line; struct annotation *notes = symbol__annotation(sym); struct sym_hist *h = annotation__histogram(notes, evidx); @@ -1148,7 +1115,10 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, start = map__rip_2objdump(map, sym->start); for (i = 0; i < len; i++) { + char *path = NULL; + size_t line_len; u64 offset; + FILE *fp; double percent_max = 0.0; src_line->nr_pcnt = nr_pcnt; @@ -1165,9 +1135,23 @@ 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); + sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); + fp = popen(cmd, "r"); + if (!fp) + goto next; + + if (getline(&path, &line_len, fp) < 0 || !line_len) + goto next_close; + + src_line->path = malloc(sizeof(char) * line_len + 1); + if (!src_line->path) + goto next_close; + + strcpy(src_line->path, path); insert_source_line(&tmp_root, src_line); + next_close: + pclose(fp); next: src_line = (void *)src_line + sizeof_src_line; } @@ -1208,7 +1192,7 @@ static void print_summary(struct rb_root *root, const char *filename) path = src_line->path; color = get_percent_color(percent_max); - color_fprintf(stdout, color, " %s\n", path); + color_fprintf(stdout, color, " %s", path); node = rb_next(node); } @@ -1372,6 +1356,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool full_paths, int min_pcnt, int max_lines) { struct dso *dso = map->dso; + const char *filename = dso->long_name; struct rb_root source_line = RB_ROOT; u64 len; @@ -1381,8 +1366,9 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, len = symbol__size(sym); if (print_lines) { - symbol__get_source_line(sym, map, evsel, &source_line, len); - print_summary(&source_line, dso->long_name); + symbol__get_source_line(sym, map, evsel, &source_line, + len, filename); + print_summary(&source_line, filename); } symbol__annotate_printf(sym, map, evsel, full_paths, @@ -1394,8 +1380,3 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, return 0; } - -int hist_entry__annotate(struct hist_entry *he, size_t privsize) -{ - return symbol__annotate(he->ms.sym, he->ms.map, privsize); -} |