diff options
Diffstat (limited to 'tools/perf/util/sort.c')
-rw-r--r-- | tools/perf/util/sort.c | 196 |
1 files changed, 92 insertions, 104 deletions
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5d2518e89fc4..345b5ccc90f6 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2,16 +2,23 @@ #include <errno.h> #include <inttypes.h> #include <regex.h> +#include <stdlib.h> #include <linux/mman.h> #include <linux/time64.h> +#include "debug.h" +#include "dso.h" #include "sort.h" #include "hist.h" +#include "cacheline.h" #include "comm.h" #include "map.h" #include "symbol.h" +#include "map_symbol.h" +#include "branch.h" #include "thread.h" #include "evsel.h" #include "evlist.h" +#include "srcline.h" #include "strlist.h" #include "strbuf.h" #include <traceevent/event-parse.h> @@ -19,6 +26,7 @@ #include "annotate.h" #include "time-utils.h" #include <linux/kernel.h> +#include <linux/string.h> regex_t parent_regex; const char default_parent_pattern[] = "^sys_|^do_page_fault"; @@ -279,10 +287,12 @@ sort__sym_sort(struct hist_entry *left, struct hist_entry *right) return strcmp(right->ms.sym->name, left->ms.sym->name); } -static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, +static int _hist_entry__sym_snprintf(struct map_symbol *ms, u64 ip, char level, char *bf, size_t size, unsigned int width) { + struct symbol *sym = ms->sym; + struct map *map = ms->map; size_t ret = 0; if (verbose > 0) { @@ -317,7 +327,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { - return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip, + return _hist_entry__sym_snprintf(&he->ms, he->ip, he->level, bf, size, width); } @@ -378,7 +388,7 @@ struct sort_entry sort_srcline = { static char *addr_map_symbol__srcline(struct addr_map_symbol *ams) { - return map__srcline(ams->map, ams->al_addr, ams->sym); + return map__srcline(ams->ms.map, ams->al_addr, ams->ms.sym); } static int64_t @@ -668,17 +678,11 @@ sort__time_cmp(struct hist_entry *left, struct hist_entry *right) static int hist_entry__time_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { - unsigned long secs; - unsigned long long nsecs; char he_time[32]; - nsecs = he->time; - secs = nsecs / NSEC_PER_SEC; - nsecs -= secs * NSEC_PER_SEC; - if (symbol_conf.nanosecs) - snprintf(he_time, sizeof he_time, "%5lu.%09llu: ", - secs, nsecs); + timestamp__scnprintf_nsec(he->time, he_time, + sizeof(he_time)); else timestamp__scnprintf_usec(he->time, he_time, sizeof(he_time)); @@ -698,7 +702,7 @@ struct sort_entry sort_time = { static char *get_trace_output(struct hist_entry *he) { struct trace_seq seq; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_record rec = { .data = he->raw_data, .size = he->raw_size, @@ -711,7 +715,8 @@ static char *get_trace_output(struct hist_entry *he) tep_print_fields(&seq, he->raw_data, he->raw_size, evsel->tp_format); } else { - tep_event_info(&seq, evsel->tp_format, &rec); + tep_print_event(evsel->tp_format->tep, + &seq, &rec, "%s", TEP_PRINT_INFO); } /* * Trim the buffer, it starts at 4KB and we're not going to @@ -723,10 +728,10 @@ static char *get_trace_output(struct hist_entry *he) static int64_t sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = hists_to_evsel(left->hists); - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) return 0; if (left->trace_output == NULL) @@ -740,10 +745,10 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = hists_to_evsel(he->hists); - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) return scnprintf(bf, size, "%-.*s", width, "N/A"); if (he->trace_output == NULL) @@ -766,15 +771,15 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) if (!left->branch_info || !right->branch_info) return cmp_null(left->branch_info, right->branch_info); - return _sort__dso_cmp(left->branch_info->from.map, - right->branch_info->from.map); + return _sort__dso_cmp(left->branch_info->from.ms.map, + right->branch_info->from.ms.map); } static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { if (he->branch_info) - return _hist_entry__dso_snprintf(he->branch_info->from.map, + return _hist_entry__dso_snprintf(he->branch_info->from.ms.map, bf, size, width); else return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); @@ -788,8 +793,8 @@ static int hist_entry__dso_from_filter(struct hist_entry *he, int type, if (type != HIST_FILTER__DSO) return -1; - return dso && (!he->branch_info || !he->branch_info->from.map || - he->branch_info->from.map->dso != dso); + return dso && (!he->branch_info || !he->branch_info->from.ms.map || + he->branch_info->from.ms.map->dso != dso); } static int64_t @@ -798,15 +803,15 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) if (!left->branch_info || !right->branch_info) return cmp_null(left->branch_info, right->branch_info); - return _sort__dso_cmp(left->branch_info->to.map, - right->branch_info->to.map); + return _sort__dso_cmp(left->branch_info->to.ms.map, + right->branch_info->to.ms.map); } static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { if (he->branch_info) - return _hist_entry__dso_snprintf(he->branch_info->to.map, + return _hist_entry__dso_snprintf(he->branch_info->to.ms.map, bf, size, width); else return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); @@ -820,8 +825,8 @@ static int hist_entry__dso_to_filter(struct hist_entry *he, int type, if (type != HIST_FILTER__DSO) return -1; - return dso && (!he->branch_info || !he->branch_info->to.map || - he->branch_info->to.map->dso != dso); + return dso && (!he->branch_info || !he->branch_info->to.ms.map || + he->branch_info->to.ms.map->dso != dso); } static int64_t @@ -836,10 +841,10 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) from_l = &left->branch_info->from; from_r = &right->branch_info->from; - if (!from_l->sym && !from_r->sym) + if (!from_l->ms.sym && !from_r->ms.sym) return _sort__addr_cmp(from_l->addr, from_r->addr); - return _sort__sym_cmp(from_l->sym, from_r->sym); + return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym); } static int64_t @@ -853,10 +858,10 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) to_l = &left->branch_info->to; to_r = &right->branch_info->to; - if (!to_l->sym && !to_r->sym) + if (!to_l->ms.sym && !to_r->ms.sym) return _sort__addr_cmp(to_l->addr, to_r->addr); - return _sort__sym_cmp(to_l->sym, to_r->sym); + return _sort__sym_cmp(to_l->ms.sym, to_r->ms.sym); } static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, @@ -865,8 +870,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, if (he->branch_info) { struct addr_map_symbol *from = &he->branch_info->from; - return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(&from->ms, from->addr, he->level, bf, size, width); } return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); @@ -878,8 +882,7 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, if (he->branch_info) { struct addr_map_symbol *to = &he->branch_info->to; - return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(&to->ms, to->addr, he->level, bf, size, width); } return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); @@ -893,8 +896,8 @@ static int hist_entry__sym_from_filter(struct hist_entry *he, int type, if (type != HIST_FILTER__SYMBOL) return -1; - return sym && !(he->branch_info && he->branch_info->from.sym && - strstr(he->branch_info->from.sym->name, sym)); + return sym && !(he->branch_info && he->branch_info->from.ms.sym && + strstr(he->branch_info->from.ms.sym->name, sym)); } static int hist_entry__sym_to_filter(struct hist_entry *he, int type, @@ -905,8 +908,8 @@ static int hist_entry__sym_to_filter(struct hist_entry *he, int type, if (type != HIST_FILTER__SYMBOL) return -1; - return sym && !(he->branch_info && he->branch_info->to.sym && - strstr(he->branch_info->to.sym->name, sym)); + return sym && !(he->branch_info && he->branch_info->to.ms.sym && + strstr(he->branch_info->to.ms.sym->name, sym)); } struct sort_entry sort_dso_from = { @@ -1014,16 +1017,13 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { uint64_t addr = 0; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; if (he->mem_info) { addr = he->mem_info->daddr.addr; - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + ms = &he->mem_info->daddr.ms; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); } int64_t @@ -1043,16 +1043,13 @@ static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { uint64_t addr = 0; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; if (he->mem_info) { addr = he->mem_info->iaddr.addr; - map = he->mem_info->iaddr.map; - sym = he->mem_info->iaddr.sym; + ms = &he->mem_info->iaddr.ms; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); } static int64_t @@ -1062,9 +1059,9 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) struct map *map_r = NULL; if (left->mem_info) - map_l = left->mem_info->daddr.map; + map_l = left->mem_info->daddr.ms.map; if (right->mem_info) - map_r = right->mem_info->daddr.map; + map_r = right->mem_info->daddr.ms.map; return _sort__dso_cmp(map_l, map_r); } @@ -1075,7 +1072,7 @@ static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, struct map *map = NULL; if (he->mem_info) - map = he->mem_info->daddr.map; + map = he->mem_info->daddr.ms.map; return _hist_entry__dso_snprintf(map, bf, size, width); } @@ -1197,6 +1194,7 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) { u64 l, r; struct map *l_map, *r_map; + int rc; if (!left->mem_info) return -1; if (!right->mem_info) return 1; @@ -1205,8 +1203,8 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) if (left->cpumode > right->cpumode) return -1; if (left->cpumode < right->cpumode) return 1; - l_map = left->mem_info->daddr.map; - r_map = right->mem_info->daddr.map; + l_map = left->mem_info->daddr.ms.map; + r_map = right->mem_info->daddr.ms.map; /* if both are NULL, jump to sort on al_addr instead */ if (!l_map && !r_map) @@ -1215,18 +1213,9 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) if (!l_map) return -1; if (!r_map) return 1; - if (l_map->maj > r_map->maj) return -1; - if (l_map->maj < r_map->maj) return 1; - - if (l_map->min > r_map->min) return -1; - if (l_map->min < r_map->min) return 1; - - if (l_map->ino > r_map->ino) return -1; - if (l_map->ino < r_map->ino) return 1; - - if (l_map->ino_generation > r_map->ino_generation) return -1; - if (l_map->ino_generation < r_map->ino_generation) return 1; - + rc = dso__cmp_id(l_map->dso, r_map->dso); + if (rc) + return rc; /* * Addresses with no major/minor numbers are assumed to be * anonymous in userspace. Sort those on pid then address. @@ -1237,8 +1226,8 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) if ((left->cpumode != PERF_RECORD_MISC_KERNEL) && (!(l_map->flags & MAP_SHARED)) && - !l_map->maj && !l_map->min && !l_map->ino && - !l_map->ino_generation) { + !l_map->dso->id.maj && !l_map->dso->id.min && + !l_map->dso->id.ino && !l_map->dso->id.ino_generation) { /* userspace anonymous */ if (left->thread->pid_ > right->thread->pid_) return -1; @@ -1261,27 +1250,26 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf, { uint64_t addr = 0; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; char level = he->level; if (he->mem_info) { + struct map *map = he->mem_info->daddr.ms.map; + addr = cl_address(he->mem_info->daddr.al_addr); - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + ms = &he->mem_info->daddr.ms; /* print [s] for shared data mmaps */ if ((he->cpumode != PERF_RECORD_MISC_KERNEL) && map && !(map->prot & PROT_EXEC) && (map->flags & MAP_SHARED) && - (map->maj || map->min || map->ino || - map->ino_generation)) + (map->dso->id.maj || map->dso->id.min || + map->dso->id.ino || map->dso->id.ino_generation)) level = 's'; else if (!map) level = 'X'; } - return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width); } struct sort_entry sort_mispredict = { @@ -1984,7 +1972,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd, struct hpp_dynamic_entry { struct perf_hpp_fmt hpp; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; unsigned dynamic_len; bool raw_trace; @@ -2218,7 +2206,7 @@ static void hde_free(struct perf_hpp_fmt *fmt) } static struct hpp_dynamic_entry * -__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field, +__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field, int level) { struct hpp_dynamic_entry *hde; @@ -2313,20 +2301,20 @@ static int parse_field_name(char *str, char **event, char **field, char **opt) * 2. full event name (e.g. sched:sched_switch) * 3. partial event name (should not contain ':') */ -static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name) +static struct evsel *find_evsel(struct evlist *evlist, char *event_name) { - struct perf_evsel *evsel = NULL; - struct perf_evsel *pos; + struct evsel *evsel = NULL; + struct evsel *pos; bool full_name; /* case 1 */ if (event_name[0] == '%') { int nr = strtol(event_name+1, NULL, 0); - if (nr > evlist->nr_entries) + if (nr > evlist->core.nr_entries) return NULL; - evsel = perf_evlist__first(evlist); + evsel = evlist__first(evlist); while (--nr > 0) evsel = perf_evsel__next(evsel); @@ -2352,7 +2340,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam return evsel; } -static int __dynamic_dimension__add(struct perf_evsel *evsel, +static int __dynamic_dimension__add(struct evsel *evsel, struct tep_format_field *field, bool raw_trace, int level) { @@ -2368,7 +2356,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel, return 0; } -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) +static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level) { int ret; struct tep_format_field *field; @@ -2384,14 +2372,14 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) return 0; } -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, +static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace, int level) { int ret; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) continue; ret = add_evsel_fields(evsel, raw_trace, level); @@ -2401,15 +2389,15 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, return 0; } -static int add_all_matching_fields(struct perf_evlist *evlist, +static int add_all_matching_fields(struct evlist *evlist, char *field_name, bool raw_trace, int level) { int ret = -ESRCH; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) continue; field = tep_find_any_field(evsel->tp_format, field_name); @@ -2423,11 +2411,11 @@ static int add_all_matching_fields(struct perf_evlist *evlist, return ret; } -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, +static int add_dynamic_entry(struct evlist *evlist, const char *tok, int level) { char *str, *event_name, *field_name, *opt_name; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; bool raw_trace = symbol_conf.raw_trace; int ret = 0; @@ -2470,7 +2458,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, goto out; } - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { pr_debug("%s is not a tracepoint event\n", event_name); ret = -EINVAL; goto out; @@ -2567,7 +2555,7 @@ int hpp_dimension__add_output(unsigned col) } int sort_dimension__add(struct perf_hpp_list *list, const char *tok, - struct perf_evlist *evlist, + struct evlist *evlist, int level) { unsigned int i; @@ -2663,7 +2651,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok, } static int setup_sort_list(struct perf_hpp_list *list, char *str, - struct perf_evlist *evlist) + struct evlist *evlist) { char *tmp, *tok; int ret = 0; @@ -2709,7 +2697,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, return ret; } -static const char *get_default_sort_order(struct perf_evlist *evlist) +static const char *get_default_sort_order(struct evlist *evlist) { const char *default_sort_orders[] = { default_sort_order, @@ -2720,7 +2708,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) default_tracepoint_sort_order, }; bool use_trace = true; - struct perf_evsel *evsel; + struct evsel *evsel; BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); @@ -2728,7 +2716,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) goto out_no_evlist; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { use_trace = false; break; } @@ -2743,7 +2731,7 @@ out_no_evlist: return default_sort_orders[sort__mode]; } -static int setup_sort_order(struct perf_evlist *evlist) +static int setup_sort_order(struct evlist *evlist) { char *new_sort_order; @@ -2804,7 +2792,7 @@ static char *setup_overhead(char *keys) return keys; } -static int __setup_sorting(struct perf_evlist *evlist) +static int __setup_sorting(struct evlist *evlist) { char *str; const char *sort_keys; @@ -3057,7 +3045,7 @@ out: return ret; } -int setup_sorting(struct perf_evlist *evlist) +int setup_sorting(struct evlist *evlist) { int err; |