]> Pileus Git - ~andy/linux/blobdiff - tools/perf/builtin-report.c
perf probe: Check build-id of vmlinux
[~andy/linux] / tools / perf / builtin-report.c
index 9cbdcbc4cd5697408584c12809d839f66ed19b0d..40389c0e38c6b72165facd2cf243caea068bfdd6 100644 (file)
@@ -38,6 +38,7 @@ static char           *dso_list_str, *comm_list_str, *sym_list_str,
 static struct strlist  *dso_list, *comm_list, *sym_list;
 
 static int             force;
+static bool            use_callchain;
 
 static int             show_nr_samples;
 
@@ -51,9 +52,7 @@ static int            exclude_other = 1;
 
 static char            callchain_default_opt[] = "fractal,0.5";
 
-static u64             sample_type;
-
-struct symbol_conf     symbol_conf;
+static struct symbol_conf      symbol_conf;
 
 
 static size_t
@@ -312,8 +311,9 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
        return ret;
 }
 
-static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
+static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self,
+                                 struct perf_session *session,
+                                 u64 total_samples)
 {
        struct sort_entry *se;
        size_t ret;
@@ -345,7 +345,7 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
 
        ret += fprintf(fp, "\n");
 
-       if (callchain) {
+       if (session->use_callchain) {
                int left_margin = 0;
 
                if (sort__first_dimension == SORT_COMM) {
@@ -405,87 +405,29 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
        return 0;
 }
 
-static int call__match(struct symbol *sym)
-{
-       if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
-               return 1;
-
-       return 0;
-}
-
-static struct symbol **resolve_callchain(struct thread *thread,
-                                        struct perf_session *session,
-                                        struct ip_callchain *chain,
-                                        struct symbol **parent)
-{
-       u8 cpumode = PERF_RECORD_MISC_USER;
-       struct symbol **syms = NULL;
-       unsigned int i;
-
-       if (callchain) {
-               syms = calloc(chain->nr, sizeof(*syms));
-               if (!syms) {
-                       fprintf(stderr, "Can't allocate memory for symbols\n");
-                       exit(-1);
-               }
-       }
-
-       for (i = 0; i < chain->nr; i++) {
-               u64 ip = chain->ips[i];
-               struct addr_location al;
-
-               if (ip >= PERF_CONTEXT_MAX) {
-                       switch (ip) {
-                       case PERF_CONTEXT_HV:
-                               cpumode = PERF_RECORD_MISC_HYPERVISOR;  break;
-                       case PERF_CONTEXT_KERNEL:
-                               cpumode = PERF_RECORD_MISC_KERNEL;      break;
-                       case PERF_CONTEXT_USER:
-                               cpumode = PERF_RECORD_MISC_USER;        break;
-                       default:
-                               break;
-                       }
-                       continue;
-               }
-
-               thread__find_addr_location(thread, session, cpumode,
-                                          MAP__FUNCTION, ip, &al, NULL);
-               if (al.sym != NULL) {
-                       if (sort__has_parent && !*parent &&
-                           call__match(al.sym))
-                               *parent = al.sym;
-                       if (!callchain)
-                               break;
-                       syms[i] = al.sym;
-               }
-       }
-
-       return syms;
-}
-
 /*
  * collect histogram counts
  */
 
-static int hist_entry__add(struct addr_location *al,
-                          struct perf_session *session,
-                          struct ip_callchain *chain, u64 count)
+static int perf_session__add_hist_entry(struct perf_session *self,
+                                       struct addr_location *al,
+                                       struct ip_callchain *chain, u64 count)
 {
        struct symbol **syms = NULL, *parent = NULL;
        bool hit;
        struct hist_entry *he;
 
-       if ((sort__has_parent || callchain) && chain)
-               syms = resolve_callchain(al->thread, session, chain, &parent);
-
-       he = __hist_entry__add(al, parent, count, &hit);
+       if ((sort__has_parent || self->use_callchain) && chain)
+               syms = perf_session__resolve_callchain(self, al->thread,
+                                                      chain, &parent);
+       he = __perf_session__add_hist_entry(self, al, parent, count, &hit);
        if (he == NULL)
                return -ENOMEM;
 
        if (hit)
                he->count += count;
 
-       if (callchain) {
+       if (self->use_callchain) {
                if (!hit)
                        callchain_init(&he->callchain);
                append_chain(&he->callchain, chain, syms);
@@ -495,7 +437,8 @@ static int hist_entry__add(struct addr_location *al,
        return 0;
 }
 
-static size_t output__fprintf(FILE *fp, u64 total_samples)
+static size_t perf_session__fprintf_hist_entries(struct perf_session *self,
+                                                u64 total_samples, FILE *fp)
 {
        struct hist_entry *pos;
        struct sort_entry *se;
@@ -567,9 +510,9 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
        fprintf(fp, "#\n");
 
 print_entries:
-       for (nd = rb_first(&hist); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
                pos = rb_entry(nd, struct hist_entry, rb_node);
-               ret += hist_entry__fprintf(fp, pos, total_samples);
+               ret += hist_entry__fprintf(fp, pos, self, total_samples);
        }
 
        if (sort_order == default_sort_order &&
@@ -612,7 +555,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
        memset(&data, 0, sizeof(data));
        data.period = 1;
 
-       event__parse_sample(event, sample_type, &data);
+       event__parse_sample(event, session->sample_type, &data);
 
        dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
                event->header.misc,
@@ -620,7 +563,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
                (void *)(long)data.ip,
                (long long)data.period);
 
-       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+       if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
                unsigned int i;
 
                dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
@@ -671,13 +614,12 @@ static int process_sample_event(event_t *event, struct perf_session *session)
        if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
                return 0;
 
-       if (hist_entry__add(&al, session, data.callchain, data.period)) {
+       if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) {
                pr_debug("problem incrementing symbol count, skipping event\n");
                return -1;
        }
 
-       event__stats.total += data.period;
-
+       session->events_stats.total += data.period;
        return 0;
 }
 
@@ -719,25 +661,23 @@ static int process_read_event(event_t *event, struct perf_session *session __use
        return 0;
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
 {
-       sample_type = type;
-
-       if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
+       if (!(session->sample_type & PERF_SAMPLE_CALLCHAIN)) {
                if (sort__has_parent) {
                        fprintf(stderr, "selected --sort parent, but no"
                                        " callchain data. Did you call"
                                        " perf record without -g?\n");
                        return -1;
                }
-               if (callchain) {
+               if (session->use_callchain) {
                        fprintf(stderr, "selected -g but no callchain data."
                                        " Did you call perf record without"
                                        " -g?\n");
                        return -1;
                }
-       } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
-                       callchain = 1;
+       } else if (callchain_param.mode != CHAIN_NONE && !session->use_callchain) {
+                       session->use_callchain = true;
                        if (register_callchain_param(&callchain_param) < 0) {
                                fprintf(stderr, "Can't register callchain"
                                                " params\n");
@@ -769,6 +709,8 @@ static int __cmd_report(void)
        if (session == NULL)
                return -ENOMEM;
 
+       session->use_callchain = use_callchain;
+
        if (show_threads)
                perf_read_values_init(&show_threads_values);
 
@@ -787,9 +729,9 @@ static int __cmd_report(void)
        if (verbose > 2)
                dsos__fprintf(stdout);
 
-       collapse__resort();
-       output__resort(event__stats.total);
-       output__fprintf(stdout, event__stats.total);
+       perf_session__collapse_resort(session);
+       perf_session__output_resort(session, session->events_stats.total);
+       perf_session__fprintf_hist_entries(session, session->events_stats.total, stdout);
 
        if (show_threads)
                perf_read_values_destroy(&show_threads_values);
@@ -805,7 +747,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
        char *tok;
        char *endptr;
 
-       callchain = 1;
+       use_callchain = true;
 
        if (!arg)
                return 0;
@@ -826,7 +768,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
 
        else if (!strncmp(tok, "none", strlen(arg))) {
                callchain_param.mode = CHAIN_NONE;
-               callchain = 0;
+               use_callchain = true;
 
                return 0;
        }
@@ -901,21 +843,6 @@ static const struct option options[] = {
        OPT_END()
 };
 
-static void setup_sorting(void)
-{
-       char *tmp, *tok, *str = strdup(sort_order);
-
-       for (tok = strtok_r(str, ", ", &tmp);
-                       tok; tok = strtok_r(NULL, ", ", &tmp)) {
-               if (sort_dimension__add(tok) < 0) {
-                       error("Unknown --sort key: `%s'", tok);
-                       usage_with_options(report_usage, options);
-               }
-       }
-
-       free(str);
-}
-
 static void setup_list(struct strlist **list, const char *list_str,
                       struct sort_entry *se, const char *list_name,
                       FILE *fp)
@@ -942,7 +869,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 
        argc = parse_options(argc, argv, options, report_usage, 0);
 
-       setup_sorting();
+       setup_sorting(report_usage, options);
 
        if (parent_pattern != default_parent_pattern) {
                sort_dimension__add("parent");