perf report: Fix leak of resolved callchains array on error path
[safe/jmp/linux-2.6] / tools / perf / builtin-report.c
index 816edae..3a70c58 100644 (file)
@@ -83,7 +83,7 @@ static int perf_session__add_hist_entry(struct perf_session *self,
        struct map_symbol *syms = NULL;
        struct symbol *parent = NULL;
        bool hit;
-       int err;
+       int err = -ENOMEM;
        struct hist_entry *he;
        struct event_stat_id *stats;
        struct perf_event_attr *attr;
@@ -101,39 +101,24 @@ static int perf_session__add_hist_entry(struct perf_session *self,
        else
                stats = get_stats(self, data->id, 0, 0);
        if (stats == NULL)
-               return -ENOMEM;
+               goto out_free_syms;
        he = __perf_session__add_hist_entry(&stats->hists, al, parent,
                                            data->period, &hit);
        if (he == NULL)
-               return -ENOMEM;
+               goto out_free_syms;
 
        if (hit)
                __perf_session__add_count(he, al,  data->period);
 
+       err = 0;
        if (symbol_conf.use_callchain) {
                if (!hit)
                        callchain_init(he->callchain);
                err = append_chain(he->callchain, data->callchain, syms);
-               free(syms);
-
-               if (err)
-                       return err;
        }
-
-       return 0;
-}
-
-static int validate_chain(struct ip_callchain *chain, event_t *event)
-{
-       unsigned int chain_size;
-
-       chain_size = event->header.size;
-       chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
-
-       if (chain->nr*sizeof(u64) > chain_size)
-               return -1;
-
-       return 0;
+out_free_syms:
+       free(syms);
+       return err;
 }
 
 static int add_event_total(struct perf_session *session,
@@ -171,7 +156,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 
                dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
 
-               if (validate_chain(data.callchain, event) < 0) {
+               if (!ip_callchain__valid(data.callchain, event)) {
                        pr_debug("call-chain problem with event, "
                                 "skipping it.\n");
                        return 0;
@@ -289,7 +274,7 @@ static int __cmd_report(void)
 
        signal(SIGINT, sig_handler);
 
-       session = perf_session__new(input_name, O_RDONLY, force);
+       session = perf_session__new(input_name, O_RDONLY, force, false);
        if (session == NULL)
                return -ENOMEM;
 
@@ -313,7 +298,7 @@ static int __cmd_report(void)
                perf_session__fprintf(session, stdout);
 
        if (verbose > 2)
-               dsos__fprintf(&session->kerninfo_root, stdout);
+               perf_session__fprintf_dsos(session, stdout);
 
        next = rb_first(&session->stats_by_id);
        while (next) {
@@ -457,7 +442,7 @@ static const struct option options[] = {
        OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
                    "Only display entries with parent-match"),
        OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
-                    "Display callchains using output_type and min percent threshold. "
+                    "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. "
                     "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
        OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
                   "only consider symbols in these dsos"),