diff options
Diffstat (limited to 'tools/perf/util')
47 files changed, 410 insertions, 325 deletions
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index e6d134773d0a..c0b43ee40d95 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c @@ -55,8 +55,7 @@ int split_cmdline(char *cmdline, const char ***argv) src++; c = cmdline[src]; if (!c) { - free(*argv); - *argv = NULL; + zfree(argv); return error("cmdline ends with \\"); } } @@ -68,8 +67,7 @@ int split_cmdline(char *cmdline, const char ***argv) cmdline[dst] = 0; if (quoted) { - free(*argv); - *argv = NULL; + zfree(argv); return error("unclosed quote"); } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 0fcd81ea31ae..469eb679fb9d 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) { - free(ops->source.raw); - free(ops->source.name); - free(ops->target.raw); - free(ops->target.name); + zfree(&ops->source.raw); + zfree(&ops->source.name); + zfree(&ops->target.raw); + zfree(&ops->target.name); } static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, @@ -185,8 +185,7 @@ static int lock__parse(struct ins_operands *ops) return 0; out_free_ops: - free(ops->locked.ops); - ops->locked.ops = NULL; + zfree(&ops->locked.ops); return 0; } @@ -205,9 +204,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, static void lock__delete(struct ins_operands *ops) { - free(ops->locked.ops); - free(ops->target.raw); - free(ops->target.name); + zfree(&ops->locked.ops); + zfree(&ops->target.raw); + zfree(&ops->target.name); } static struct ins_ops lock_ops = { @@ -256,8 +255,7 @@ static int mov__parse(struct ins_operands *ops) return 0; out_free_source: - free(ops->source.raw); - ops->source.raw = NULL; + zfree(&ops->source.raw); return -1; } @@ -464,17 +462,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym) pthread_mutex_unlock(¬es->lock); } -int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - int evidx, u64 addr) +static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, + struct annotation *notes, 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) @@ -491,6 +484,33 @@ 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); @@ -538,8 +558,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp) return 0; out_free_name: - free(*namep); - *namep = NULL; + zfree(namep); return -1; } @@ -564,7 +583,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs return dl; out_free_line: - free(dl->line); + zfree(&dl->line); out_delete: free(dl); return NULL; @@ -572,8 +591,8 @@ out_delete: void disasm_line__free(struct disasm_line *dl) { - free(dl->line); - free(dl->name); + zfree(&dl->line); + zfree(&dl->name); if (dl->ins && dl->ins->ops->free) dl->ins->ops->free(&dl->ops); else @@ -1091,8 +1110,7 @@ static void symbol__free_source_line(struct symbol *sym, int len) src_line = (void *)src_line + sizeof_src_line; } - free(notes->src->lines); - notes->src->lines = NULL; + zfree(¬es->src->lines); } /* Get the filename:line for the colored entries */ @@ -1376,3 +1394,8 @@ 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); +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 834b7b57b788..b2aef59d6bb2 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -132,12 +132,17 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) return &a->annotation; } -int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - int evidx, u64 addr); +int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); + +int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); + int symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); + +int hist_entry__annotate(struct hist_entry *he, size_t privsize); + int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); int symbol__annotate_printf(struct symbol *sym, struct map *map, struct perf_evsel *evsel, bool full_paths, diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 4f7f989876ec..08b25af9eea1 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -146,7 +146,7 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) struct option; -int record_parse_callchain(const char *arg, struct perf_record_opts *opts); +int record_parse_callchain(const char *arg, struct record_opts *opts); int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); int record_callchain_opt(const struct option *opt, const char *arg, int unset); diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 96bbda1ddb83..0922aa4218c2 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -133,7 +133,7 @@ void close_cgroup(struct cgroup_sel *cgrp) /* XXX: not reentrant */ if (--cgrp->refcnt == 0) { close(cgrp->fd); - free(cgrp->name); + zfree(&cgrp->name); free(cgrp); } } diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c index ee0df0e24cdb..67d1e404c0cb 100644 --- a/tools/perf/util/comm.c +++ b/tools/perf/util/comm.c @@ -21,7 +21,7 @@ static void comm_str__put(struct comm_str *cs) { if (!--cs->ref) { rb_erase(&cs->rb_node, &comm_str_root); - free(cs->str); + zfree(&cs->str); free(cs); } } diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 8640a9121e72..299b55586502 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -25,7 +25,6 @@ static int _eprintf(int level, const char *fmt, va_list args) ui_helpline__vshow(fmt, args); else ret = vfprintf(stderr, fmt, args); - va_end(args); } return ret; diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 4ddeecb9ff85..4045d086d9d9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -497,21 +497,18 @@ void dso__delete(struct dso *dso) symbols__delete(&dso->symbols[i]); if (dso->short_name_allocated) { - free((char *)dso->short_name); - dso->short_name = NULL; + zfree((char **)&dso->short_name); dso->short_name_allocated = false; } if (dso->long_name_allocated) { - free((char *)dso->long_name); - dso->long_name = NULL; + zfree((char **)&dso->long_name); dso->long_name_allocated = false; } dso_cache__free(&dso->cache); dso__free_a2l(dso); - free(dso->symsrc_filename); - dso->symsrc_filename = NULL; + zfree(&dso->symsrc_filename); free(dso); } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 694876877ae2..45a76c69a9ed 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -106,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, memset(&event->comm, 0, sizeof(event->comm)); - tgid = perf_event__get_comm_tgid(pid, event->comm.comm, - sizeof(event->comm.comm)); + if (machine__is_host(machine)) + tgid = perf_event__get_comm_tgid(pid, event->comm.comm, + sizeof(event->comm.comm)); + else + tgid = machine->pid; + if (tgid < 0) goto out; @@ -129,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, goto out; } - snprintf(filename, sizeof(filename), "/proc/%d/task", pid); + if (machine__is_default_guest(machine)) + return 0; + + snprintf(filename, sizeof(filename), "%s/proc/%d/task", + machine->root_dir, pid); tasks = opendir(filename); if (tasks == NULL) { @@ -178,7 +186,11 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, FILE *fp; int rc = 0; - snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); + if (machine__is_default_guest(machine)) + return 0; + + snprintf(filename, sizeof(filename), "%s/proc/%d/maps", + machine->root_dir, pid); fp = fopen(filename, "r"); if (fp == NULL) { @@ -218,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, /* * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c */ - event->header.misc = PERF_RECORD_MISC_USER; + if (machine__is_host(machine)) + event->header.misc = PERF_RECORD_MISC_USER; + else + event->header.misc = PERF_RECORD_MISC_GUEST_USER; if (prot[2] != 'x') { if (!mmap_data || prot[0] != 'r') @@ -387,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, struct machine *machine, bool mmap_data) { DIR *proc; + char proc_path[PATH_MAX]; struct dirent dirent, *next; union perf_event *comm_event, *mmap_event; int err = -1; @@ -399,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (mmap_event == NULL) goto out_free_comm; - proc = opendir("/proc"); + if (machine__is_default_guest(machine)) + return 0; + + snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); + proc = opendir(proc_path); + if (proc == NULL) goto out_free_mmap; @@ -638,6 +659,7 @@ void thread__find_addr_map(struct thread *thread, struct map_groups *mg = &thread->mg; bool load_map = false; + al->machine = machine; al->thread = thread; al->addr = addr; al->cpumode = cpumode; @@ -658,15 +680,10 @@ void thread__find_addr_map(struct thread *thread, al->level = 'g'; mg = &machine->kmaps; load_map = true; + } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) { + al->level = 'u'; } else { - /* - * 'u' means guest os user space. - * TODO: We don't support guest user space. Might support late. - */ - if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) - al->level = 'u'; - else - al->level = 'H'; + al->level = 'H'; al->map = NULL; if ((cpumode == PERF_RECORD_MISC_GUEST_USER || diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index da3182914984..b08a7ecdcea1 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -101,10 +101,8 @@ static void perf_evlist__purge(struct perf_evlist *evlist) void perf_evlist__exit(struct perf_evlist *evlist) { - free(evlist->mmap); - free(evlist->pollfd); - evlist->mmap = NULL; - evlist->pollfd = NULL; + zfree(&evlist->mmap); + zfree(&evlist->pollfd); } void perf_evlist__delete(struct perf_evlist *evlist) @@ -587,8 +585,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist) for (i = 0; i < evlist->nr_mmaps; i++) __perf_evlist__munmap(evlist, i); - free(evlist->mmap); - evlist->mmap = NULL; + zfree(&evlist->mmap); } static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 9f64ede3ecbd..2fe51958ed85 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -12,7 +12,7 @@ struct pollfd; struct thread_map; struct cpu_map; -struct perf_record_opts; +struct record_opts; #define PERF_EVLIST__HLIST_BITS 8 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) @@ -97,9 +97,8 @@ void perf_evlist__close(struct perf_evlist *evlist); void perf_evlist__set_id_pos(struct perf_evlist *evlist); bool perf_can_sample_identifier(void); -void perf_evlist__config(struct perf_evlist *evlist, - struct perf_record_opts *opts); -int perf_record_opts__config(struct perf_record_opts *opts); +void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); +int record_opts__config(struct record_opts *opts); int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 01ff4cfde1f5..ade8d9c1c431 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -208,7 +208,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int return evsel; out_free: - free(evsel->name); + zfree(&evsel->name); free(evsel); return NULL; } @@ -528,8 +528,7 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) * enable/disable events specifically, as there's no * initial traced exec call. */ -void perf_evsel__config(struct perf_evsel *evsel, - struct perf_record_opts *opts) +void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) { struct perf_evsel *leader = evsel->leader; struct perf_event_attr *attr = &evsel->attr; @@ -751,8 +750,7 @@ void perf_evsel__free_id(struct perf_evsel *evsel) { xyarray__delete(evsel->sample_id); evsel->sample_id = NULL; - free(evsel->id); - evsel->id = NULL; + zfree(&evsel->id); } void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) @@ -768,7 +766,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) void perf_evsel__free_counts(struct perf_evsel *evsel) { - free(evsel->counts); + zfree(&evsel->counts); } void perf_evsel__exit(struct perf_evsel *evsel) @@ -782,10 +780,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) { perf_evsel__exit(evsel); close_cgroup(evsel->cgrp); - free(evsel->group_name); + zfree(&evsel->group_name); if (evsel->tp_format) pevent_free_format(evsel->tp_format); - free(evsel->name); + zfree(&evsel->name); free(evsel); } @@ -1961,8 +1959,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, evsel->attr.type = PERF_TYPE_SOFTWARE; evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; - free(evsel->name); - evsel->name = NULL; + zfree(&evsel->name); return true; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8120eeb86ac1..f1b325665aae 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -96,7 +96,7 @@ struct perf_evsel { struct cpu_map; struct thread_map; struct perf_evlist; -struct perf_record_opts; +struct record_opts; struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); @@ -120,7 +120,7 @@ void perf_evsel__exit(struct perf_evsel *evsel); void perf_evsel__delete(struct perf_evsel *evsel); void perf_evsel__config(struct perf_evsel *evsel, - struct perf_record_opts *opts); + struct record_opts *opts); int __perf_evsel__sample_size(u64 sample_type); void perf_evsel__calc_id_pos(struct perf_evsel *evsel); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 61c54213704b..a4a60b7887ee 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -800,10 +800,10 @@ static void free_cpu_topo(struct cpu_topo *tp) return; for (i = 0 ; i < tp->core_sib; i++) - free(tp->core_siblings[i]); + zfree(&tp->core_siblings[i]); for (i = 0 ; i < tp->thread_sib; i++) - free(tp->thread_siblings[i]); + zfree(&tp->thread_siblings[i]); free(tp); } @@ -1232,10 +1232,8 @@ static void free_event_desc(struct perf_evsel *events) return; for (evsel = events; evsel->attr.size; evsel++) { - if (evsel->name) - free(evsel->name); - if (evsel->id) - free(evsel->id); + zfree(&evsel->name); + zfree(&evsel->id); } free(events); @@ -1326,8 +1324,7 @@ read_event_desc(struct perf_header *ph, int fd) } } out: - if (buf) - free(buf); + free(buf); return events; error: if (events) @@ -2108,7 +2105,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, ret = 0; out_free: for (i = 0; i < nr_groups; i++) - free(desc[i].name); + zfree(&desc[i].name); free(desc); return ret; diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8b1f6e891b8a..86c37c472263 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -22,8 +22,8 @@ static void clean_cmdnames(struct cmdnames *cmds) unsigned int i; for (i = 0; i < cmds->cnt; ++i) - free(cmds->names[i]); - free(cmds->names); + zfree(&cmds->names[i]); + zfree(&cmds->names); cmds->cnt = 0; cmds->alloc = 0; } @@ -263,9 +263,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) for (i = 0; i < old->cnt; i++) cmds->names[cmds->cnt++] = old->names[i]; - free(old->names); + zfree(&old->names); old->cnt = 0; - old->names = NULL; } const char *help_unknown_cmd(const char *cmd) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 822903eaa201..4ed3e883240d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1,4 +1,3 @@ -#include "annotate.h" #include "util.h" #include "build-id.h" #include "hist.h" @@ -342,15 +341,15 @@ static u8 symbol__parent_filter(const struct symbol *parent) } static struct hist_entry *add_hist_entry(struct hists *hists, - struct hist_entry *entry, - struct addr_location *al, - u64 period, - u64 weight) + struct hist_entry *entry, + struct addr_location *al) { struct rb_node **p; struct rb_node *parent = NULL; struct hist_entry *he; int64_t cmp; + u64 period = entry->stat.period; + u64 weight = entry->stat.weight; p = &hists->entries_in->rb_node; @@ -373,7 +372,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, * This mem info was allocated from machine__resolve_mem * and will not be used anymore. */ - free(entry->mem_info); + zfree(&entry->mem_info); /* If the map of an existing hist_entry has * become out-of-date due to an exec() or @@ -437,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists, .transaction = transaction, }; - return add_hist_entry(hists, &entry, al, period, weight); + return add_hist_entry(hists, &entry, al); } int64_t @@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) void hist_entry__free(struct hist_entry *he) { - free(he->branch_info); - free(he->mem_info); + zfree(&he->branch_info); + zfree(&he->mem_info); free_srcline(he->srcline); free(he); } @@ -807,16 +806,6 @@ void hists__filter_by_symbol(struct hists *hists) } } -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); -} - -int hist_entry__annotate(struct hist_entry *he, size_t privsize) -{ - return symbol__annotate(he->ms.sym, he->ms.map, privsize); -} - void events_stats__inc(struct events_stats *stats, u32 type) { ++stats->nr_events[0]; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b621347a1585..a59743fa3ef7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -111,9 +111,6 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp); -int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); -int hist_entry__annotate(struct hist_entry *he, size_t privsize); - void hists__filter_by_dso(struct hists *hists); void hists__filter_by_thread(struct hists *hists); void hists__filter_by_symbol(struct hists *hists); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index c78cc84f433e..a98538dc465a 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -102,8 +102,7 @@ void machine__exit(struct machine *machine) map_groups__exit(&machine->kmaps); dsos__delete(&machine->user_dsos); dsos__delete(&machine->kernel_dsos); - free(machine->root_dir); - machine->root_dir = NULL; + zfree(&machine->root_dir); } void machine__delete(struct machine *machine) @@ -562,11 +561,10 @@ void machine__destroy_kernel_maps(struct machine *machine) * on one of them. */ if (type == MAP__FUNCTION) { - free((char *)kmap->ref_reloc_sym->name); - kmap->ref_reloc_sym->name = NULL; - free(kmap->ref_reloc_sym); - } - kmap->ref_reloc_sym = NULL; + zfree((char **)&kmap->ref_reloc_sym->name); + zfree(&kmap->ref_reloc_sym); + } else + kmap->ref_reloc_sym = NULL; } map__delete(machine->vmlinux_maps[type]); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 094c28ba2fae..0153435b8427 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -204,7 +204,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) } path->name = malloc(MAX_EVENT_LENGTH); if (!path->name) { - free(path->system); + zfree(&path->system); free(path); return NULL; } @@ -236,8 +236,8 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name) path->name = strdup(str+1); if (path->system == NULL || path->name == NULL) { - free(path->system); - free(path->name); + zfree(&path->system); + zfree(&path->name); free(path); path = NULL; } @@ -917,7 +917,7 @@ int parse_events_terms(struct list_head *terms, const char *str) ret = parse_events__scanner(str, &data, PE_START_TERMS); if (!ret) { list_splice(data.terms, terms); - free(data.terms); + zfree(&data.terms); return 0; } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 56fc10a5e288..0934d645ebdc 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -755,7 +755,7 @@ void print_pmu_events(const char *event_glob, bool name_only) continue; } printf(" %-50s [Kernel PMU event]\n", aliases[j]); - free(aliases[j]); + zfree(&aliases[j]); printed++; } if (printed) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 544ac1898a9f..86ed8580c3cb 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -172,6 +172,52 @@ const char *kernel_get_module_path(const char *module) return (dso) ? dso->long_name : NULL; } +/* Copied from unwind.c */ +static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, + GElf_Shdr *shp, const char *name) +{ + Elf_Scn *sec = NULL; + + while ((sec = elf_nextscn(elf, sec)) != NULL) { + char *str; + + gelf_getshdr(sec, shp); + str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); + if (!strcmp(name, str)) + break; + } + + return sec; +} + +static int get_text_start_address(const char *exec, unsigned long *address) +{ + Elf *elf; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + int fd, ret = -ENOENT; + + fd = open(exec, O_RDONLY); + if (fd < 0) + return -errno; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + return -EINVAL; + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out; + + if (!elf_section_by_name(elf, &ehdr, &shdr, ".text")) + goto out; + + *address = shdr.sh_addr - shdr.sh_offset; + ret = 0; +out: + elf_end(elf); + return ret; +} + static int init_user_exec(void) { int ret = 0; @@ -186,6 +232,37 @@ static int init_user_exec(void) return ret; } +static int convert_exec_to_group(const char *exec, char **result) +{ + char *ptr1, *ptr2, *exec_copy; + char buf[64]; + int ret; + + exec_copy = strdup(exec); + if (!exec_copy) + return -ENOMEM; + + ptr1 = basename(exec_copy); + if (!ptr1) { + ret = -EINVAL; + goto out; + } + + ptr2 = strpbrk(ptr1, "-._"); + if (ptr2) + *ptr2 = '\0'; + ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); + if (ret < 0) + goto out; + + *result = strdup(buf); + ret = *result ? 0 : -ENOMEM; + +out: + free(exec_copy); + return ret; +} + static int convert_to_perf_probe_point(struct probe_trace_point *tp, struct perf_probe_point *pp) { @@ -261,6 +338,40 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, return 0; } +static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, + int ntevs, const char *exec) +{ + int i, ret = 0; + unsigned long offset, stext = 0; + char buf[32]; + + if (!exec) + return 0; + + ret = get_text_start_address(exec, &stext); + if (ret < 0) + return ret; + + for (i = 0; i < ntevs && ret >= 0; i++) { + offset = tevs[i].point.address - stext; + offset += tevs[i].point.offset; + tevs[i].point.offset = 0; + zfree(&tevs[i].point.symbol); + ret = e_snprintf(buf, 32, "0x%lx", offset); + if (ret < 0) + break; + tevs[i].point.module = strdup(exec); + tevs[i].point.symbol = strdup(buf); + if (!tevs[i].point.symbol || !tevs[i].point.module) { + ret = -ENOMEM; + break; + } + tevs[i].uprobes = true; + } + + return ret; +} + static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, int ntevs, const char *module) { @@ -290,9 +401,7 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, } } - if (tmp) - free(tmp); - + free(tmp); return ret; } @@ -305,15 +414,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, struct debuginfo *dinfo; int ntevs, ret = 0; - if (pev->uprobes) { - if (need_dwarf) { - pr_warning("Debuginfo-analysis is not yet supported" - " with -x/--exec option.\n"); - return -ENOSYS; - } - return convert_name_to_addr(pev, target); - } - dinfo = open_debuginfo(target); if (!dinfo) { @@ -332,9 +432,14 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, if (ntevs > 0) { /* Succeeded to find trace events */ pr_debug("find %d probe_trace_events.\n", ntevs); - if (target) - ret = add_module_to_probe_trace_events(*tevs, ntevs, - target); + if (target) { + if (pev->uprobes) + ret = add_exec_to_probe_trace_events(*tevs, + ntevs, target); + else + ret = add_module_to_probe_trace_events(*tevs, + ntevs, target); + } return ret < 0 ? ret : ntevs; } @@ -401,15 +506,13 @@ static int get_real_path(const char *raw_path, const char *comp_dir, case EFAULT: raw_path = strchr(++raw_path, '/'); if (!raw_path) { - free(*new_path); - *new_path = NULL; + zfree(new_path); return -ENOENT; } continue; default: - free(*new_path); - *new_path = NULL; + zfree(new_path); return -errno; } } @@ -580,7 +683,7 @@ static int show_available_vars_at(struct debuginfo *dinfo, */ fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, vl->point.offset); - free(vl->point.symbol); + zfree(&vl->point.symbol); nvars = 0; if (vl->vars) { strlist__for_each(node, vl->vars) { @@ -654,9 +757,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, return -ENOSYS; } - if (pev->uprobes) - return convert_name_to_addr(pev, target); - return 0; } @@ -1278,8 +1378,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) error: pr_debug("Failed to synthesize perf probe point: %s\n", strerror(-ret)); - if (buf) - free(buf); + free(buf); return NULL; } @@ -1480,34 +1579,25 @@ void clear_perf_probe_event(struct perf_probe_event *pev) struct perf_probe_arg_field *field, *next; int i; - if (pev->event) - free(pev->event); - if (pev->group) - free(pev->group); - if (pp->file) - free(pp->file); - if (pp->function) - free(pp->function); - if (pp->lazy_line) - free(pp->lazy_line); + free(pev->event); + free(pev->group); + free(pp->file); + free(pp->function); + free(pp->lazy_line); + for (i = 0; i < pev->nargs; i++) { - if (pev->args[i].name) - free(pev->args[i].name); - if (pev->args[i].var) - free(pev->args[i].var); - if (pev->args[i].type) - free(pev->args[i].type); + free(pev->args[i].name); + free(pev->args[i].var); + free(pev->args[i].type); field = pev->args[i].field; while (field) { next = field->next; - if (field->name) - free(field->name); + zfree(&field->name); free(field); field = next; } } - if (pev->args) - free(pev->args); + free(pev->args); memset(pev, 0, sizeof(*pev)); } @@ -1516,21 +1606,14 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) struct probe_trace_arg_ref *ref, *next; int i; - if (tev->event) - free(tev->event); - if (tev->group) - free(tev->group); - if (tev->point.symbol) - free(tev->point.symbol); - if (tev->point.module) - free(tev->point.module); + free(tev->event); + free(tev->group); + free(tev->point.symbol); + free(tev->point.module); for (i = 0; i < tev->nargs; i++) { - if (tev->args[i].name) - free(tev->args[i].name); - if (tev->args[i].value) - free(tev->args[i].value); - if (tev->args[i].type) - free(tev->args[i].type); + free(tev->args[i].name); + free(tev->args[i].value); + free(tev->args[i].type); ref = tev->args[i].ref; while (ref) { next = ref->next; @@ -1538,8 +1621,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) ref = next; } } - if (tev->args) - free(tev->args); + free(tev->args); memset(tev, 0, sizeof(*tev)); } @@ -1913,14 +1995,29 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, int max_tevs, const char *target) { struct symbol *sym; - int ret = 0, i; + int ret, i; struct probe_trace_event *tev; + if (pev->uprobes && !pev->group) { + /* Replace group name if not given */ + ret = convert_exec_to_group(target, &pev->group); + if (ret != 0) { + pr_warning("Failed to make a group name.\n"); + return ret; + } + } + /* Convert perf_probe_event with debuginfo */ ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); if (ret != 0) return ret; /* Found in debuginfo or got an error */ + if (pev->uprobes) { + ret = convert_name_to_addr(pev, target); + if (ret < 0) + return ret; + } + /* Allocate trace event buffer */ tev = *tevs = zalloc(sizeof(struct probe_trace_event)); if (tev == NULL) @@ -2056,7 +2153,7 @@ end: for (i = 0; i < npevs; i++) { for (j = 0; j < pkgs[i].ntevs; j++) clear_probe_trace_event(&pkgs[i].tevs[j]); - free(pkgs[i].tevs); + zfree(&pkgs[i].tevs); } free(pkgs); @@ -2281,7 +2378,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) struct perf_probe_point *pp = &pev->point; struct symbol *sym; struct map *map = NULL; - char *function = NULL, *name = NULL; + char *function = NULL; int ret = -EINVAL; unsigned long long vaddr = 0; @@ -2297,12 +2394,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) goto out; } - name = realpath(exec, NULL); - if (!name) { - pr_warning("Cannot find realpath for %s.\n", exec); - goto out; - } - map = dso__new_map(name); + map = dso__new_map(exec); if (!map) { pr_warning("Cannot find appropriate DSO for %s.\n", exec); goto out; @@ -2367,7 +2459,5 @@ out: } if (function) free(function); - if (name) - free(name); return ret; } diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index f9f3de8b4220..d481c46e0796 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -12,6 +12,7 @@ struct probe_trace_point { char *symbol; /* Base symbol */ char *module; /* Module name */ unsigned long offset; /* Offset from symbol */ + unsigned long address; /* Actual address of the trace point */ bool retprobe; /* Return probe flag */ }; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ffb657ffd327..061edb162b5b 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -226,10 +226,8 @@ struct debuginfo *debuginfo__new(const char *path) if (!dbg) return NULL; - if (debuginfo__init_offline_dwarf(dbg, path) < 0) { - free(dbg); - dbg = NULL; - } + if (debuginfo__init_offline_dwarf(dbg, path) < 0) + zfree(&dbg); return dbg; } @@ -241,10 +239,8 @@ struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) if (!dbg) return NULL; - if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { - free(dbg); - dbg = NULL; - } + if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) + zfree(&dbg); return dbg; } @@ -729,6 +725,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, return -ENOENT; } tp->offset = (unsigned long)(paddr - sym.st_value); + tp->address = (unsigned long)paddr; tp->symbol = strdup(symbol); if (!tp->symbol) return -ENOMEM; @@ -1301,8 +1298,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, ret = debuginfo__find_probes(dbg, &tf.pf); if (ret < 0) { - free(*tevs); - *tevs = NULL; + zfree(tevs); return ret; } @@ -1413,13 +1409,10 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, if (ret < 0) { /* Free vlist for error */ while (af.nvls--) { - if (af.vls[af.nvls].point.symbol) - free(af.vls[af.nvls].point.symbol); - if (af.vls[af.nvls].vars) - strlist__delete(af.vls[af.nvls].vars); + zfree(&af.vls[af.nvls].point.symbol); + strlist__delete(af.vls[af.nvls].vars); } - free(af.vls); - *vls = NULL; + zfree(vls); return ret; } @@ -1523,10 +1516,7 @@ post: if (fname) { ppt->file = strdup(fname); if (ppt->file == NULL) { - if (ppt->function) { - free(ppt->function); - ppt->function = NULL; - } + zfree(&ppt->function); ret = -ENOMEM; goto end; } @@ -1580,8 +1570,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) else ret = 0; /* Lines are not found */ else { - free(lf->lr->path); - lf->lr->path = NULL; + zfree(&lf->lr->path); } return ret; } diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index e5104538c354..104a47563d39 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -74,8 +74,7 @@ bool perf_can_sample_identifier(void) return perf_probe_api(perf_probe_sample_identifier); } -void perf_evlist__config(struct perf_evlist *evlist, - struct perf_record_opts *opts) +void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) { struct perf_evsel *evsel; bool use_sample_identifier = false; @@ -123,7 +122,7 @@ static int get_max_rate(unsigned int *rate) return filename__read_int(path, (int *) rate); } -static int perf_record_opts__config_freq(struct perf_record_opts *opts) +static int record_opts__config_freq(struct record_opts *opts) { bool user_freq = opts->user_freq != UINT_MAX; unsigned int max_rate; @@ -173,9 +172,9 @@ static int perf_record_opts__config_freq(struct perf_record_opts *opts) return 0; } -int perf_record_opts__config(struct perf_record_opts *opts) +int record_opts__config(struct record_opts *opts) { - return perf_record_opts__config_freq(opts); + return record_opts__config_freq(opts); } bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d5e5969f6fea..e108207c5de0 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -194,8 +194,7 @@ static void define_event_symbols(struct event_format *event, zero_flag_atom = 0; break; case PRINT_FIELD: - if (cur_field_name) - free(cur_field_name); + free(cur_field_name); cur_field_name = strdup(args->field.name); break; case PRINT_FLAGS: @@ -257,12 +256,9 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, - struct perf_sample *sample, +static void perl_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct thread *thread, - struct addr_location *al) + struct thread *thread) { struct format_field *field; static char handler[256]; @@ -349,10 +345,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct thread *thread __maybe_unused, - struct addr_location *al __maybe_unused) + struct perf_evsel *evsel) { dSP; @@ -377,12 +370,11 @@ static void perl_process_event_generic(union perf_event *event, static void perl_process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine, struct thread *thread, - struct addr_location *al) + struct addr_location *al __maybe_unused) { - perl_process_tracepoint(event, sample, evsel, machine, thread, al); - perl_process_event_generic(event, sample, evsel, machine, thread, al); + perl_process_tracepoint(sample, evsel, thread); + perl_process_event_generic(event, sample, evsel); } static void run_start_sub(void) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 53c20e7fd900..cd9774df3750 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -161,8 +161,7 @@ static void define_event_symbols(struct event_format *event, zero_flag_atom = 0; break; case PRINT_FIELD: - if (cur_field_name) - free(cur_field_name); + free(cur_field_name); cur_field_name = strdup(args->field.name); break; case PRINT_FLAGS: @@ -231,13 +230,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void python_process_tracepoint(union perf_event *perf_event - __maybe_unused, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine __maybe_unused, - struct thread *thread, - struct addr_location *al) +static void python_process_tracepoint(struct perf_sample *sample, + struct perf_evsel *evsel, + struct thread *thread, + struct addr_location *al) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; static char handler_name[256]; @@ -351,11 +347,8 @@ static void python_process_tracepoint(union perf_event *perf_event Py_DECREF(t); } -static void python_process_general_event(union perf_event *perf_event - __maybe_unused, - struct perf_sample *sample, +static void python_process_general_event(struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __maybe_unused, struct thread *thread, struct addr_location *al) { @@ -411,22 +404,19 @@ exit: Py_DECREF(t); } -static void python_process_event(union perf_event *perf_event, +static void python_process_event(union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine, struct thread *thread, struct addr_location *al) { switch (evsel->attr.type) { case PERF_TYPE_TRACEPOINT: - python_process_tracepoint(perf_event, sample, evsel, - machine, thread, al); + python_process_tracepoint(sample, evsel, thread, al); break; /* Reserve for future process_hw/sw/raw APIs */ default: - python_process_general_event(perf_event, sample, evsel, - machine, thread, al); + python_process_general_event(sample, evsel, thread, al); } } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 989b2e377626..8ffe29c55d0f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -132,18 +132,18 @@ static void perf_session__delete_threads(struct perf_session *session) static void perf_session_env__delete(struct perf_session_env *env) { - free(env->hostname); - free(env->os_release); - free(env->version); - free(env->arch); - free(env->cpu_desc); - free(env->cpuid); + zfree(&env->hostname); + zfree(&env->os_release); + zfree(&env->version); + zfree(&env->arch); + zfree(&env->cpu_desc); + zfree(&env->cpuid); - free(env->cmdline); - free(env->sibling_cores); - free(env->sibling_threads); - free(env->numa_nodes); - free(env->pmu_mappings); + zfree(&env->cmdline); + zfree(&env->sibling_cores); + zfree(&env->sibling_threads); + zfree(&env->numa_nodes); + zfree(&env->pmu_mappings); } void perf_session__delete(struct perf_session *session) @@ -830,6 +830,7 @@ static struct machine * struct perf_sample *sample) { const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + struct machine *machine; if (perf_guest && ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || @@ -842,7 +843,11 @@ static struct machine * else pid = sample->pid; - return perf_session__findnew_machine(session, pid); + machine = perf_session__find_machine(session, pid); + if (!machine) + machine = perf_session__findnew_machine(session, + DEFAULT_GUEST_KERNEL_ID); + return machine; } return &session->machines.host; @@ -1467,7 +1472,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, } void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct machine *machine, struct addr_location *al, + struct addr_location *al, unsigned int print_opts, unsigned int stack_depth) { struct callchain_cursor_node *node; @@ -1482,7 +1487,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, if (symbol_conf.use_callchain && sample->callchain) { struct addr_location node_al; - if (machine__resolve_callchain(machine, evsel, al->thread, + if (machine__resolve_callchain(al->machine, evsel, al->thread, sample, NULL, NULL, PERF_MAX_STACK_DEPTH) != 0) { if (verbose) diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 9c25d49900af..3140f8ae6148 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -106,7 +106,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct machine *machine, struct addr_location *al, + struct addr_location *al, unsigned int print_opts, unsigned int stack_depth); int perf_session__cpu_bitmap(struct perf_session *session, diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f4494a..635cd8f8b22e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -13,6 +13,7 @@ int have_ignore_callees = 0; int sort__need_collapse = 0; int sort__has_parent = 0; int sort__has_sym = 0; +int sort__has_dso = 0; enum sort_mode sort__mode = SORT_MODE__NORMAL; enum sort_type sort__first_dimension; @@ -161,6 +162,11 @@ struct sort_entry sort_dso = { /* --sort symbol */ +static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip) +{ + return (int64_t)(right_ip - left_ip); +} + static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) { u64 ip_l, ip_r; @@ -183,15 +189,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) int64_t ret; if (!left->ms.sym && !right->ms.sym) - return right->level - left->level; + return _sort__addr_cmp(left->ip, right->ip); /* * comparing symbol address alone is not enough since it's a * relative address within a dso. */ - ret = sort__dso_cmp(left, right); - if (ret != 0) - return ret; + if (!sort__has_dso) { + ret = sort__dso_cmp(left, right); + if (ret != 0) + return ret; + } return _sort__sym_cmp(left->ms.sym, right->ms.sym); } @@ -372,7 +380,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) struct addr_map_symbol *from_r = &right->branch_info->from; if (!from_l->sym && !from_r->sym) - return right->level - left->level; + return _sort__addr_cmp(from_l->addr, from_r->addr); return _sort__sym_cmp(from_l->sym, from_r->sym); } @@ -384,7 +392,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) struct addr_map_symbol *to_r = &right->branch_info->to; if (!to_l->sym && !to_r->sym) - return right->level - left->level; + return _sort__addr_cmp(to_l->addr, to_r->addr); return _sort__sym_cmp(to_l->sym, to_r->sym); } @@ -1056,6 +1064,8 @@ int sort_dimension__add(const char *tok) sort__has_parent = 1; } else if (sd->entry == &sort_sym) { sort__has_sym = 1; + } else if (sd->entry == &sort_dso) { + sort__has_dso = 1; } __sort_dimension__add(sd, i); diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 58b2bd8f38c9..7e67879ebd25 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -129,7 +129,7 @@ static struct a2l_data *addr2line_init(const char *path) out: if (a2l) { - free((void *)a2l->input); + zfree((void **)&a2l->input); free(a2l); } bfd_close(abfd); @@ -140,8 +140,8 @@ static void addr2line_cleanup(struct a2l_data *a2l) { if (a2l->abfd) bfd_close(a2l->abfd); - free((void *)a2l->input); - free(a2l->syms); + zfree((void **)&a2l->input); + zfree(&a2l->syms); free(a2l); } diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index cfa906882e2c..4abe23550c73 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -28,7 +28,7 @@ void strbuf_init(struct strbuf *sb, ssize_t hint) void strbuf_release(struct strbuf *sb) { if (sb->alloc) { - free(sb->buf); + zfree(&sb->buf); strbuf_init(sb, 0); } } diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 3edd0538161f..79a757a2a15c 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c @@ -14,7 +14,7 @@ static void strfilter_node__delete(struct strfilter_node *node) { if (node) { if (node->p && !is_operator(*node->p)) - free((char *)node->p); + zfree((char **)&node->p); strfilter_node__delete(node->l); strfilter_node__delete(node->r); free(node); diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index f0b0c008c507..2553e5b55b89 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -128,7 +128,7 @@ void argv_free(char **argv) { char **p; for (p = argv; *p; p++) - free(*p); + zfree(p); free(argv); } diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index eabdce0a2daa..61a90bf24b4d 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c @@ -5,6 +5,7 @@ */ #include "strlist.h" +#include "util.h" #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -38,7 +39,7 @@ out_delete: static void str_node__delete(struct str_node *snode, bool dupstr) { if (dupstr) - free((void *)snode->s); + zfree((void **)&snode->s); free(snode); } diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 56a84f2cc46d..43262b83c541 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -21,6 +21,7 @@ #include "perf.h" #include "svghelper.h" +#include "util.h" #include "cpumap.h" static u64 first_time, last_time; @@ -708,8 +709,8 @@ int svg_build_topology_map(char *sib_core, int sib_core_nr, return 0; exit: - free(t.sib_core); - free(t.sib_thr); + zfree(&t.sib_core); + zfree(&t.sib_thr); return -1; } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index bf0ce29567b6..4b0a127a4d3b 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -554,7 +554,7 @@ bool symsrc__has_symtab(struct symsrc *ss) void symsrc__destroy(struct symsrc *ss) { - free(ss->name); + zfree(&ss->name); elf_end(ss->elf); close(ss->fd); } diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index ac7070a2f2b6..bd15f490d04f 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -1,4 +1,5 @@ #include "symbol.h" +#include "util.h" #include <stdio.h> #include <fcntl.h> @@ -275,7 +276,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused) void symsrc__destroy(struct symsrc *ss) { - free(ss->name); + zfree(&ss->name); close(ss->fd); } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 923d00040bbf..39ce9adbaaf0 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -796,7 +796,7 @@ static void delete_modules(struct rb_root *modules) mi = rb_entry(next, struct module_info, rb_node); next = rb_next(&mi->rb_node); rb_erase(&mi->rb_node, modules); - free(mi->name); + zfree(&mi->name); free(mi); } } @@ -1621,13 +1621,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, static void vmlinux_path__exit(void) { - while (--vmlinux_path__nr_entries >= 0) { - free(vmlinux_path[vmlinux_path__nr_entries]); - vmlinux_path[vmlinux_path__nr_entries] = NULL; - } + while (--vmlinux_path__nr_entries >= 0) + zfree(&vmlinux_path[vmlinux_path__nr_entries]); - free(vmlinux_path); - vmlinux_path = NULL; + zfree(&vmlinux_path); } static int vmlinux_path__init(void) diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 8a9d910c5345..cbd680361806 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -164,6 +164,7 @@ struct mem_info { }; struct addr_location { + struct machine *machine; struct thread *thread; struct map *map; struct symbol *sym; diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 9b5f856cc280..5d3215912105 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -9,6 +9,7 @@ #include "strlist.h" #include <string.h> #include "thread_map.h" +#include "util.h" /* Skip "." and ".." directories */ static int filter(const struct dirent *dir) @@ -40,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) } for (i=0; i<items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); return threads; @@ -117,7 +118,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads->map[threads->nr + i] = atoi(namelist[i]->d_name); for (i = 0; i < items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); threads->nr += items; @@ -134,12 +135,11 @@ out_free_threads: out_free_namelist: for (i = 0; i < items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); out_free_closedir: - free(threads); - threads = NULL; + zfree(&threads); goto out_closedir; } @@ -194,7 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) for (i = 0; i < items; i++) { threads->map[j++] = atoi(namelist[i]->d_name); - free(namelist[i]); + zfree(&namelist[i]); } threads->nr = total_tasks; free(namelist); @@ -206,12 +206,11 @@ out: out_free_namelist: for (i = 0; i < items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); out_free_threads: - free(threads); - threads = NULL; + zfree(&threads); goto out; } @@ -262,8 +261,7 @@ out: return threads; out_free_threads: - free(threads); - threads = NULL; + zfree(&threads); goto out; } diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index ce793c7dd23c..8e517def925b 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -26,7 +26,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) float samples_per_sec; float ksamples_per_sec; float esamples_percent; - struct perf_record_opts *opts = &top->record_opts; + struct record_opts *opts = &top->record_opts; struct target *target = &opts->target; size_t ret = 0; diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 88cfeaff600b..dab14d0ad3d0 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -14,7 +14,7 @@ struct perf_session; struct perf_top { struct perf_tool tool; struct perf_evlist *evlist; - struct perf_record_opts record_opts; + struct record_opts record_opts; /* * Symbols will be added here in perf_event__process_sample and will * get out after decayed. diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index c354b95a2348..7e6fcfe8b438 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -397,8 +397,8 @@ put_tracepoints_path(struct tracepoint_path *tps) struct tracepoint_path *t = tps; tps = tps->next; - free(t->name); - free(t->system); + zfree(&t->name); + zfree(&t->system); free(t); } } @@ -562,10 +562,8 @@ out: output_fd = fd; } - if (err) { - free(tdata); - tdata = NULL; - } + if (err) + zfree(&tdata); put_tracepoints_path(tps); return tdata; diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 95199e4eea97..57aaccc1692e 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -38,9 +38,8 @@ static int stop_script_unsupported(void) static void process_event_unsupported(union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, struct perf_evsel *evsel __maybe_unused, - struct machine *machine __maybe_unused, struct thread *thread __maybe_unused, - struct addr_location *al __maybe_unused) + struct addr_location *al __maybe_unused) { } diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 3a01618c5b87..7b6d68688327 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -68,7 +68,6 @@ struct scripting_ops { void (*process_event) (union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine, struct thread *thread, struct addr_location *al); int (*generate_script) (struct pevent *pevent, const char *outfile); diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 9a2c268ad718..6995d66f225c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -186,6 +186,8 @@ static inline void *zalloc(size_t size) return calloc(1, size); } +#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) + static inline int has_extension(const char *filename, const char *ext) { size_t len = strlen(filename); diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c index 697c8b4e59cc..0fb3c1fcd3e6 100644 --- a/tools/perf/util/values.c +++ b/tools/perf/util/values.c @@ -31,14 +31,14 @@ void perf_read_values_destroy(struct perf_read_values *values) return; for (i = 0; i < values->threads; i++) - free(values->value[i]); - free(values->value); - free(values->pid); - free(values->tid); - free(values->counterrawid); + zfree(&values->value[i]); + zfree(&values->value); + zfree(&values->pid); + zfree(&values->tid); + zfree(&values->counterrawid); for (i = 0; i < values->counters; i++) - free(values->countername[i]); - free(values->countername); + zfree(&values->countername[i]); + zfree(&values->countername); } static void perf_read_values__enlarge_threads(struct perf_read_values *values) |