From 2037be53b2bceac3c2e648b8ff3fd62e21af2d35 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 18 Dec 2013 14:21:09 +0900 Subject: [PATCH 01/49] perf sort: Compare addresses if no symbol info If a hist entry doesn't have symbol information, compare it with its address. Currently it only compares its level or whether it's NULL. This can lead to an undesired result like an overhead exceeds 100% especially when callchain accumulation is enabled by later patch. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Arun Sharma Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Rodrigo Campos Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1387344086-12744-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f4494a..68a4fd2f505e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -161,6 +161,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,7 +188,7 @@ 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 @@ -372,7 +377,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 +389,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); } From 68f6d0224b2a19a4da4a12a5081f01776e5150df Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 18 Dec 2013 14:21:10 +0900 Subject: [PATCH 02/49] perf sort: Do not compare dso again The commit 09600e0f9ebb ("perf tools: Compare dso's also when comparing symbols") added a comparison of dso when comparing symbol. But if the sort key already has dso, it doesn't need to do it again since entries have a different dso already filtered out. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Arun Sharma Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Rodrigo Campos Link: http://lkml.kernel.org/r/1387344086-12744-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 68a4fd2f505e..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; @@ -194,9 +195,11 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) * 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); } @@ -1061,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); From f1cbf78d175e6202a29f53a7f915520e40a37baf Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 18 Dec 2013 14:21:11 +0900 Subject: [PATCH 03/49] perf hists: Do not pass period and weight to add_hist_entry() The @entry argument already has the info so no need to pass them. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Arun Sharma Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Rodrigo Campos Link: http://lkml.kernel.org/r/1387344086-12744-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 822903eaa201..63234e37583c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -342,15 +342,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; @@ -437,7 +437,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 From bf19b82e7cf033319525a9eab12216b59c41c519 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:17 +0900 Subject: [PATCH 04/49] tools lib traceevent: Introduce pevent_filter_strerror() The pevent_filter_strerror() function is for receiving actual error message from pevent_errno value. To do that, add a static buffer to event_filter for saving internal error message If a failed function saved other information in the static buffer returns the information, otherwise returns generic error message. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-15-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 17 +---- tools/lib/traceevent/event-parse.h | 7 ++- tools/lib/traceevent/parse-filter.c | 98 ++++++++++++++++------------- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 22566c271275..2ce565a73dd5 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5230,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused, idx = errnum - __PEVENT_ERRNO__START - 1; msg = pevent_error_str[idx]; - - switch (errnum) { - case PEVENT_ERRNO__MEM_ALLOC_FAILED: - case PEVENT_ERRNO__PARSE_EVENT_FAILED: - case PEVENT_ERRNO__READ_ID_FAILED: - case PEVENT_ERRNO__READ_FORMAT_FAILED: - case PEVENT_ERRNO__READ_PRINT_FAILED: - case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: - case PEVENT_ERRNO__INVALID_ARG_TYPE: - snprintf(buf, buflen, "%s", msg); - break; - - default: - /* cannot reach here */ - break; - } + snprintf(buf, buflen, "%s", msg); return 0; } diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 3ad784f5f647..cf5db9013f2c 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -851,10 +851,13 @@ struct filter_type { struct filter_arg *filter; }; +#define PEVENT_FILTER_ERROR_BUFSZ 1024 + struct event_filter { struct pevent *pevent; int filters; struct filter_type *event_filters; + char error_buffer[PEVENT_FILTER_ERROR_BUFSZ]; }; struct event_filter *pevent_filter_alloc(struct pevent *pevent); @@ -874,10 +877,12 @@ enum filter_trivial_type { enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, const char *filter_str); - enum pevent_errno pevent_filter_match(struct event_filter *filter, struct pevent_record *record); +int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, + char *buf, size_t buflen); + int pevent_event_filtered(struct event_filter *filter, int event_id); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index e2842b926759..b50234402fc2 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -38,55 +38,31 @@ struct event_list { struct event_format *event; }; -#define MAX_ERR_STR_SIZE 256 - -static void show_error(char **error_str, const char *fmt, ...) +static void show_error(char *error_buf, const char *fmt, ...) { unsigned long long index; const char *input; - char *error; va_list ap; int len; int i; - if (!error_str) - return; - input = pevent_get_input_buf(); index = pevent_get_input_buf_ptr(); len = input ? strlen(input) : 0; - error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3); - if (error == NULL) { - /* - * Maybe it's due to len is too long. - * Retry without the input buffer part. - */ - len = 0; - - error = malloc(MAX_ERR_STR_SIZE); - if (error == NULL) { - /* no memory */ - *error_str = NULL; - return; - } - } - if (len) { - strcpy(error, input); - error[len] = '\n'; + strcpy(error_buf, input); + error_buf[len] = '\n'; for (i = 1; i < len && i < index; i++) - error[len+i] = ' '; - error[len + i] = '^'; - error[len + i + 1] = '\n'; + error_buf[len+i] = ' '; + error_buf[len + i] = '^'; + error_buf[len + i + 1] = '\n'; len += i+2; } va_start(ap, fmt); - vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap); + vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap); va_end(ap); - - *error_str = error; } static void free_token(char *token) @@ -370,7 +346,7 @@ static void free_events(struct event_list *events) static enum pevent_errno create_arg_item(struct event_format *event, const char *token, - enum event_type type, struct filter_arg **parg, char **error_str) + enum event_type type, struct filter_arg **parg, char *error_str) { struct format_field *field; struct filter_arg *arg; @@ -474,7 +450,7 @@ create_arg_cmp(enum filter_exp_type etype) } static enum pevent_errno -add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str) +add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) { struct filter_arg *left; char *str; @@ -786,7 +762,7 @@ enum filter_vals { static enum pevent_errno reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, - struct filter_arg *arg, char **error_str) + struct filter_arg *arg, char *error_str) { struct filter_arg *other_child; struct filter_arg **ptr; @@ -838,7 +814,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, /* Returns either filter_vals (success) or pevent_errno (failfure) */ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, - char **error_str) + char *error_str) { int lval, rval; @@ -938,7 +914,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, /* Remove any unknown event fields */ static int collapse_tree(struct filter_arg *arg, - struct filter_arg **arg_collapsed, char **error_str) + struct filter_arg **arg_collapsed, char *error_str) { int ret; @@ -973,7 +949,7 @@ static int collapse_tree(struct filter_arg *arg, static enum pevent_errno process_filter(struct event_format *event, struct filter_arg **parg, - char **error_str, int not) + char *error_str, int not) { enum event_type type; char *token = NULL; @@ -1211,7 +1187,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, static enum pevent_errno process_event(struct event_format *event, const char *filter_str, - struct filter_arg **parg, char **error_str) + struct filter_arg **parg, char *error_str) { int ret; @@ -1236,7 +1212,7 @@ process_event(struct event_format *event, const char *filter_str, static enum pevent_errno filter_event(struct event_filter *filter, struct event_format *event, - const char *filter_str, char **error_str) + const char *filter_str, char *error_str) { struct filter_type *filter_type; struct filter_arg *arg; @@ -1268,13 +1244,21 @@ filter_event(struct event_filter *filter, struct event_format *event, return 0; } +static void filter_init_error_buf(struct event_filter *filter) +{ + /* clear buffer to reset show error */ + pevent_buffer_init("", 0); + filter->error_buffer[0] = '\0'; +} + /** * pevent_filter_add_filter_str - add a new filter * @filter: the event filter to add to * @filter_str: the filter string that contains the filter * * Returns 0 if the filter was successfully added or a - * negative error code. + * negative error code. Use pevent_filter_strerror() to see + * actual error message in case of error. */ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, const char *filter_str) @@ -1291,10 +1275,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ int len; int ret; - char *error_str = NULL; - /* clear buffer to reset show error */ - pevent_buffer_init("", 0); + filter_init_error_buf(filter); filter_start = strchr(filter_str, ':'); if (filter_start) @@ -1353,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, /* filter starts here */ for (event = events; event; event = event->next) { ret = filter_event(filter, event->event, filter_start, - &error_str); + filter->error_buffer); /* Failures are returned if a parse error happened */ if (ret < 0) rtn = ret; @@ -1381,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type) free_arg(filter_type->filter); } +/** + * pevent_filter_strerror - fill error message in a buffer + * @filter: the event filter contains error + * @err: the error code + * @buf: the buffer to be filled in + * @buflen: the size of the buffer + * + * Returns 0 if message was filled successfully, -1 if error + */ +int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, + char *buf, size_t buflen) +{ + if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END) + return -1; + + if (strlen(filter->error_buffer) > 0) { + size_t len = snprintf(buf, buflen, "%s", filter->error_buffer); + + if (len > buflen) + return -1; + return 0; + } + + return pevent_strerror(filter->pevent, err, buf, buflen); +} + /** * pevent_filter_remove_event - remove a filter for an event * @filter: the event filter to remove from @@ -2027,6 +2035,8 @@ enum pevent_errno pevent_filter_match(struct event_filter *filter, int ret; enum pevent_errno err = 0; + filter_init_error_buf(filter); + if (!filter->filters) return PEVENT_ERRNO__NO_FILTER; From b66d8c0caa8f7925ae75fed243b0482a901f21e1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 15:37:41 -0300 Subject: [PATCH 05/49] perf annotate: Auto allocate symbol per addr hist buckets Instead of open coding it in multiple places in 'report' and 'top'. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ay1ushp57qsva9aw59rha5ve@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 57 ++++++++++--------------------------- tools/perf/builtin-top.c | 13 ++++----- tools/perf/util/annotate.c | 26 ++++++++++++----- 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3a14dbed387c..b75fc361b9bd 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -140,22 +140,11 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, goto out; } - if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) { - struct annotation *notes; - - mx = he->mem_info; - - notes = symbol__annotation(mx->daddr.sym); - if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0) - goto out; - - err = symbol__inc_addr_samples(mx->daddr.sym, - mx->daddr.map, - evsel->idx, - mx->daddr.al_addr); - if (err) - goto out; - } + mx = he->mem_info; + err = symbol__inc_addr_samples(mx->daddr.sym, mx->daddr.map, + evsel->idx, mx->daddr.al_addr); + if (err) + goto out; evsel->hists.stats.total_period += cost; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); @@ -214,35 +203,19 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL, 1, 1, 0); if (he) { - struct annotation *notes; bx = he->branch_info; - if (bx->from.sym && use_browser == 1 && sort__has_sym) { - notes = symbol__annotation(bx->from.sym); - if (!notes->src - && symbol__alloc_hist(bx->from.sym) < 0) - goto out; + err = symbol__inc_addr_samples(bx->from.sym, + bx->from.map, evsel->idx, + bx->from.al_addr); + if (err) + goto out; - err = symbol__inc_addr_samples(bx->from.sym, - bx->from.map, - evsel->idx, - bx->from.al_addr); - if (err) - goto out; - } + err = symbol__inc_addr_samples(bx->to.sym, + bx->to.map, evsel->idx, + bx->to.al_addr); + if (err) + goto out; - if (bx->to.sym && use_browser == 1 && sort__has_sym) { - notes = symbol__annotation(bx->to.sym); - if (!notes->src - && symbol__alloc_hist(bx->to.sym) < 0) - goto out; - - err = symbol__inc_addr_samples(bx->to.sym, - bx->to.map, - evsel->idx, - bx->to.al_addr); - if (err) - goto out; - } evsel->hists.stats.total_period += 1; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); } else diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 03d37a76c612..73df9c05bad9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -189,14 +189,6 @@ static void perf_top__record_precise_ip(struct perf_top *top, if (pthread_mutex_trylock(¬es->lock)) return; - if (notes->src == NULL && symbol__alloc_hist(sym) < 0) { - pthread_mutex_unlock(¬es->lock); - pr_err("Not enough memory for annotating '%s' symbol!\n", - sym->name); - sleep(1); - return; - } - ip = he->ms.map->map_ip(he->ms.map, ip); err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); @@ -204,6 +196,11 @@ static void perf_top__record_precise_ip(struct perf_top *top, if (err == -ERANGE && !he->ms.map->erange_warned) ui__warn_map_erange(he->ms.map, sym, ip); + else if (err == -ENOMEM) { + pr_err("Not enough memory for annotating '%s' symbol!\n", + sym->name); + sleep(1); + } } static void perf_top__show_details(struct perf_top *top) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 0fcd81ea31ae..93614cd3948f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -464,17 +464,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 +486,23 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, return 0; } +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); +} + static void disasm_line__init_ins(struct disasm_line *dl) { dl->ins = ins__find(dl->name); From 00e55218642b91c152917e170c8387c631467460 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 15:46:32 -0300 Subject: [PATCH 06/49] perf hists: Leave symbol addr hist bucket auto alloc to symbol layer Since now symbol__addr_inc_samples() does the auto alloc, no need to do it prior to calling hist_entry__inc_addr_samples. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-6ife7xq2kef1nn017m04b3id@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 10 +-------- tools/perf/builtin-report.c | 38 ++++------------------------------- 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6fd52c8fa682..4136f9970fd5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -69,15 +69,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, if (he == NULL) return -ENOMEM; - ret = 0; - if (he->ms.sym != NULL) { - struct annotation *notes = symbol__annotation(he->ms.sym); - if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) - return -ENOMEM; - - ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); - } - + ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); return ret; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b75fc361b9bd..0615a63ae355 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -122,23 +122,9 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, if (!he) return -ENOMEM; - /* - * In the TUI browser, we are doing integrated annotation, - * so we don't allocate the extra space needed because the stdio - * code will not use it. - */ - if (sort__has_sym && he->ms.sym && use_browser > 0) { - struct annotation *notes = symbol__annotation(he->ms.sym); - - assert(evsel != NULL); - - if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) - goto out; - - err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); - if (err) - goto out; - } + err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + if (err) + goto out; mx = he->mem_info; err = symbol__inc_addr_samples(mx->daddr.sym, mx->daddr.map, @@ -259,26 +245,10 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool, if (err) return err; } - /* - * Only in the TUI browser we are doing integrated annotation, - * so we don't allocated the extra space needed because the stdio - * code will not use it. - */ - if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) { - struct annotation *notes = symbol__annotation(he->ms.sym); - - assert(evsel != NULL); - - err = -ENOMEM; - if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) - goto out; - - err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); - } + err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); -out: return err; } From 0f4e7a24d0303eaf12847b4fdf4f2d31553fdc61 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 16:48:29 -0300 Subject: [PATCH 07/49] perf annotate: Add inc_samples method to addr_map_symbol Since there are three calls that could receive just the struct addr_map_symbol pointer and call the symbol method. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-d728gz1orgkaknac9ppnzd9e@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 11 +++-------- tools/perf/util/annotate.c | 5 +++++ tools/perf/util/annotate.h | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0615a63ae355..9a20c9efb84b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -127,8 +127,7 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, goto out; mx = he->mem_info; - err = symbol__inc_addr_samples(mx->daddr.sym, mx->daddr.map, - evsel->idx, mx->daddr.al_addr); + err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx); if (err) goto out; @@ -190,15 +189,11 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, 1, 1, 0); if (he) { bx = he->branch_info; - err = symbol__inc_addr_samples(bx->from.sym, - bx->from.map, evsel->idx, - bx->from.al_addr); + err = addr_map_symbol__inc_samples(&bx->from, evsel->idx); if (err) goto out; - err = symbol__inc_addr_samples(bx->to.sym, - bx->to.map, evsel->idx, - bx->to.al_addr); + err = addr_map_symbol__inc_samples(&bx->to, evsel->idx); if (err) goto out; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 93614cd3948f..2812e7b78d0f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -503,6 +503,11 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 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); +} + static void disasm_line__init_ins(struct disasm_line *dl) { dl->ins = ins__find(dl->name); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 834b7b57b788..8de10b1ef027 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -134,6 +134,9 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) 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 symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); From 618afb294e288db086fce59de4419644215265e5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 17:08:07 -0300 Subject: [PATCH 08/49] perf top: Use hist_entry__inc_addr_sample Since it has a hist_entry, no need to skip the hist layer and use the underlying symbol one. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-txsgu9umb0i86ijk888r1a0o@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 73df9c05bad9..2c6cb66f5358 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -190,7 +190,7 @@ static void perf_top__record_precise_ip(struct perf_top *top, return; ip = he->ms.map->map_ip(he->ms.map, ip); - err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); + err = hist_entry__inc_addr_samples(he, counter, ip); pthread_mutex_unlock(¬es->lock); From f626adffe17632aa7b0e2a7732b49e2c32d477d8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 17:10:15 -0300 Subject: [PATCH 09/49] perf annotate: Adopt methods from hists Those are just wrappers to annotation methods, so move them to annotate.c Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-336h7z0bi2k51cbfi6mkpo5k@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 10 ++++++++++ tools/perf/util/annotate.h | 5 +++++ tools/perf/util/hist.c | 11 ----------- tools/perf/util/hist.h | 3 --- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 2812e7b78d0f..91e25269bb27 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -508,6 +508,11 @@ 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); @@ -1393,3 +1398,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 8de10b1ef027..43727a9b93cd 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -137,10 +137,15 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 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/hist.c b/tools/perf/util/hist.c index 63234e37583c..6cd4823a7a8b 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" @@ -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); From 44e8303944cd45788abd48f14d4c683331ed6cf7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 17:12:24 -0300 Subject: [PATCH 10/49] perf annotate: Make symbol__inc_addr_samples private Since it is now accessed just thru addr_map_symbol and hist_entry wrappers. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-gjoam7wcfrb03sp753gk1nfk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 4 ++-- tools/perf/util/annotate.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 91e25269bb27..27ab7b59dbf4 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -486,8 +486,8 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, return 0; } -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, + int evidx, u64 addr) { struct annotation *notes; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 43727a9b93cd..b2aef59d6bb2 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -132,9 +132,6 @@ 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); From 6dbc8ca97b7737fa9254083df29d06c556b0653c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 18 Dec 2013 18:16:18 -0300 Subject: [PATCH 11/49] perf report: Introduce helpers for processing callchains Continuing to try to remove the code duplication introduced with mem and branch hist entry code, this time providing prologue and epilogues to deal with callchains when processing samples. Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-js3pour59yk2aibqzb1tpumh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 72 +++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 9a20c9efb84b..8424053b399a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -75,6 +75,24 @@ static int perf_report_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } +static int report__resolve_callchain(struct perf_report *rep, struct symbol **parent, + struct perf_evsel *evsel, struct addr_location *al, + struct perf_sample *sample, struct machine *machine) +{ + if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { + return machine__resolve_callchain(machine, evsel, al->thread, sample, + parent, al, rep->max_stack); + } + return 0; +} + +static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) +{ + if (!symbol_conf.use_callchain) + return 0; + return callchain_append(he->callchain, &callchain_cursor, sample->period); +} + static int perf_report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al, struct perf_sample *sample, @@ -85,19 +103,13 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, struct perf_report *rep = container_of(tool, struct perf_report, tool); struct symbol *parent = NULL; u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; - int err = 0; struct hist_entry *he; struct mem_info *mi, *mx; uint64_t cost; + int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); - if ((sort__has_parent || symbol_conf.use_callchain) && - sample->callchain) { - err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent, al, - rep->max_stack); - if (err) - return err; - } + if (err) + return err; mi = machine__resolve_mem(machine, al->thread, sample, cpumode); if (!mi) @@ -133,13 +145,7 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, evsel->hists.stats.total_period += cost; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); - err = 0; - - if (symbol_conf.use_callchain) { - err = callchain_append(he->callchain, - &callchain_cursor, - sample->period); - } + err = hist_entry__append_callchain(he, sample); out: return err; } @@ -152,19 +158,13 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, { struct perf_report *rep = container_of(tool, struct perf_report, tool); struct symbol *parent = NULL; - int err = 0; unsigned i; struct hist_entry *he; struct branch_info *bi, *bx; + int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); - if ((sort__has_parent || symbol_conf.use_callchain) - && sample->callchain) { - err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent, al, - rep->max_stack); - if (err) - return err; - } + if (err) + return err; bi = machine__resolve_bstack(machine, al->thread, sample->branch_stack); @@ -216,16 +216,11 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool, { struct perf_report *rep = container_of(tool, struct perf_report, tool); struct symbol *parent = NULL; - int err = 0; struct hist_entry *he; + int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); - if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent, al, - rep->max_stack); - if (err) - return err; - } + if (err) + return err; he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL, sample->period, sample->weight, @@ -233,17 +228,14 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool, if (he == NULL) return -ENOMEM; - if (symbol_conf.use_callchain) { - err = callchain_append(he->callchain, - &callchain_cursor, - sample->period); - if (err) - return err; - } + err = hist_entry__append_callchain(he, sample); + if (err) + goto out; err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); +out: return err; } From 73db8f82619b7538d9b4badfe13f3ab2fef7d9b3 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 19 Dec 2013 16:00:08 +0900 Subject: [PATCH 12/49] perf tools: Get rid of a duplicate va_end() in error reporting routine The va_end() in _eprintf() should be removed since the caller also invokes va_end(). Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1387436411-20160-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/debug.c | 1 - 1 file changed, 1 deletion(-) 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; From 3406912cc1c631dea7ff050a9df92216e5a70e98 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 29 Oct 2013 19:04:57 +0100 Subject: [PATCH 13/49] perf inject: Handle output file via perf_data_file object Using the perf_data_file object to handle output file processing. No functional change intended. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Mike Galbraith Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-01j9ophd7tntmgrxa40uqjjm@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 65 +++++++++++++++---------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6a2508589460..c9f6d74e1fd7 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -22,14 +22,13 @@ #include struct perf_inject { - struct perf_tool tool; - bool build_ids; - bool sched_stat; - const char *input_name; - int pipe_output, - output; - u64 bytes_written; - struct list_head samples; + struct perf_tool tool; + bool build_ids; + bool sched_stat; + const char *input_name; + struct perf_data_file output; + u64 bytes_written; + struct list_head samples; }; struct event_entry { @@ -42,21 +41,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool, union perf_event *event) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); - uint32_t size; - void *buf = event; + ssize_t size; - size = event->header.size; - - while (size) { - int ret = write(inject->output, buf, size); - if (ret < 0) - return -errno; - - size -= ret; - buf += ret; - inject->bytes_written += ret; - } + size = perf_data_file__write(&inject->output, event, + event->header.size); + if (size < 0) + return -errno; + inject->bytes_written += size; return 0; } @@ -80,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool, if (ret) return ret; - if (!inject->pipe_output) + if (&inject->output.is_pipe) return 0; return perf_event__repipe_synth(tool, event); @@ -355,6 +347,7 @@ static int __cmd_inject(struct perf_inject *inject) .path = inject->input_name, .mode = PERF_DATA_MODE_READ, }; + struct perf_data_file *file_out = &inject->output; signal(SIGINT, sig_handler); @@ -391,14 +384,14 @@ static int __cmd_inject(struct perf_inject *inject) } } - if (!inject->pipe_output) - lseek(inject->output, session->header.data_offset, SEEK_SET); + if (!file_out->is_pipe) + lseek(file_out->fd, session->header.data_offset, SEEK_SET); ret = perf_session__process_events(session, &inject->tool); - if (!inject->pipe_output) { + if (!file_out->is_pipe) { session->header.data_size = inject->bytes_written; - perf_session__write_header(session, session->evlist, inject->output, true); + perf_session__write_header(session, session->evlist, file_out->fd, true); } perf_session__delete(session); @@ -427,14 +420,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }, .input_name = "-", .samples = LIST_HEAD_INIT(inject.samples), + .output = { + .path = "-", + .mode = PERF_DATA_MODE_WRITE, + }, }; - const char *output_name = "-"; const struct option options[] = { OPT_BOOLEAN('b', "build-ids", &inject.build_ids, "Inject build-ids into the output stream"), OPT_STRING('i', "input", &inject.input_name, "file", "input file name"), - OPT_STRING('o', "output", &output_name, "file", + OPT_STRING('o', "output", &inject.output.path, "file", "output file name"), OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " @@ -456,16 +452,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) if (argc) usage_with_options(inject_usage, options); - if (!strcmp(output_name, "-")) { - inject.pipe_output = 1; - inject.output = STDOUT_FILENO; - } else { - inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC, - S_IRUSR | S_IWUSR); - if (inject.output < 0) { - perror("failed to create output file"); - return -1; - } + if (perf_data_file__open(&inject.output)) { + perror("failed to create output file"); + return -1; } if (symbol__init() < 0) From 50a9b8680613a2708ca882d982dcfa4fd9a66673 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 22 Nov 2013 13:11:24 +0100 Subject: [PATCH 14/49] perf record: Use perf_data_file__write for output file Changing the file output code to use the newly added perf_data_file__write interface. No functional change intended. Signed-off-by: Jiri Olsa Cc: Ingo Molnar Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Namhyung Kim Cc: Mike Galbraith Cc: David Ahern Cc: Adrian Hunter Cc: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index c1c1200d2f0a..8eed3d752c80 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -76,24 +76,19 @@ struct perf_record { long samples; }; -static int perf_record__write(struct perf_record *rec, void *buf, size_t size) +static ssize_t perf_record__write(struct perf_record *rec, + void *buf, size_t size) { - struct perf_data_file *file = &rec->file; + struct perf_session *session = rec->session; + ssize_t ret; - while (size) { - ssize_t ret = write(file->fd, buf, size); - - if (ret < 0) { - pr_err("failed to write perf data, error: %m\n"); - return -1; - } - - size -= ret; - buf += ret; - - rec->bytes_written += ret; + ret = perf_data_file__write(session->file, buf, size); + if (ret < 0) { + pr_err("failed to write perf data, error: %m\n"); + return -1; } + rec->bytes_written += ret; return 0; } From cf8b2e6941091d2034f19c1799f8d6407bd565a4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 14:26:26 -0300 Subject: [PATCH 15/49] perf record: Simplify perf_record__write 1. Since all callers either test if it is less than zero or assign its result to an int variable, convert it from ssize_t to int; 2. There is just one use for the 'session' variable, so use rec->session directly instead; 3. No need to store the result of perf_data_file__write, since that result is either 'size' or -1, the later making the error result to be stored in 'errno' and accessed thru printf's %m in the pr_err call. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-xwsk964dp681fica3xlqhjin@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8eed3d752c80..e8d606caf747 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -76,19 +76,14 @@ struct perf_record { long samples; }; -static ssize_t perf_record__write(struct perf_record *rec, - void *buf, size_t size) +static int perf_record__write(struct perf_record *rec, void *bf, size_t size) { - struct perf_session *session = rec->session; - ssize_t ret; - - ret = perf_data_file__write(session->file, buf, size); - if (ret < 0) { + if (perf_data_file__write(rec->session->file, bf, size) < 0) { pr_err("failed to write perf data, error: %m\n"); return -1; } - rec->bytes_written += ret; + rec->bytes_written += size; return 0; } From 8c6f45a7c263840c27dfe846d40577b49e43b85b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 14:38:03 -0300 Subject: [PATCH 16/49] perf record: Rename 'perf_record' to plain 'record' Its a local struct and the functions use the __ separator from the class name to the method name, so its unlikely that this will clash with other namespaces. Save some typing then. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-r011tdv7ianars9jr9ur2n4q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 58 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e8d606caf747..f2624d43333e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -62,7 +62,7 @@ static void __handle_on_exit_funcs(void) } #endif -struct perf_record { +struct record { struct perf_tool tool; struct perf_record_opts opts; u64 bytes_written; @@ -76,7 +76,7 @@ struct perf_record { long samples; }; -static int perf_record__write(struct perf_record *rec, void *bf, size_t size) +static int record__write(struct record *rec, void *bf, size_t size) { if (perf_data_file__write(rec->session->file, bf, size) < 0) { pr_err("failed to write perf data, error: %m\n"); @@ -92,12 +92,11 @@ static int process_synthesized_event(struct perf_tool *tool, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { - struct perf_record *rec = container_of(tool, struct perf_record, tool); - return perf_record__write(rec, event, event->header.size); + struct record *rec = container_of(tool, struct record, tool); + return record__write(rec, event, event->header.size); } -static int perf_record__mmap_read(struct perf_record *rec, - struct perf_mmap *md) +static int record__mmap_read(struct record *rec, struct perf_mmap *md) { unsigned int head = perf_mmap__read_head(md); unsigned int old = md->prev; @@ -118,7 +117,7 @@ static int perf_record__mmap_read(struct perf_record *rec, size = md->mask + 1 - (old & md->mask); old += size; - if (perf_record__write(rec, buf, size) < 0) { + if (record__write(rec, buf, size) < 0) { rc = -1; goto out; } @@ -128,7 +127,7 @@ static int perf_record__mmap_read(struct perf_record *rec, size = head - old; old += size; - if (perf_record__write(rec, buf, size) < 0) { + if (record__write(rec, buf, size) < 0) { rc = -1; goto out; } @@ -153,9 +152,9 @@ static void sig_handler(int sig) signr = sig; } -static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) +static void record__sig_exit(int exit_status __maybe_unused, void *arg) { - struct perf_record *rec = arg; + struct record *rec = arg; int status; if (rec->evlist->workload.pid > 0) { @@ -173,7 +172,7 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) signal(signr, SIG_DFL); } -static int perf_record__open(struct perf_record *rec) +static int record__open(struct record *rec) { char msg[512]; struct perf_evsel *pos; @@ -229,7 +228,7 @@ static int perf_record__open(struct perf_record *rec) return rc; } -static int process_buildids(struct perf_record *rec) +static int process_buildids(struct record *rec) { struct perf_data_file *file = &rec->file; struct perf_session *session = rec->session; @@ -244,9 +243,9 @@ static int process_buildids(struct perf_record *rec) size, &build_id__mark_dso_hit_ops); } -static void perf_record__exit(int status, void *arg) +static void record__exit(int status, void *arg) { - struct perf_record *rec = arg; + struct record *rec = arg; struct perf_data_file *file = &rec->file; if (status != 0) @@ -302,14 +301,14 @@ static struct perf_event_header finished_round_event = { .type = PERF_RECORD_FINISHED_ROUND, }; -static int perf_record__mmap_read_all(struct perf_record *rec) +static int record__mmap_read_all(struct record *rec) { int i; int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { if (rec->evlist->mmap[i].base) { - if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { + if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { rc = -1; goto out; } @@ -317,14 +316,13 @@ static int perf_record__mmap_read_all(struct perf_record *rec) } if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) - rc = perf_record__write(rec, &finished_round_event, - sizeof(finished_round_event)); + rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); out: return rc; } -static void perf_record__init_features(struct perf_record *rec) +static void record__init_features(struct record *rec) { struct perf_evlist *evsel_list = rec->evlist; struct perf_session *session = rec->session; @@ -343,7 +341,7 @@ static void perf_record__init_features(struct perf_record *rec) perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); } -static int __cmd_record(struct perf_record *rec, int argc, const char **argv) +static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; unsigned long waking = 0; @@ -358,7 +356,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) rec->progname = argv[0]; - on_exit(perf_record__sig_exit, rec); + on_exit(record__sig_exit, rec); signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGUSR1, sig_handler); @@ -372,7 +370,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) rec->session = session; - perf_record__init_features(rec); + record__init_features(rec); if (forks) { err = perf_evlist__prepare_workload(evsel_list, &opts->target, @@ -384,7 +382,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } - if (perf_record__open(rec) != 0) { + if (record__open(rec) != 0) { err = -1; goto out_delete_session; } @@ -393,9 +391,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); /* - * perf_session__delete(session) will be called at perf_record__exit() + * perf_session__delete(session) will be called at record__exit() */ - on_exit(perf_record__exit, rec); + on_exit(record__exit, rec); if (file->is_pipe) { err = perf_header__write_pipe(file->fd); @@ -500,7 +498,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) for (;;) { int hits = rec->samples; - if (perf_record__mmap_read_all(rec) < 0) { + if (record__mmap_read_all(rec) < 0) { err = -1; goto out_delete_session; } @@ -765,8 +763,8 @@ static const char * const record_usage[] = { }; /* - * XXX Ideally would be local to cmd_record() and passed to a perf_record__new - * because we need to have access to it in perf_record__exit, that is called + * XXX Ideally would be local to cmd_record() and passed to a record__new + * because we need to have access to it in record__exit, that is called * after cmd_record() exits, but since record_options need to be accessible to * builtin-script, leave it here. * @@ -774,7 +772,7 @@ static const char * const record_usage[] = { * * Just say no to tons of global variables, sigh. */ -static struct perf_record record = { +static struct record record = { .opts = { .mmap_pages = UINT_MAX, .user_freq = UINT_MAX, @@ -881,7 +879,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) { int err = -ENOMEM; struct perf_evlist *evsel_list; - struct perf_record *rec = &record; + struct record *rec = &record; char errbuf[BUFSIZ]; evsel_list = perf_evlist__new(); From b40067964f09a5b4d9e133dec225007ee0a13050 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 14:43:45 -0300 Subject: [PATCH 17/49] perf tools: Rename 'perf_record_opts' to 'record_opts Reduce typing, functions use class__method convention, so unlikely to clash with other libraries. This actually was discussed in the "Link:" referenced message below. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20131112113427.GA4053@ghostprotocols.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 18 +++++++++--------- tools/perf/builtin-top.c | 8 ++++---- tools/perf/builtin-trace.c | 2 +- tools/perf/perf.h | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/perf-time-to-tsc.c | 2 +- tools/perf/util/callchain.h | 2 +- tools/perf/util/evlist.h | 7 +++---- tools/perf/util/evsel.c | 3 +-- tools/perf/util/evsel.h | 4 ++-- tools/perf/util/record.c | 9 ++++----- tools/perf/util/top.c | 2 +- tools/perf/util/top.h | 2 +- 17 files changed, 34 insertions(+), 37 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 154b397a5d27..5a80da6ba413 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -89,7 +89,7 @@ struct exit_reasons_table { struct perf_kvm_stat { struct perf_tool tool; - struct perf_record_opts opts; + struct record_opts opts; struct perf_evlist *evlist; struct perf_session *session; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f2624d43333e..6ec0cbc2a5d5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -64,7 +64,7 @@ static void __handle_on_exit_funcs(void) struct record { struct perf_tool tool; - struct perf_record_opts opts; + struct record_opts opts; u64 bytes_written; struct perf_data_file file; struct perf_evlist *evlist; @@ -178,7 +178,7 @@ static int record__open(struct record *rec) struct perf_evsel *pos; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; - struct perf_record_opts *opts = &rec->opts; + struct record_opts *opts = &rec->opts; int rc = 0; perf_evlist__config(evlist, opts); @@ -348,7 +348,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) const bool forks = argc > 0; struct machine *machine; struct perf_tool *tool = &rec->tool; - struct perf_record_opts *opts = &rec->opts; + struct record_opts *opts = &rec->opts; struct perf_evlist *evsel_list = rec->evlist; struct perf_data_file *file = &rec->file; struct perf_session *session; @@ -657,7 +657,7 @@ static int get_stack_size(char *str, unsigned long *_size) } #endif /* HAVE_LIBUNWIND_SUPPORT */ -int record_parse_callchain(const char *arg, struct perf_record_opts *opts) +int record_parse_callchain(const char *arg, struct record_opts *opts) { char *tok, *name, *saveptr = NULL; char *buf; @@ -713,7 +713,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts) return ret; } -static void callchain_debug(struct perf_record_opts *opts) +static void callchain_debug(struct record_opts *opts) { pr_debug("callchain: type %d\n", opts->call_graph); @@ -726,7 +726,7 @@ int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset) { - struct perf_record_opts *opts = opt->value; + struct record_opts *opts = opt->value; int ret; /* --no-call-graph */ @@ -747,7 +747,7 @@ int record_callchain_opt(const struct option *opt, const char *arg __maybe_unused, int unset __maybe_unused) { - struct perf_record_opts *opts = opt->value; + struct record_opts *opts = opt->value; if (opts->call_graph == CALLCHAIN_NONE) opts->call_graph = CALLCHAIN_FP; @@ -796,7 +796,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp"; /* * XXX Will stay a global variable till we fix builtin-script.c to stop messing * with it and switch to use the library functions in perf_evlist that came - * from builtin-record.c, i.e. use perf_record_opts, + * from builtin-record.c, i.e. use record_opts, * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', * using pipes, etc. */ @@ -944,7 +944,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) usage_with_options(record_usage, record_options); - if (perf_record_opts__config(&rec->opts)) { + if (record_opts__config(&rec->opts)) { err = -EINVAL; goto out_free_fd; } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 2c6cb66f5358..172e91a9ce62 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -854,7 +854,7 @@ static int perf_top__start_counters(struct perf_top *top) char msg[512]; struct perf_evsel *counter; struct perf_evlist *evlist = top->evlist; - struct perf_record_opts *opts = &top->record_opts; + struct record_opts *opts = &top->record_opts; perf_evlist__config(evlist, opts); @@ -906,7 +906,7 @@ static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) static int __cmd_top(struct perf_top *top) { - struct perf_record_opts *opts = &top->record_opts; + struct record_opts *opts = &top->record_opts; pthread_t thread; int ret; @@ -1028,7 +1028,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) .max_stack = PERF_MAX_STACK_DEPTH, .sym_pcnt_filter = 5, }; - struct perf_record_opts *opts = &top.record_opts; + struct record_opts *opts = &top.record_opts; struct target *target = &opts->target; const struct option options[] = { OPT_CALLBACK('e', "event", &top.evlist, "event", @@ -1179,7 +1179,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (top.delay_secs < 1) top.delay_secs = 1; - if (perf_record_opts__config(opts)) { + if (record_opts__config(opts)) { status = -EINVAL; goto out_delete_maps; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 56bbca5bc2dc..f64b5b0aa8b1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1159,7 +1159,7 @@ struct trace { int max; struct syscall *table; } syscalls; - struct perf_record_opts opts; + struct record_opts opts; struct machine *host; u64 base_time; bool full_time; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index b23fed527514..b1cc84b01d5b 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -247,7 +247,7 @@ enum perf_call_graph_mode { CALLCHAIN_DWARF }; -struct perf_record_opts { +struct record_opts { struct target target; int call_graph; bool group; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 85d4919dd623..4248d1e96848 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -391,7 +391,7 @@ static int do_test_code_reading(bool try_kcore) struct machines machines; struct machine *machine; struct thread *thread; - struct perf_record_opts opts = { + struct record_opts opts = { .mmap_pages = UINT_MAX, .user_freq = UINT_MAX, .user_interval = ULLONG_MAX, diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 376c35608534..27eb75142b88 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -51,7 +51,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm) */ int test__keep_tracking(void) { - struct perf_record_opts opts = { + struct record_opts opts = { .mmap_pages = UINT_MAX, .user_freq = UINT_MAX, .user_interval = ULLONG_MAX, diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index 41cc0badb74b..774620a5aecb 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -6,7 +6,7 @@ int test__syscall_open_tp_fields(void) { - struct perf_record_opts opts = { + struct record_opts opts = { .target = { .uid = UINT_MAX, .uses_mmap = true, diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 93a62b06c3af..eeba562920e9 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -34,7 +34,7 @@ static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) int test__PERF_RECORD(void) { - struct perf_record_opts opts = { + struct record_opts opts = { .target = { .uid = UINT_MAX, .uses_mmap = true, diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c index 4ca1b938f6a6..c6398b90e897 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/tests/perf-time-to-tsc.c @@ -46,7 +46,7 @@ static u64 rdtsc(void) */ int test__perf_time_to_tsc(void) { - struct perf_record_opts opts = { + struct record_opts opts = { .mmap_pages = UINT_MAX, .user_freq = UINT_MAX, .user_interval = ULLONG_MAX, 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/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..6874e0485693 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -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; 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/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/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. From ee4ad93e82b8fd260ae618f6b0413cd321bc09cb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:41:59 +0100 Subject: [PATCH 18/49] perf tests: Factor make install tests Factoring make install tests to check for multiple files. Adding default set of installed files for install and install_bin tests. Putting the 'test' line into the log file instead to the screen as it gets more complex now. If the tests fails to find a file, following message is displayed: $ make -f tests/make make_install_bin - make_install_bin: cd . && make -f Makefile DESTDIR=/tmp/tmp.nCVuQoSHaJ install-bin failed to find: bin/perf Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 2ca0abf1b2b6..f641c35f2321 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -106,10 +106,36 @@ test_make_python_perf_so := test -f $(PERF)/python/perf.so test_make_perf_o := test -f $(PERF)/perf.o test_make_util_map_o := test -f $(PERF)/util/map.o -test_make_install := test -x $$TMP_DEST/bin/perf -test_make_install_O := $(test_make_install) -test_make_install_bin := $(test_make_install) -test_make_install_bin_O := $(test_make_install) +define test_dest_files + for file in $(1); do \ + if [ ! -x $$TMP_DEST/$$file ]; then \ + echo " failed to find: $$file"; \ + fi \ + done +endef + +installed_files_bin := bin/perf +installed_files_bin += etc/bash_completion.d/perf +installed_files_bin += libexec/perf-core/perf-archive + +installed_files_plugins := lib64/traceevent/plugins/plugin_cfg80211.so +installed_files_plugins += lib64/traceevent/plugins/plugin_scsi.so +installed_files_plugins += lib64/traceevent/plugins/plugin_xen.so +installed_files_plugins += lib64/traceevent/plugins/plugin_function.so +installed_files_plugins += lib64/traceevent/plugins/plugin_sched_switch.so +installed_files_plugins += lib64/traceevent/plugins/plugin_mac80211.so +installed_files_plugins += lib64/traceevent/plugins/plugin_kvm.so +installed_files_plugins += lib64/traceevent/plugins/plugin_kmem.so +installed_files_plugins += lib64/traceevent/plugins/plugin_hrtimer.so +installed_files_plugins += lib64/traceevent/plugins/plugin_jbd2.so + +installed_files_all := $(installed_files_bin) +installed_files_all += $(installed_files_plugins) + +test_make_install := $(call test_dest_files,$(installed_files_all)) +test_make_install_O := $(call test_dest_files,$(installed_files_all)) +test_make_install_bin := $(call test_dest_files,$(installed_files_bin)) +test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin)) # FIXME nothing gets installed test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 @@ -162,7 +188,7 @@ $(run): cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1; \ - echo " test: $(call test,$@)"; \ + echo " test: $(call test,$@)" >> $@ 2>&1; \ $(call test,$@) && \ rm -f $@ \ rm -rf $$TMP_DEST @@ -174,7 +200,7 @@ $(run_O): cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ - echo " test: $(call test_O,$@)"; \ + echo " test: $(call test_O,$@)" >> $@ 2>&1; \ $(call test_O,$@) && \ rm -f $@ && \ rm -rf $$TMP_O \ From b7248defce917acce74b338d69c2b8f600370213 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:00 +0100 Subject: [PATCH 19/49] perf tools: Making QUIET_(CLEAN|INSTAL) variables global Moving QUIET_(CLEAN|INSTAL) variables into: tools/scripts/Makefile.include to be usable by other tools. The change to use them in libtraceevent is in following patches. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/utilities.mak | 7 ------- tools/scripts/Makefile.include | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak index f168debc5be2..4d985e0f03f5 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/perf/config/utilities.mak @@ -178,10 +178,3 @@ endef _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) _gea_warn = $(warning The path '$(1)' is not executable.) _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) - -ifneq ($(findstring $(MAKEFLAGS),s),s) - ifneq ($(V),1) - QUIET_CLEAN = @printf ' CLEAN %s\n' $1; - QUIET_INSTALL = @printf ' INSTALL %s\n' $1; - endif -endif diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index ee76544deecb..e4cfbedcaf11 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -76,5 +76,8 @@ ifneq ($(findstring $(MAKEFLAGS),s),s) +@echo ' DESCEND '$(1); \ mkdir -p $(OUTPUT)$(1) && \ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) + + QUIET_CLEAN = @printf ' CLEAN %s\n' $1; + QUIET_INSTALL = @printf ' INSTALL %s\n' $1; endif endif From db72a330587e10d6b8009e0dcf3d97aa9b1e2659 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:01 +0100 Subject: [PATCH 20/49] tools lib traceevent: Remove print_app_build variable Removing print_app_build variable, because it's not needed. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 0d9cbb426b44..022c987d25b6 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -151,7 +151,6 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = print_compile = - print_app_build = print_fpic_compile = print_shared_lib_compile = print_plugin_obj_compile = @@ -160,7 +159,6 @@ ifeq ($(VERBOSE),1) else Q = @ print_compile = echo ' CC '$(OBJ); - print_app_build = echo ' BUILD '$(OBJ); print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); @@ -173,10 +171,6 @@ do_fpic_compile = \ ($(print_fpic_compile) \ $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) -do_app_build = \ - ($(print_app_build) \ - $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)) - do_compile_shared_library = \ ($(print_shared_lib_compile) \ $(CC) --shared $^ -o $@) From c3d090f498a4d7a8905c92dbf83ae2aa4810fbef Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:02 +0100 Subject: [PATCH 21/49] tools lib traceevent: Use global QUIET_CC build output Using global QUIET_CC build output variable and getting rid of local print_compile. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 022c987d25b6..e852a8d54d84 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -67,6 +67,8 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)" PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' endif +include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include + # copy a bit from Linux kbuild ifeq ("$(origin V)", "command line") @@ -150,7 +152,6 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_compile = print_fpic_compile = print_shared_lib_compile = print_plugin_obj_compile = @@ -158,7 +159,6 @@ ifeq ($(VERBOSE),1) print_install = else Q = @ - print_compile = echo ' CC '$(OBJ); print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); @@ -188,16 +188,13 @@ do_build_static_lib = \ $(RM) $@; $(AR) rcs $@ $^) -define do_compile - $(print_compile) \ - $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; -endef +do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; $(obj)/%.o: $(src)/%.c - $(Q)$(call do_compile) + $(call do_compile) %.o: $(src)/%.c - $(Q)$(call do_compile) + $(call do_compile) PEVENT_LIB_OBJS = event-parse.o PEVENT_LIB_OBJS += event-plugin.o From bdebbacd421184234b5551c468e53956a9b6edf5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:03 +0100 Subject: [PATCH 22/49] tools lib traceevent: Add global QUIET_CC_FPIC build output Adding global QUIET_CC_FPIC build output variable and getting rid of local print_fpic_compile and print_plugin_obj_compile. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 16 ++-------------- tools/scripts/Makefile.include | 1 + 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index e852a8d54d84..24203cc14649 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,33 +152,21 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_fpic_compile = print_shared_lib_compile = - print_plugin_obj_compile = print_plugin_build = print_install = else Q = @ - print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); - print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); print_install = echo ' INSTALL '$1; endif -do_fpic_compile = \ - ($(print_fpic_compile) \ - $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) - do_compile_shared_library = \ ($(print_shared_lib_compile) \ $(CC) --shared $^ -o $@) -do_compile_plugin_obj = \ - ($(print_plugin_obj_compile) \ - $(CC) -c $(CFLAGS) -fPIC -o $@ $<) - do_plugin_build = \ ($(print_plugin_build) \ $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<) @@ -236,10 +224,10 @@ libtraceevent.a: $(PEVENT_LIB_OBJS) plugins: $(PLUGINS) $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS - $(Q)$(do_fpic_compile) + $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ $(PLUGIN_OBJS): %.o : $(src)/%.c - $(Q)$(do_compile_plugin_obj) + $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< $(PLUGINS): %.so: %.o $(Q)$(do_plugin_build) diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index e4cfbedcaf11..8abbef164b4e 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -61,6 +61,7 @@ QUIET_SUBDIR1 = ifneq ($(findstring $(MAKEFLAGS),s),s) ifneq ($(V),1) QUIET_CC = @echo ' CC '$@; + QUIET_CC_FPIC = @echo ' CC FPIC '$@; QUIET_AR = @echo ' AR '$@; QUIET_LINK = @echo ' LINK '$@; QUIET_MKDIR = @echo ' MKDIR '$@; From e6262e23134f575ae07ecc25bb69ddb63caebc95 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:04 +0100 Subject: [PATCH 23/49] tools lib traceevent: Use global QUIET_LINK build output Using global QUIET_LINK build output variable and getting rid of local print_static_lib_build, print_plugin_build and print_shared_lib_compile. We no longer distinguish between shared and static library in the build message. It's differenced by the built file suffix, like: $ make ... LINK libtraceevent.a LINK libtraceevent.so Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-7-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 24203cc14649..51be8ab76f9f 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,14 +152,9 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_shared_lib_compile = - print_plugin_build = print_install = else Q = @ - print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); - print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); - print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); print_install = echo ' INSTALL '$1; endif @@ -216,10 +211,10 @@ all: all_cmd all_cmd: $(CMD_TARGETS) libtraceevent.so: $(PEVENT_LIB_OBJS) - $(Q)$(do_compile_shared_library) + $(QUIET_LINK)$(CC) --shared $^ -o $@ libtraceevent.a: $(PEVENT_LIB_OBJS) - $(Q)$(do_build_static_lib) + $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ plugins: $(PLUGINS) @@ -230,7 +225,7 @@ $(PLUGIN_OBJS): %.o : $(src)/%.c $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< $(PLUGINS): %.so: %.o - $(Q)$(do_plugin_build) + $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< define make_version.h (echo '/* This file is automatically generated. Do not modify. */'; \ From 02a82c7bcd353b8cc4d4f8b3c872b527fbac7c31 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:05 +0100 Subject: [PATCH 24/49] tools lib traceevent: Use global QUIET_INSTALL build output Using global QUIET_INSTALL build output variable and factoring plugins installation so we could have only single install message for plugins: INSTALL trace_plugins Getting rid of local print_install. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-8-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 51be8ab76f9f..8ea4368381f0 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,10 +152,8 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_install = else Q = @ - print_install = echo ' INSTALL '$1; endif do_compile_shared_library = \ @@ -307,22 +305,25 @@ TAGS: force --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' define do_install - $(print_install) \ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ fi; \ $(INSTALL) $1 '$(DESTDIR_SQ)$2' endef +define do_install_plugins + for plugin in $1; do \ + $(call do_install,$$plugin,$(plugin_dir_SQ)); \ + done +endef + install_lib: all_cmd install_plugins - $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) + $(call QUIET_INSTALL, $(LIB_FILE)) \ + $(call do_install,$(LIB_FILE),$(bindir_SQ)) -PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS)) - -$(PLUGINS_INSTALL): %.install : %.so force - $(Q)$(call do_install,$<,$(plugin_dir_SQ)) - -install_plugins: $(PLUGINS_INSTALL) +install_plugins: $(PLUGINS) + $(call QUIET_INSTALL, trace_plugins) \ + $(call do_install_plugins, $(PLUGINS)) install: install_lib From 4a953c716af285c94432e2d303ca5ee8f66129c0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:06 +0100 Subject: [PATCH 25/49] tools lib traceevent: Use global QUIET_CLEAN build output Using global QUIET_CLEAN build output variable and so we could have only single clean message: CLEAN libtraceevent Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-9-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 8ea4368381f0..3496c9ce84d4 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -328,8 +328,9 @@ install_plugins: $(PLUGINS) install: install_lib clean: - $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d - $(RM) TRACEEVENT-CFLAGS tags TAGS + $(call QUIET_CLEAN, libtraceevent) \ + $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ + $(RM) TRACEEVENT-CFLAGS tags TAGS endif # skip-makefile From 4c7aafc950178cd78f8cbda916ee8208afe039b5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:07 +0100 Subject: [PATCH 26/49] tools lib traceevent: Use global 'O' processing code Using global 'O' processing code because it's already setup due to the scripts/Makefile.include include. Using global variable OUTPUT instead of the local BUILD_OUTPUT. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-10-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 3496c9ce84d4..ca4ab78425d1 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -83,18 +83,13 @@ ifeq ("$(origin O)", "command line") endif ifeq ($(BUILD_SRC),) -ifneq ($(BUILD_OUTPUT),) +ifneq ($(OUTPUT),) define build_output - $(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT) \ - BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 + $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ + BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 endef -saved-output := $(BUILD_OUTPUT) -BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd) -$(if $(BUILD_OUTPUT),, \ - $(error output directory "$(saved-output)" does not exist)) - all: sub-make $(MAKECMDGOALS): sub-make @@ -106,7 +101,7 @@ sub-make: force # Leave processing to above invocation of make skip-makefile := 1 -endif # BUILD_OUTPUT +endif # OUTPUT endif # BUILD_SRC # We process the rest of the Makefile if this is the final invocation of make From 28b21393fa0472501b5a2a85a0b008b4e3dc154c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 14:53:53 -0300 Subject: [PATCH 27/49] perf report: Rename 'perf_report' to 'report' Reduce typing, functions use class__method convention, so unlikely to clash with other libraries. This actually was discussed in the "Link:" referenced message below. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20131112113427.GA4053@ghostprotocols.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 73 ++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8424053b399a..da156a44cb15 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -39,7 +39,7 @@ #include #include -struct perf_report { +struct report { struct perf_tool tool; struct perf_session *session; bool force, use_tui, use_gtk, use_stdio; @@ -60,14 +60,14 @@ struct perf_report { DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); }; -static int perf_report_config(const char *var, const char *value, void *cb) +static int report__config(const char *var, const char *value, void *cb) { if (!strcmp(var, "report.group")) { symbol_conf.event_group = perf_config_bool(var, value); return 0; } if (!strcmp(var, "report.percent-limit")) { - struct perf_report *rep = cb; + struct report *rep = cb; rep->min_percent = strtof(value, NULL); return 0; } @@ -75,7 +75,7 @@ static int perf_report_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } -static int report__resolve_callchain(struct perf_report *rep, struct symbol **parent, +static int report__resolve_callchain(struct report *rep, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, struct perf_sample *sample, struct machine *machine) { @@ -93,14 +93,11 @@ static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sampl return callchain_append(he->callchain, &callchain_cursor, sample->period); } -static int perf_report__add_mem_hist_entry(struct perf_tool *tool, - struct addr_location *al, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine, - union perf_event *event) +static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al, + struct perf_sample *sample, struct perf_evsel *evsel, + struct machine *machine, union perf_event *event) { - struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; struct hist_entry *he; @@ -150,13 +147,11 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, return err; } -static int perf_report__add_branch_hist_entry(struct perf_tool *tool, - struct addr_location *al, - struct perf_sample *sample, - struct perf_evsel *evsel, - struct machine *machine) +static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, + struct perf_sample *sample, struct perf_evsel *evsel, + struct machine *machine) { - struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; unsigned i; struct hist_entry *he; @@ -208,13 +203,11 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, return err; } -static int perf_evsel__add_hist_entry(struct perf_tool *tool, - struct perf_evsel *evsel, - struct addr_location *al, - struct perf_sample *sample, - struct machine *machine) +static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel, + struct addr_location *al, struct perf_sample *sample, + struct machine *machine) { - struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; struct hist_entry *he; int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); @@ -246,7 +239,7 @@ static int process_sample_event(struct perf_tool *tool, struct perf_evsel *evsel, struct machine *machine) { - struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct report *rep = container_of(tool, struct report, tool); struct addr_location al; int ret; @@ -263,21 +256,18 @@ static int process_sample_event(struct perf_tool *tool, return 0; if (sort__mode == SORT_MODE__BRANCH) { - ret = perf_report__add_branch_hist_entry(tool, &al, sample, - evsel, machine); + ret = report__add_branch_hist_entry(tool, &al, sample, evsel, machine); if (ret < 0) pr_debug("problem adding lbr entry, skipping event\n"); } else if (rep->mem_mode == 1) { - ret = perf_report__add_mem_hist_entry(tool, &al, sample, - evsel, machine, event); + ret = report__add_mem_hist_entry(tool, &al, sample, evsel, machine, event); if (ret < 0) pr_debug("problem adding mem entry, skipping event\n"); } else { if (al.map != NULL) al.map->dso->hit = 1; - ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample, - machine); + ret = report__add_hist_entry(tool, evsel, &al, sample, machine); if (ret < 0) pr_debug("problem incrementing symbol period, skipping event\n"); } @@ -290,7 +280,7 @@ static int process_read_event(struct perf_tool *tool, struct perf_evsel *evsel, struct machine *machine __maybe_unused) { - struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct report *rep = container_of(tool, struct report, tool); if (rep->show_threads) { const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; @@ -309,7 +299,7 @@ static int process_read_event(struct perf_tool *tool, } /* For pipe mode, sample_type is not currently set */ -static int perf_report__setup_sample_type(struct perf_report *rep) +static int report__setup_sample_type(struct report *rep) { struct perf_session *session = rep->session; u64 sample_type = perf_evlist__combined_sample_type(session->evlist); @@ -354,8 +344,7 @@ static void sig_handler(int sig __maybe_unused) session_done = 1; } -static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, - struct hists *hists, +static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep, const char *evname, FILE *fp) { size_t ret; @@ -392,7 +381,7 @@ static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, } static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, - struct perf_report *rep, + struct report *rep, const char *help) { struct perf_evsel *pos; @@ -405,7 +394,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, !perf_evsel__is_group_leader(pos)) continue; - hists__fprintf_nr_sample_events(rep, hists, evname, stdout); + hists__fprintf_nr_sample_events(hists, rep, evname, stdout); hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); fprintf(stdout, "\n\n"); } @@ -425,7 +414,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, return 0; } -static int __cmd_report(struct perf_report *rep) +static int __cmd_report(struct report *rep) { int ret = -EINVAL; u64 nr_samples; @@ -449,7 +438,7 @@ static int __cmd_report(struct perf_report *rep) if (rep->show_threads) perf_read_values_init(&rep->show_threads_values); - ret = perf_report__setup_sample_type(rep); + ret = report__setup_sample_type(rep); if (ret) return ret; @@ -568,7 +557,7 @@ static int __cmd_report(struct perf_report *rep) static int parse_callchain_opt(const struct option *opt, const char *arg, int unset) { - struct perf_report *rep = (struct perf_report *)opt->value; + struct report *rep = (struct report *)opt->value; char *tok, *tok2; char *endptr; @@ -688,7 +677,7 @@ static int parse_percent_limit(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_report *rep = opt->value; + struct report *rep = opt->value; rep->min_percent = strtof(str, NULL); return 0; @@ -706,7 +695,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "perf report []", NULL }; - struct perf_report report = { + struct report report = { .tool = { .sample = process_sample_event, .mmap = perf_event__process_mmap, @@ -822,7 +811,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .mode = PERF_DATA_MODE_READ, }; - perf_config(perf_report_config, &report); + perf_config(report__config, &report); argc = parse_options(argc, argv, options, report_usage, 0); From 3184c47cb8b04b8bb5c1005168049519b066bcd1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 16:25:17 -0300 Subject: [PATCH 28/49] perf ui browser: Remove misplaced __maybe_unused The 'browser' arg _is_ used, so ditch the misplaced attribute. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-bo4dabkip5iikhk3x384ac46@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index cbaa7af45513..94223d404f43 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -268,7 +268,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, return err ? 0 : -1; } -void ui_browser__hide(struct ui_browser *browser __maybe_unused) +void ui_browser__hide(struct ui_browser *browser) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); From b7fff6b5f977115be1757f18b1aca928803b1e17 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 16:34:52 -0300 Subject: [PATCH 29/49] perf scripting python: Shorten function signatures Removing unused parameters. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-fspmnjadohrik8uvhytyu8lp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../scripting-engines/trace-event-python.c | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 53c20e7fd900..fc007926eb1c 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -231,13 +231,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 +348,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 +405,20 @@ static void python_process_general_event(union perf_event *perf_event 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 machine *machine __maybe_unused, 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); } } From 8853a1b76288d79aa1a6c5b8fe623d892aa9958b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 16:39:31 -0300 Subject: [PATCH 30/49] perf scripting perl: Shorten function signatures Removing unused parameters. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-b7r7o80o2xwwtlzgqxv50foe@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../util/scripting-engines/trace-event-perl.c | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d5e5969f6fea..b672ef0ae46d 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -257,12 +257,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 +346,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 +371,12 @@ 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 machine *machine __maybe_unused, 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) From 8b640cc4c56cee14bfe5cfb4dbb372ac66d5ec6b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 17:00:45 -0300 Subject: [PATCH 31/49] perf mem: Remove unused parameter from dump_raw_samples() The 'evsel' parameter is not used, ditch it, reducing the function signature. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-kx9temzdcy7mk2edya9c1tdu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-mem.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 31c00f186da1..2e3ade69a58e 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -62,7 +62,6 @@ static int dump_raw_samples(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, struct machine *machine) { struct perf_mem *mem = container_of(tool, struct perf_mem, tool); @@ -112,10 +111,10 @@ dump_raw_samples(struct perf_tool *tool, static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct perf_evsel *evsel __maybe_unused, struct machine *machine) { - return dump_raw_samples(tool, event, sample, evsel, machine); + return dump_raw_samples(tool, event, sample, machine); } static int report_raw_events(struct perf_mem *mem) From cc22e575a6fddbe3183ac14c28e2f792704995c5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Dec 2013 17:20:06 -0300 Subject: [PATCH 32/49] perf symbols: Add 'machine' member to struct addr_location The addr_location struct should fully qualify an address, and to do that it should have in it the machine where the thread was found. Thus all functions that receive an addr_location now don't need to also receive a 'machine', those functions just need to access al->machine instead, just like it does with the other parts of an address location: al->thread, al->map, etc. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-o51iiee7vyq4r3k362uvuylg@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 28 +++++++++---------- tools/perf/builtin-script.c | 16 +++++------ tools/perf/util/event.c | 1 + .../util/scripting-engines/trace-event-perl.c | 1 - .../scripting-engines/trace-event-python.c | 1 - tools/perf/util/session.c | 4 +-- tools/perf/util/session.h | 2 +- tools/perf/util/symbol.h | 1 + tools/perf/util/trace-event-scripting.c | 3 +- tools/perf/util/trace-event.h | 1 - 10 files changed, 26 insertions(+), 32 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index da156a44cb15..ec7399a84872 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -77,10 +77,10 @@ static int report__config(const char *var, const char *value, void *cb) static int report__resolve_callchain(struct report *rep, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, - struct perf_sample *sample, struct machine *machine) + struct perf_sample *sample) { if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - return machine__resolve_callchain(machine, evsel, al->thread, sample, + return machine__resolve_callchain(al->machine, evsel, al->thread, sample, parent, al, rep->max_stack); } return 0; @@ -95,7 +95,7 @@ static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sampl static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine, union perf_event *event) + union perf_event *event) { struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; @@ -103,12 +103,12 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati struct hist_entry *he; struct mem_info *mi, *mx; uint64_t cost; - int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); + int err = report__resolve_callchain(rep, &parent, evsel, al, sample); if (err) return err; - mi = machine__resolve_mem(machine, al->thread, sample, cpumode); + mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode); if (!mi) return -ENOMEM; @@ -148,20 +148,19 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati } static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, - struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine) + struct perf_sample *sample, struct perf_evsel *evsel) { struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; unsigned i; struct hist_entry *he; struct branch_info *bi, *bx; - int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); + int err = report__resolve_callchain(rep, &parent, evsel, al, sample); if (err) return err; - bi = machine__resolve_bstack(machine, al->thread, + bi = machine__resolve_bstack(al->machine, al->thread, sample->branch_stack); if (!bi) return -ENOMEM; @@ -204,13 +203,12 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc } static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel, - struct addr_location *al, struct perf_sample *sample, - struct machine *machine) + struct addr_location *al, struct perf_sample *sample) { struct report *rep = container_of(tool, struct report, tool); struct symbol *parent = NULL; struct hist_entry *he; - int err = report__resolve_callchain(rep, &parent, evsel, al, sample, machine); + int err = report__resolve_callchain(rep, &parent, evsel, al, sample); if (err) return err; @@ -256,18 +254,18 @@ static int process_sample_event(struct perf_tool *tool, return 0; if (sort__mode == SORT_MODE__BRANCH) { - ret = report__add_branch_hist_entry(tool, &al, sample, evsel, machine); + ret = report__add_branch_hist_entry(tool, &al, sample, evsel); if (ret < 0) pr_debug("problem adding lbr entry, skipping event\n"); } else if (rep->mem_mode == 1) { - ret = report__add_mem_hist_entry(tool, &al, sample, evsel, machine, event); + ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event); if (ret < 0) pr_debug("problem adding mem entry, skipping event\n"); } else { if (al.map != NULL) al.map->dso->hit = 1; - ret = report__add_hist_entry(tool, evsel, &al, sample, machine); + ret = report__add_hist_entry(tool, evsel, &al, sample); if (ret < 0) pr_debug("problem incrementing symbol period, skipping event\n"); } diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index f8ab125aac48..62ef190c4320 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -423,7 +423,6 @@ static void print_sample_addr(union perf_event *event, static void print_sample_bts(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine, struct thread *thread, struct addr_location *al) { @@ -435,7 +434,7 @@ static void print_sample_bts(union perf_event *event, printf(" "); else printf("\n"); - perf_evsel__print_ip(evsel, sample, machine, al, + perf_evsel__print_ip(evsel, sample, al, output[attr->type].print_ip_opts, PERF_MAX_STACK_DEPTH); } @@ -446,14 +445,13 @@ static void print_sample_bts(union perf_event *event, if (PRINT_FIELD(ADDR) || ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && !output[attr->type].user_set)) - print_sample_addr(event, sample, machine, thread, attr); + print_sample_addr(event, sample, al->machine, thread, attr); printf("\n"); } static void process_event(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, struct machine *machine, - struct thread *thread, + struct perf_evsel *evsel, struct thread *thread, struct addr_location *al) { struct perf_event_attr *attr = &evsel->attr; @@ -469,7 +467,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, } if (is_bts_event(attr)) { - print_sample_bts(event, sample, evsel, machine, thread, al); + print_sample_bts(event, sample, evsel, thread, al); return; } @@ -477,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, event_format__print(evsel->tp_format, sample->cpu, sample->raw_data, sample->raw_size); if (PRINT_FIELD(ADDR)) - print_sample_addr(event, sample, machine, thread, attr); + print_sample_addr(event, sample, al->machine, thread, attr); if (PRINT_FIELD(IP)) { if (!symbol_conf.use_callchain) @@ -485,7 +483,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, else printf("\n"); - perf_evsel__print_ip(evsel, sample, machine, al, + perf_evsel__print_ip(evsel, sample, al, output[attr->type].print_ip_opts, PERF_MAX_STACK_DEPTH); } @@ -574,7 +572,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) return 0; - scripting_ops->process_event(event, sample, evsel, machine, thread, &al); + scripting_ops->process_event(event, sample, evsel, thread, &al); evsel->hists.stats.total_period += sample->period; return 0; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 694876877ae2..fe2022799161 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -638,6 +638,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; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index b672ef0ae46d..3773c4841cab 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -371,7 +371,6 @@ 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 __maybe_unused, struct thread *thread, struct addr_location *al __maybe_unused) { diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index fc007926eb1c..b258de6357ac 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -408,7 +408,6 @@ static void python_process_general_event(struct perf_sample *sample, static void python_process_event(union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __maybe_unused, struct thread *thread, struct addr_location *al) { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 989b2e377626..cbacaab3e9c4 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1467,7 +1467,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 +1482,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/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/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); From a42101418072d3be357b534521be2849518611e6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 20 Dec 2013 14:11:12 +0900 Subject: [PATCH 33/49] perf report: Use pr_*() functions where applicable There're some places printing messages to stdout/err directly. It should be converted to use proper error printing functions instead. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1387516278-17024-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ec7399a84872..0c9ec3e3f0fc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -242,8 +242,8 @@ static int process_sample_event(struct perf_tool *tool, int ret; if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { - fprintf(stderr, "problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %d event, skipping it.\n", + event->header.type); return -1; } @@ -637,7 +637,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) return -1; setup: if (callchain_register_param(&callchain_param) < 0) { - fprintf(stderr, "Can't register callchain params\n"); + pr_err("Can't register callchain params\n"); return -1; } return 0; @@ -859,7 +859,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) } if (report.mem_mode) { if (sort__mode == SORT_MODE__BRANCH) { - fprintf(stderr, "branch and mem mode incompatible\n"); + pr_err("branch and mem mode incompatible\n"); goto error; } sort__mode = SORT_MODE__MEMORY; From 150e465ac99ed18fb9555c16e0def7ce01913a2a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 20 Dec 2013 14:11:13 +0900 Subject: [PATCH 34/49] perf report: Print session information only if --stdio is given Move those print functions under "if (use_browser == 0)" so that they don't interfere with TUI output. Maybe they can handle other UIs later. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1387516278-17024-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0c9ec3e3f0fc..bf8dd2e893e4 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -469,15 +469,17 @@ static int __cmd_report(struct report *rep) desc); } - if (verbose > 3) - perf_session__fprintf(session, stdout); + if (use_browser == 0) { + if (verbose > 3) + perf_session__fprintf(session, stdout); - if (verbose > 2) - perf_session__fprintf_dsos(session, stdout); + if (verbose > 2) + perf_session__fprintf_dsos(session, stdout); - if (dump_trace) { - perf_session__fprintf_nr_events(session, stdout); - return 0; + if (dump_trace) { + perf_session__fprintf_nr_events(session, stdout); + return 0; + } } nr_samples = 0; From ad85ace07a05062ef6b59c35a5e80b6eaee1eee6 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 13:41:47 -0500 Subject: [PATCH 35/49] perf kvm: Fix kvm report without guestmount. Currently, if we use perf kvm --guestkallsyms --guestmodules report, we can not get the perf information from perf data file. All sample are shown as unknown. Reproducing steps: # perf kvm --guestkallsyms /tmp/kallsyms --guestmodules /tmp/modules record -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.624 MB perf.data.guest (~27260 samples) ] # perf kvm --guestkallsyms /tmp/kallsyms --guestmodules /tmp/modules report |grep % 100.00% [guest/6471] [unknown] [g] 0xffffffff8164f330 This bug was introduced by 207b57926 (perf kvm: Fix regression with guest machine creation). In original code, it uses perf_session__find_machine(), it means we deliver symbol to machine which has the same pid, if no machine found, deliver it to *default* guest. But if we use perf_session__findnew_machine() here, if no machine was found, new machine with pid will be built and added. Then the default guest which with pid == 0 will never get a symbol. And because the new machine initialized here has no kernel map created, the symbol delivered to it will be marked as "unknown". This patch here is to revert commit 207b57926 and fix the SEGFAULT bug in another way. Verification steps: # ./perf kvm --guestkallsyms /home/kallsyms --guestmodules /home/modules record -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.651 MB perf.data.guest (~28437 samples) ] # ./perf kvm --guestkallsyms /home/kallsyms --guestmodules /home/modules report |grep % 22.64% :6471 [guest.kernel.kallsyms] [g] update_rq_clock.part.70 19.99% :6471 [guest.kernel.kallsyms] [g] d_free 18.46% :6471 [guest.kernel.kallsyms] [g] bio_phys_segments 16.25% :6471 [guest.kernel.kallsyms] [g] dequeue_task 12.78% :6471 [guest.kernel.kallsyms] [g] __switch_to 7.91% :6471 [guest.kernel.kallsyms] [g] scheduler_tick 1.75% :6471 [guest.kernel.kallsyms] [g] native_apic_mem_write 0.21% :6471 [guest.kernel.kallsyms] [g] apic_timer_interrupt Signed-off-by: Dongsheng Yang Acked-by: David Ahern Cc: stable@vger.kernel.org # 3.3+ Cc: David Ahern Link: http://lkml.kernel.org/r/1387564907-3045-1-git-send-email-yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cbacaab3e9c4..d3a857be9682 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -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; From fb50bb43d051d12aad9e2337d0d5d14d0d3dd281 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 15:52:56 -0500 Subject: [PATCH 36/49] perf tools: Add support for PERF_RECORD_MISC_GUEST_USER in thread__find_addr_map(). This patch remove a TODO in thread__find_addr_map() and add support of PERF_RECORD_MISC_GUEST_USER. Signed-off-by: Dongsheng Yang Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/3dd652201171a19c910b500984c7c3590e77603b.1387572416.git.yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index fe2022799161..484e99464a00 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -659,15 +659,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 || From 995634650ef1f907196bd7e9ae45354124a80e47 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 15:52:57 -0500 Subject: [PATCH 37/49] perf tools: Find the proc info under machine->root_dir. When we synthesize the threads, we are looking for the infomation under /proc. But it is only for host. This patch look for the path of proc under machine->root_dir, then XXX__synthesize_threads() functions can support guest machines. Signed-off-by: Dongsheng Yang Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/927b937da9177a079abafe4532fa9c9b60b5c4b7.1387572416.git.yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 484e99464a00..a61726ea01a9 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -129,7 +129,8 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, goto out; } - snprintf(filename, sizeof(filename), "/proc/%d/task", pid); + snprintf(filename, sizeof(filename), "%s/proc/%d/task", + machine->root_dir, pid); tasks = opendir(filename); if (tasks == NULL) { @@ -178,7 +179,8 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, FILE *fp; int rc = 0; - snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); + snprintf(filename, sizeof(filename), "%s/proc/%d/maps", + machine->root_dir, pid); fp = fopen(filename, "r"); if (fp == NULL) { @@ -387,6 +389,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 +402,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (mmap_event == NULL) goto out_free_comm; - proc = opendir("/proc"); + snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); + proc = opendir(proc_path); + if (proc == NULL) goto out_free_mmap; From 73547aacdcd45cdf8b53245ded9593d7c587501a Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 15:52:58 -0500 Subject: [PATCH 38/49] perf tools: Set event->header.misc to PERF_RECORD_MISC_GUEST_USER if machine is guest. When we synthesize the mmap events of user space, if machine is guest, we should set the event->header.misc to PERF_RECORD_MISC_GUEST_USER, rather than PERF_RECORD_MISC_USER. Signed-off-by: Dongsheng Yang Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/e6f8ff6505d2db8a4b21bff8e448bb9be0bcff35.1387572416.git.yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index a61726ea01a9..07c07833de53 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -220,7 +220,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') From f5db57c4c47f3985dfc677152e25636a3401fa13 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 15:52:59 -0500 Subject: [PATCH 39/49] perf tools: Use machine->pid for tgid if machine is guest. When we synthesize an comm event, if machine is guest, we should use the pid of machine as the event->comm.pid, rather than tgid of thread. Signed-off-by: Dongsheng Yang Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/22455abe107c618a361e7b667ad0f098f7c9b4a3.1387572416.git.yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 07c07833de53..2905771a1f49 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; From c239c25a82808ad2cbc795b69e621c4c24f154d6 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 20 Dec 2013 15:53:00 -0500 Subject: [PATCH 40/49] perf tools: Do not synthesize the treads of default guest. As the default guest is designed to handle orphan kernel symboles with --guestkallsysms and --guestmodules, it has no user space. So we should skip synthesizing threads if machine is default guest. Signed-off-by: Dongsheng Yang Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/e9ddb5dac6f963169657218b12ceb3c2030f54e8.1387572416.git.yangds.fnst@cn.fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2905771a1f49..45a76c69a9ed 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -133,6 +133,9 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, goto out; } + if (machine__is_default_guest(machine)) + return 0; + snprintf(filename, sizeof(filename), "%s/proc/%d/task", machine->root_dir, pid); @@ -183,6 +186,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, FILE *fp; int rc = 0; + if (machine__is_default_guest(machine)) + return 0; + snprintf(filename, sizeof(filename), "%s/proc/%d/maps", machine->root_dir, pid); @@ -409,6 +415,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (mmap_event == NULL) goto out_free_comm; + if (machine__is_default_guest(machine)) + return 0; + snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); proc = opendir(proc_path); From 56560ec692c142bb9ee404764e3b67999031ad19 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Sat, 21 Dec 2013 13:48:11 +0800 Subject: [PATCH 41/49] perf config: Ignore generated files in feature-checks 1. Rename the test-* binary files to test-*.bin for easier pattern matching as suggested by Ingo. 2. Ignore *.bin and *.d files. Signed-off-by: Chunwei Chen Reviewed-by: Ingo Molnar Acked-by: Jiri Olsa Cc: Ingo Molnar Cc: Jiri Olsa Link: http://lkml.kernel.org/r/52B52B9B.50708@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile | 6 +- tools/perf/config/feature-checks/.gitignore | 2 + tools/perf/config/feature-checks/Makefile | 110 ++++++++++---------- 3 files changed, 60 insertions(+), 58 deletions(-) create mode 100644 tools/perf/config/feature-checks/.gitignore diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 5a1f4df3c3a8..14faeeb0d752 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -126,7 +126,7 @@ endif feature_check = $(eval $(feature_check_code)) define feature_check_code - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0) + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) endef feature_set = $(eval $(feature_set_code)) @@ -173,7 +173,7 @@ CORE_FEATURE_TESTS = \ # to skip the print-out of the long features list if the file # existed before and after it was built: # -ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),) +ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),) test-all-failed := 1 else test-all-failed := 0 @@ -203,7 +203,7 @@ ifeq ($(feature-all), 1) # $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat))) else - $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1) + $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1) $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) endif diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore new file mode 100644 index 000000000000..80f3da0c3515 --- /dev/null +++ b/tools/perf/config/feature-checks/.gitignore @@ -0,0 +1,2 @@ +*.d +*.bin diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile index bc86462e80a2..7cf6fcdacebe 100644 --- a/tools/perf/config/feature-checks/Makefile +++ b/tools/perf/config/feature-checks/Makefile @@ -1,90 +1,90 @@ FILES= \ - test-all \ - test-backtrace \ - test-bionic \ - test-dwarf \ - test-fortify-source \ - test-glibc \ - test-gtk2 \ - test-gtk2-infobar \ - test-hello \ - test-libaudit \ - test-libbfd \ - test-liberty \ - test-liberty-z \ - test-cplus-demangle \ - test-libelf \ - test-libelf-getphdrnum \ - test-libelf-mmap \ - test-libnuma \ - test-libperl \ - test-libpython \ - test-libpython-version \ - test-libslang \ - test-libunwind \ - test-libunwind-debug-frame \ - test-on-exit \ - test-stackprotector-all \ - test-timerfd + test-all.bin \ + test-backtrace.bin \ + test-bionic.bin \ + test-dwarf.bin \ + test-fortify-source.bin \ + test-glibc.bin \ + test-gtk2.bin \ + test-gtk2-infobar.bin \ + test-hello.bin \ + test-libaudit.bin \ + test-libbfd.bin \ + test-liberty.bin \ + test-liberty-z.bin \ + test-cplus-demangle.bin \ + test-libelf.bin \ + test-libelf-getphdrnum.bin \ + test-libelf-mmap.bin \ + test-libnuma.bin \ + test-libperl.bin \ + test-libpython.bin \ + test-libpython-version.bin \ + test-libslang.bin \ + test-libunwind.bin \ + test-libunwind-debug-frame.bin \ + test-on-exit.bin \ + test-stackprotector-all.bin \ + test-timerfd.bin CC := $(CC) -MD all: $(FILES) -BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $@.c $(LDFLAGS) +BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) ############################### -test-all: +test-all.bin: $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -test-hello: +test-hello.bin: $(BUILD) -test-stackprotector-all: +test-stackprotector-all.bin: $(BUILD) -Werror -fstack-protector-all -test-fortify-source: +test-fortify-source.bin: $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 -test-bionic: +test-bionic.bin: $(BUILD) -test-libelf: +test-libelf.bin: $(BUILD) -lelf -test-glibc: +test-glibc.bin: $(BUILD) -test-dwarf: +test-dwarf.bin: $(BUILD) -ldw -test-libelf-mmap: +test-libelf-mmap.bin: $(BUILD) -lelf -test-libelf-getphdrnum: +test-libelf-getphdrnum.bin: $(BUILD) -lelf -test-libnuma: +test-libnuma.bin: $(BUILD) -lnuma -test-libunwind: +test-libunwind.bin: $(BUILD) -lelf -test-libunwind-debug-frame: +test-libunwind-debug-frame.bin: $(BUILD) -lelf -test-libaudit: +test-libaudit.bin: $(BUILD) -laudit -test-libslang: +test-libslang.bin: $(BUILD) -I/usr/include/slang -lslang -test-gtk2: +test-gtk2.bin: $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) -test-gtk2-infobar: +test-gtk2-infobar.bin: $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) grep-libs = $(filter -l%,$(1)) @@ -96,7 +96,7 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) -test-libperl: +test-libperl.bin: $(BUILD) $(FLAGS_PERL_EMBED) override PYTHON := python @@ -113,31 +113,31 @@ PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) -test-libpython: +test-libpython.bin: $(BUILD) $(FLAGS_PYTHON_EMBED) -test-libpython-version: +test-libpython-version.bin: $(BUILD) $(FLAGS_PYTHON_EMBED) -test-libbfd: +test-libbfd.bin: $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl -test-liberty: +test-liberty.bin: $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -test-liberty-z: +test-liberty-z.bin: $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz -test-cplus-demangle: +test-cplus-demangle.bin: $(BUILD) -liberty -test-on-exit: +test-on-exit.bin: $(BUILD) -test-backtrace: +test-backtrace.bin: $(BUILD) -test-timerfd: +test-timerfd.bin: $(BUILD) -include *.d From 8a613d40e389b723fd5889ac8d4033ed4030be31 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 26 Dec 2013 05:41:50 +0000 Subject: [PATCH 42/49] perf probe: Expand given path to absolute path Expand given path to absolute path in the option parser, except for a module name. Since realpath at later stage in processing several probe point, can be called several times (even if currently doesn't, it can happen when we expands the feature), it is waste of the performance. Processing it once at the early stage can avoid that. Changes from previous one: - Fix not to print null string. - Allocate memory for given path/module name everytime. Signed-off-by: Masami Hiramatsu Cc: "David A. Long" Cc: "Steven Rostedt (Red Hat)" Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Oleg Nesterov Cc: Srikar Dronamraju Cc: systemtap@sourceware.org Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20131226054150.22364.12187.stgit@kbuild-fedora.novalocal [ Clarified the pr_warning message as per David Ahern's suggestion ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-probe.c | 15 ++++++++++++++- tools/perf/util/probe-event.c | 11 ++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index c98ccb570509..1792a3f1f4ce 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -169,6 +169,7 @@ static int opt_set_target(const struct option *opt, const char *str, int unset __maybe_unused) { int ret = -ENOENT; + char *tmp; if (str && !params.target) { if (!strcmp(opt->long_name, "exec")) @@ -180,7 +181,19 @@ static int opt_set_target(const struct option *opt, const char *str, else return ret; - params.target = str; + /* Expand given path to absolute path, except for modulename */ + if (params.uprobes || strchr(str, '/')) { + tmp = realpath(str, NULL); + if (!tmp) { + pr_warning("Failed to get the absolute path of %s: %m\n", str); + return ret; + } + } else { + tmp = strdup(str); + if (!tmp) + return -ENOMEM; + } + params.target = tmp; ret = 0; } diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 544ac1898a9f..68013b91377c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2281,7 +2281,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 +2297,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 +2362,5 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) } if (function) free(function); - if (name) - free(name); return ret; } From fb7345bbf7fad9bf72ef63a19c707970b9685812 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 26 Dec 2013 05:41:53 +0000 Subject: [PATCH 43/49] perf probe: Support basic dwarf-based operations on uprobe events Support basic dwarf(debuginfo) based operations for uprobe events. With this change, perf probe can analyze debuginfo of user application binary to set up new uprobe event. This allows perf-probe --add(with local variables, line numbers) and --line works with -x option. (Actually, --vars has already accepted -x option) For example, the following command shows the probe-able lines of a given user space function. Something that so far was only available in the 'perf probe' tool for kernel space functions: # ./perf probe -x perf --line map__load 0 int map__load(struct map *map, symbol_filter_t filter) 1 { 2 const char *name = map->dso->long_name; int nr; 5 if (dso__loaded(map->dso, map->type)) 6 return 0; 8 nr = dso__load(map->dso, map, filter); 9 if (nr < 0) { 10 if (map->dso->has_build_id) { And this shows the available variables at the given line of the function. # ./perf probe -x perf --vars map__load:8 Available variables at map__load:8 @ char* name struct map* map symbol_filter_t filter @ char* name symbol_filter_t filter @ char* name symbol_filter_t filter @ char* name struct map* map symbol_filter_t filter And lastly, we can now define probe(s) with all available variables on the given line: # ./perf probe -x perf --add 'map__load:8 $vars' Added new events: probe_perf:map__load (on map__load:8 with $vars) probe_perf:map__load_1 (on map__load:8 with $vars) probe_perf:map__load_2 (on map__load:8 with $vars) probe_perf:map__load_3 (on map__load:8 with $vars) You can now use it in all perf tools, such as: perf record -e probe_perf:map__load_3 -aR sleep 1 Changes from previous version: - Add examples in the patch description. - Use .text section start address and dwarf symbol address for calculating the offset of given symbol, instead of searching the symbol in symtab again. With this change, we can safely handle multiple local function instances (e.g. scnprintf in perf). Signed-off-by: Masami Hiramatsu Cc: David Ahern Cc: David A. Long Cc: Ingo Molnar Cc: Namhyung Kim Cc: Oleg Nesterov Cc: Srikar Dronamraju Cc: Steven Rostedt Cc: systemtap@sourceware.org Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20131226054152.22364.47021.stgit@kbuild-fedora.novalocal Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-probe.c | 2 +- tools/perf/util/probe-event.c | 151 +++++++++++++++++++++++++++++---- tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-finder.c | 1 + 4 files changed, 138 insertions(+), 17 deletions(-) diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 1792a3f1f4ce..43ff33d0007b 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -424,7 +424,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) } #ifdef HAVE_DWARF_SUPPORT - if (params.show_lines && !params.uprobes) { + if (params.show_lines) { if (params.mod_events) { pr_err(" Error: Don't use --line with" " --add/--del.\n"); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 68013b91377c..72b56aef105e 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; + free(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) { @@ -305,15 +416,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 +434,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; } @@ -654,9 +761,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; } @@ -1913,14 +2017,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) 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..7db7e05ccb89 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -729,6 +729,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; From 5c743cf573e6974befe917ed4a36d42b39ef1ce0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 Dec 2013 14:37:57 +0900 Subject: [PATCH 44/49] perf ui/tui: Protect windows by ui__lock Sometimes perf top TUI breaks display with concurrent help/input window and pr_* messages since they're not protected by ui__lock. You can check it by pressing (and not releasing) 'h' key on a "perf top -vvv" TUI session. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1388036284-32342-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/tui/util.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c index 092902e30cee..bf890f72fe80 100644 --- a/tools/perf/ui/tui/util.c +++ b/tools/perf/ui/tui/util.c @@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input, t = sep + 1; } + pthread_mutex_lock(&ui__lock); + max_len += 2; nr_lines += 8; y = SLtt_Screen_Rows / 2 - nr_lines / 2; @@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input, SLsmg_write_nstring((char *)exit_msg, max_len); SLsmg_refresh(); + pthread_mutex_unlock(&ui__lock); + x += 2; len = 0; key = ui__getch(delay_secs); while (key != K_TIMER && key != K_ENTER && key != K_ESC) { + pthread_mutex_lock(&ui__lock); + if (key == K_BKSPC) { - if (len == 0) + if (len == 0) { + pthread_mutex_unlock(&ui__lock); goto next_key; + } SLsmg_gotorc(y, x + --len); SLsmg_write_char(' '); } else { @@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input, } SLsmg_refresh(); + pthread_mutex_unlock(&ui__lock); + /* XXX more graceful overflow handling needed */ if (len == sizeof(buf) - 1) { ui_helpline__push("maximum size of symbol name reached!"); @@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text, t = sep + 1; } + pthread_mutex_lock(&ui__lock); + max_len += 2; nr_lines += 4; y = SLtt_Screen_Rows / 2 - nr_lines / 2, @@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text, SLsmg_gotorc(y + nr_lines - 1, x); SLsmg_write_nstring((char *)exit_msg, max_len); SLsmg_refresh(); + + pthread_mutex_unlock(&ui__lock); + return ui__getch(delay_secs); } @@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args) if (vasprintf(&s, format, args) > 0) { int key; - pthread_mutex_lock(&ui__lock); key = ui__question_window(title, s, "Press any key...", 0); - pthread_mutex_unlock(&ui__lock); free(s); return key; } From e8e684a58b9bddde3fdb1a65cd26eb7a3e1e746e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 Dec 2013 14:37:58 +0900 Subject: [PATCH 45/49] perf ui/tui: Split help message for perf top and report Some hotkeys don't work for perf top so split help messages for them. It'll be helpful to a future modification. Also sort the message by alphabetical order of the hotkey. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1388036284-32342-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 49 +++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a440e03cd8c2..d43ec79ea4e3 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1400,6 +1400,35 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, char script_opt[64]; int delay_secs = hbt ? hbt->refresh : 0; +#define HIST_BROWSER_HELP_COMMON \ + "h/?/F1 Show this window\n" \ + "UP/DOWN/PGUP\n" \ + "PGDN/SPACE Navigate\n" \ + "q/ESC/CTRL+C Exit browser\n\n" \ + "For multiple event sessions:\n\n" \ + "TAB/UNTAB Switch events\n\n" \ + "For symbolic views (--sort has sym):\n\n" \ + "-> Zoom into DSO/Threads & Annotate current symbol\n" \ + "<- Zoom out\n" \ + "a Annotate current symbol\n" \ + "C Collapse all callchains\n" \ + "d Zoom into current DSO\n" \ + "E Expand all callchains\n" \ + + /* help messages are sorted by lexical order of the hotkey */ + const char report_help[] = HIST_BROWSER_HELP_COMMON + "P Print histograms to perf.hist.N\n" + "r Run available scripts\n" + "s Switch to another data file in PWD\n" + "t Zoom into current Thread\n" + "V Verbose (DSO names in callchains, etc)\n" + "/ Filter symbol by name"; + const char top_help[] = HIST_BROWSER_HELP_COMMON + "P Print histograms to perf.hist.N\n" + "t Zoom into current Thread\n" + "V Verbose (DSO names in callchains, etc)\n" + "/ Filter symbol by name"; + if (browser == NULL) return -1; @@ -1488,25 +1517,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, case 'h': case '?': ui_browser__help_window(&browser->b, - "h/?/F1 Show this window\n" - "UP/DOWN/PGUP\n" - "PGDN/SPACE Navigate\n" - "q/ESC/CTRL+C Exit browser\n\n" - "For multiple event sessions:\n\n" - "TAB/UNTAB Switch events\n\n" - "For symbolic views (--sort has sym):\n\n" - "-> Zoom into DSO/Threads & Annotate current symbol\n" - "<- Zoom out\n" - "a Annotate current symbol\n" - "C Collapse all callchains\n" - "E Expand all callchains\n" - "d Zoom into current DSO\n" - "t Zoom into current Thread\n" - "r Run available scripts('perf report' only)\n" - "s Switch to another data file in PWD ('perf report' only)\n" - "P Print histograms to perf.hist.N\n" - "V Verbose (DSO names in callchains, etc)\n" - "/ Filter symbol by name"); + is_report_browser(hbt) ? report_help : top_help); continue; case K_ENTER: case K_RIGHT: From 6dd601354f14b5cd7a0a4103811e52ccec22ac53 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 Dec 2013 14:37:59 +0900 Subject: [PATCH 46/49] perf ui/tui: Implement header window Implement a simple, full-screen header window which shows session header (metadata) information. Press 'i' key to display the header window. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1388036284-32342-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 1 + tools/perf/ui/browser.h | 2 + tools/perf/ui/browsers/header.c | 127 ++++++++++++++++++++++++++++++++ tools/perf/ui/browsers/hists.c | 6 ++ 4 files changed, 136 insertions(+) create mode 100644 tools/perf/ui/browsers/header.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 97a2145e4cc6..3638b0bd20dc 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -489,6 +489,7 @@ ifndef NO_SLANG LIB_OBJS += $(OUTPUT)ui/browsers/hists.o LIB_OBJS += $(OUTPUT)ui/browsers/map.o LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o + LIB_OBJS += $(OUTPUT)ui/browsers/header.o LIB_OBJS += $(OUTPUT)ui/tui/setup.o LIB_OBJS += $(OUTPUT)ui/tui/util.o LIB_OBJS += $(OUTPUT)ui/tui/helpline.o diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 7d45d2f53601..118cca29dd26 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text); bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); int ui_browser__input_window(const char *title, const char *text, char *input, const char *exit_msg, int delay_sec); +struct perf_session_env; +int tui__header_window(struct perf_session_env *env); void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); unsigned int ui_browser__argv_refresh(struct ui_browser *browser); diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c new file mode 100644 index 000000000000..89c16b988618 --- /dev/null +++ b/tools/perf/ui/browsers/header.c @@ -0,0 +1,127 @@ +#include "util/cache.h" +#include "util/debug.h" +#include "ui/browser.h" +#include "ui/ui.h" +#include "ui/util.h" +#include "ui/libslang.h" +#include "util/header.h" +#include "util/session.h" + +static void ui_browser__argv_write(struct ui_browser *browser, + void *entry, int row) +{ + char **arg = entry; + char *str = *arg; + char empty[] = " "; + bool current_entry = ui_browser__is_current_entry(browser, row); + unsigned long offset = (unsigned long)browser->priv; + + if (offset >= strlen(str)) + str = empty; + else + str = str + offset; + + ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : + HE_COLORSET_NORMAL); + + slsmg_write_nstring(str, browser->width); +} + +static int list_menu__run(struct ui_browser *menu) +{ + int key; + unsigned long offset; + const char help[] = + "h/?/F1 Show this window\n" + "UP/DOWN/PGUP\n" + "PGDN/SPACE\n" + "LEFT/RIGHT Navigate\n" + "q/ESC/CTRL+C Exit browser"; + + if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0) + return -1; + + while (1) { + key = ui_browser__run(menu, 0); + + switch (key) { + case K_RIGHT: + offset = (unsigned long)menu->priv; + offset += 10; + menu->priv = (void *)offset; + continue; + case K_LEFT: + offset = (unsigned long)menu->priv; + if (offset >= 10) + offset -= 10; + menu->priv = (void *)offset; + continue; + case K_F1: + case 'h': + case '?': + ui_browser__help_window(menu, help); + continue; + case K_ESC: + case 'q': + case CTRL('c'): + key = -1; + break; + default: + continue; + } + + break; + } + + ui_browser__hide(menu); + return key; +} + +static int ui__list_menu(int argc, char * const argv[]) +{ + struct ui_browser menu = { + .entries = (void *)argv, + .refresh = ui_browser__argv_refresh, + .seek = ui_browser__argv_seek, + .write = ui_browser__argv_write, + .nr_entries = argc, + }; + + return list_menu__run(&menu); +} + +int tui__header_window(struct perf_session_env *env) +{ + int i, argc = 0; + char **argv; + struct perf_session *session; + char *ptr, *pos; + size_t size; + FILE *fp = open_memstream(&ptr, &size); + + session = container_of(env, struct perf_session, header.env); + perf_header__fprintf_info(session, fp, true); + fclose(fp); + + for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++) + argc++; + + argv = calloc(argc + 1, sizeof(*argv)); + if (argv == NULL) + goto out; + + argv[0] = pos = ptr; + for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) { + *pos++ = '\0'; + argv[i] = pos; + } + + BUG_ON(i != argc + 1); + + ui__list_menu(argc, argv); + +out: + free(argv); + free(ptr); + return 0; +} diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index d43ec79ea4e3..0d9dd99507ee 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1417,6 +1417,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, /* help messages are sorted by lexical order of the hotkey */ const char report_help[] = HIST_BROWSER_HELP_COMMON + "i Show header information\n" "P Print histograms to perf.hist.N\n" "r Run available scripts\n" "s Switch to another data file in PWD\n" @@ -1513,6 +1514,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, if (is_report_browser(hbt)) goto do_data_switch; continue; + case 'i': + /* env->arch is NULL for live-mode (i.e. perf top) */ + if (env->arch) + tui__header_window(env); + continue; case K_F1: case 'h': case '?': From f5385650c02cd4373c4124c8a8fac3b5f9851e7f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 26 Dec 2013 15:54:57 -0300 Subject: [PATCH 47/49] perf tools: No need to test against NULL before calling free() Its perfectly fine to call free(NULL), so no need to clutter the source code with all those superfluous testing. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-uux5wpvevlerd42gqer13e7n@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 4 +- tools/perf/ui/browsers/scripts.c | 3 +- tools/perf/util/header.c | 6 +- tools/perf/util/probe-event.c | 62 +++++++------------ tools/perf/util/probe-finder.c | 12 ++-- .../util/scripting-engines/trace-event-perl.c | 3 +- .../scripting-engines/trace-event-python.c | 3 +- 7 files changed, 31 insertions(+), 62 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 5a80da6ba413..a6ec1052c291 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1158,9 +1158,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) if (kvm->timerfd >= 0) close(kvm->timerfd); - if (pollfds) - free(pollfds); - + free(pollfds); return err; } diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index d63c68ea02a8..402d2bd30b09 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c @@ -173,8 +173,7 @@ int script_browse(const char *script_opt) if (script.b.width > AVERAGE_LINE_LEN) script.b.width = AVERAGE_LINE_LEN; - if (line) - free(line); + free(line); pclose(fp); script.nr_lines = nr_entries; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 61c54213704b..10730b0af804 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -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); + free(evsel->name); + free(evsel->id); } free(events); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 72b56aef105e..095a98ec7444 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -401,9 +401,7 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, } } - if (tmp) - free(tmp); - + free(tmp); return ret; } @@ -1382,8 +1380,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; } @@ -1584,34 +1581,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); + free(field->name); free(field); field = next; } } - if (pev->args) - free(pev->args); + free(pev->args); memset(pev, 0, sizeof(*pev)); } @@ -1620,21 +1608,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; @@ -1642,8 +1623,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)); } diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 7db7e05ccb89..8c087359b7ce 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1414,10 +1414,8 @@ 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); + free(af.vls[af.nvls].point.symbol); + strlist__delete(af.vls[af.nvls].vars); } free(af.vls); *vls = NULL; @@ -1524,10 +1522,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, if (fname) { ppt->file = strdup(fname); if (ppt->file == NULL) { - if (ppt->function) { - free(ppt->function); - ppt->function = NULL; - } + free(ppt->function); + ppt->function = NULL; ret = -ENOMEM; goto end; } diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 3773c4841cab..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: diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index b258de6357ac..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: From 046625231a0397f1776eb353a4ec9ff142cd2f6b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 26 Dec 2013 17:41:15 -0300 Subject: [PATCH 48/49] perf tools: Introduce zfree For the frequent idiom of: free(ptr); ptr = NULL; Make it expect a pointer to the pointer being freed, so that it becomes clear at first sight that the variable being freed is being modified. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-pfw02ezuab37kha18wlut7ir@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/common.c | 3 +-- tools/perf/builtin-annotate.c | 3 +-- tools/perf/builtin-stat.c | 6 ++---- tools/perf/builtin-timechart.c | 3 +-- tools/perf/builtin-trace.c | 12 ++++-------- tools/perf/ui/browser.c | 6 ++---- tools/perf/ui/browsers/hists.c | 6 ++---- tools/perf/ui/gtk/util.c | 3 +-- tools/perf/util/alias.c | 6 ++---- tools/perf/util/annotate.c | 12 ++++-------- tools/perf/util/dso.c | 9 +++------ tools/perf/util/evlist.c | 9 +++------ tools/perf/util/evsel.c | 6 ++---- tools/perf/util/header.c | 3 +-- tools/perf/util/help.c | 3 +-- tools/perf/util/machine.c | 12 +++++------- tools/perf/util/probe-event.c | 6 ++---- tools/perf/util/probe-finder.c | 24 ++++++++---------------- tools/perf/util/symbol.c | 9 +++------ tools/perf/util/thread_map.c | 10 ++++------ tools/perf/util/trace-event-info.c | 6 ++---- tools/perf/util/util.h | 2 ++ 22 files changed, 56 insertions(+), 103 deletions(-) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index aacef07ebf31..42faf369211c 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -154,8 +154,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, } if (lookup_path(buf)) goto out; - free(buf); - buf = NULL; + zfree(&buf); } if (!strcmp(arch, "arm")) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 4136f9970fd5..ab65057a0317 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -180,8 +180,7 @@ static void hists__find_annotations(struct hists *hists, * symbol, free he->ms.sym->src to signal we already * processed this symbol. */ - free(notes->src); - notes->src = NULL; + zfree(¬es->src); } } } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index dab98b50c9fe..106a5e5b7842 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -185,8 +185,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) { - free(evsel->priv); - evsel->priv = NULL; + zfree(&evsel->priv); } static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) @@ -208,8 +207,7 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) { - free(evsel->prev_raw_counts); - evsel->prev_raw_counts = NULL; + zfree(&evsel->prev_raw_counts); } static void perf_evlist__free_stats(struct perf_evlist *evlist) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 20d4212fa337..652af0b66a62 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -488,8 +488,7 @@ static const char *cat_backtrace(union perf_event *event, * It seems the callchain is corrupted. * Discard all. */ - free(p); - p = NULL; + zfree(&p); goto exit; } continue; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index f64b5b0aa8b1..c5b4bc51175c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -146,8 +146,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel, static void perf_evsel__delete_priv(struct perf_evsel *evsel) { - free(evsel->priv); - evsel->priv = NULL; + zfree(&evsel->priv); perf_evsel__delete(evsel); } @@ -165,8 +164,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler) return -ENOMEM; out_delete: - free(evsel->priv); - evsel->priv = NULL; + zfree(&evsel->priv); return -ENOENT; } @@ -1278,10 +1276,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); struct thread_trace *ttrace = arg->thread->priv; - if (ttrace && fd >= 0 && fd <= ttrace->paths.max) { - free(ttrace->paths.table[fd]); - ttrace->paths.table[fd] = NULL; - } + if (ttrace && fd >= 0 && fd <= ttrace->paths.max) + zfree(&ttrace->paths.table[fd]); return printed; } diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 94223d404f43..d11541d4d7d7 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -256,8 +256,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, __ui_browser__show_title(browser, title); browser->title = title; - free(browser->helpline); - browser->helpline = NULL; + zfree(&browser->helpline); va_start(ap, helpline); err = vasprintf(&browser->helpline, helpline, ap); @@ -272,8 +271,7 @@ void ui_browser__hide(struct ui_browser *browser) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); - free(browser->helpline); - browser->helpline = NULL; + zfree(&browser->helpline); pthread_mutex_unlock(&ui__lock); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 0d9dd99507ee..022d1731b801 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1267,10 +1267,8 @@ static inline void free_popup_options(char **options, int n) { int i; - for (i = 0; i < n; ++i) { - free(options[i]); - options[i] = NULL; - } + for (i = 0; i < n; ++i) + zfree(&options[i]); } /* Check whether the browser is for 'top' or 'report' */ diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index 696c1fbe4248..52e7fc48af9f 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -23,8 +23,7 @@ int perf_gtk__deactivate_context(struct perf_gtk_context **ctx) if (!perf_gtk__is_active_context(*ctx)) return -1; - free(*ctx); - *ctx = NULL; + zfree(ctx); return 0; } 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 27ab7b59dbf4..a78721d14694 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -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; } @@ -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; } @@ -560,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; } @@ -1113,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 */ 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/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/evsel.c b/tools/perf/util/evsel.c index 6874e0485693..93b6031d5459 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -750,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) @@ -1960,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/header.c b/tools/perf/util/header.c index 10730b0af804..20f3a9c97bd8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1324,8 +1324,7 @@ read_event_desc(struct perf_header *ph, int fd) } } out: - if (buf) - free(buf); + free(buf); return events; error: if (events) diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8b1f6e891b8a..7b68978e50d2 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -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/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/probe-event.c b/tools/perf/util/probe-event.c index 095a98ec7444..4d3cd1a0278a 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -506,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; } } diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 8c087359b7ce..6d8796e38d7f 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; } @@ -1302,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; } @@ -1417,8 +1412,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, free(af.vls[af.nvls].point.symbol); strlist__delete(af.vls[af.nvls].vars); } - free(af.vls); - *vls = NULL; + zfree(vls); return ret; } @@ -1522,8 +1516,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, if (fname) { ppt->file = strdup(fname); if (ppt->file == NULL) { - free(ppt->function); - ppt->function = NULL; + zfree(&ppt->function); ret = -ENOMEM; goto end; } @@ -1577,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/symbol.c b/tools/perf/util/symbol.c index 923d00040bbf..fd9e1a4fad16 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -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/thread_map.c b/tools/perf/util/thread_map.c index 9b5f856cc280..cf44644a4058 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -9,6 +9,7 @@ #include "strlist.h" #include #include "thread_map.h" +#include "util.h" /* Skip "." and ".." directories */ static int filter(const struct dirent *dir) @@ -138,8 +139,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) free(namelist); out_free_closedir: - free(threads); - threads = NULL; + zfree(&threads); goto out_closedir; } @@ -210,8 +210,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) free(namelist); out_free_threads: - free(threads); - threads = NULL; + zfree(&threads); goto out; } @@ -262,8 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) return threads; out_free_threads: - free(threads); - threads = NULL; + zfree(&threads); goto out; } diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index c354b95a2348..9f73bf43862c 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -562,10 +562,8 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs, 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/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); From 74cf249d5cf7de84c88cca69a2f13b13d500ff94 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 27 Dec 2013 16:55:14 -0300 Subject: [PATCH 49/49] perf tools: Use zfree to help detect use after free bugs Several areas already used this technique, so do some audit to consistently use it elsewhere. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-9sbere0kkplwe45ak6rk4a1f@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 2 +- tools/perf/builtin-sched.c | 2 +- tools/perf/builtin-script.c | 6 +++--- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/annotate.c | 20 ++++++++++---------- tools/perf/util/cgroup.c | 2 +- tools/perf/util/comm.c | 2 +- tools/perf/util/evsel.c | 8 ++++---- tools/perf/util/header.c | 10 +++++----- tools/perf/util/help.c | 4 ++-- tools/perf/util/hist.c | 6 +++--- tools/perf/util/parse-events.c | 8 ++++---- tools/perf/util/pmu.c | 2 +- tools/perf/util/probe-event.c | 8 ++++---- tools/perf/util/probe-finder.c | 2 +- tools/perf/util/session.c | 22 +++++++++++----------- tools/perf/util/srcline.c | 6 +++--- tools/perf/util/strbuf.c | 2 +- tools/perf/util/strfilter.c | 2 +- tools/perf/util/string.c | 2 +- tools/perf/util/strlist.c | 3 ++- tools/perf/util/svghelper.c | 5 +++-- tools/perf/util/symbol-elf.c | 2 +- tools/perf/util/symbol-minimal.c | 3 ++- tools/perf/util/symbol.c | 2 +- tools/perf/util/thread_map.c | 10 +++++----- tools/perf/util/trace-event-info.c | 4 ++-- tools/perf/util/values.c | 14 +++++++------- 29 files changed, 83 insertions(+), 80 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 2a85cc9a2d09..e6a0844bc2f0 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -654,7 +654,7 @@ static void data__free(struct data__file *d) for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { struct diff_hpp_fmt *fmt = &d->fmt[col]; - free(fmt->header); + zfree(&fmt->header); } } diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 0f3c65518a2c..6a76a07b6789 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -469,7 +469,7 @@ static void *thread_func(void *ctx) char comm2[22]; int fd; - free(parms); + zfree(&parms); sprintf(comm2, ":%s", this_task->comm); prctl(PR_SET_NAME, comm2); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 62ef190c4320..6040000bdfa6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1102,9 +1102,9 @@ static struct script_desc *script_desc__new(const char *name) static void script_desc__delete(struct script_desc *s) { - free(s->name); - free(s->half_liner); - free(s->args); + zfree(&s->name); + zfree(&s->half_liner); + zfree(&s->args); free(s); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 022d1731b801..a7045ea6d1d5 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1327,7 +1327,7 @@ static int switch_data_file(void) abs_path[nr_options] = strdup(path); if (!abs_path[nr_options]) { - free(options[nr_options]); + zfree(&options[nr_options]); ui__warning("Can't search all data files due to memory shortage.\n"); fclose(file); break; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index c244cb524ef2..831fbb77d1ff 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -510,7 +510,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, free(line); out: - free(rem_sq_bracket); + zfree(&rem_sq_bracket); return ret; } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index a78721d14694..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, @@ -204,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 = { @@ -583,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; @@ -591,8 +591,8 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs 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 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/evsel.c b/tools/perf/util/evsel.c index 93b6031d5459..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; } @@ -766,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) @@ -780,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); } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 20f3a9c97bd8..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,8 +1232,8 @@ static void free_event_desc(struct perf_evsel *events) return; for (evsel = events; evsel->attr.size; evsel++) { - free(evsel->name); - free(evsel->id); + zfree(&evsel->name); + zfree(&evsel->id); } free(events); @@ -2105,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 7b68978e50d2..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; } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6cd4823a7a8b..4ed3e883240d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -372,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 @@ -475,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); } 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 4d3cd1a0278a..86ed8580c3cb 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -356,7 +356,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, offset = tevs[i].point.address - stext; offset += tevs[i].point.offset; tevs[i].point.offset = 0; - free(tevs[i].point.symbol); + zfree(&tevs[i].point.symbol); ret = e_snprintf(buf, 32, "0x%lx", offset); if (ret < 0) break; @@ -683,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) { @@ -1592,7 +1592,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev) field = pev->args[i].field; while (field) { next = field->next; - free(field->name); + zfree(&field->name); free(field); field = next; } @@ -2153,7 +2153,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 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); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 6d8796e38d7f..061edb162b5b 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1409,7 +1409,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, if (ret < 0) { /* Free vlist for error */ while (af.nvls--) { - free(af.vls[af.nvls].point.symbol); + zfree(&af.vls[af.nvls].point.symbol); strlist__delete(af.vls[af.nvls].vars); } zfree(vls); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d3a857be9682..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) 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 #include #include @@ -38,7 +39,7 @@ struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry) 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 #include @@ -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 fd9e1a4fad16..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); } } diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index cf44644a4058..5d3215912105 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -41,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) } for (i=0; imap[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; @@ -135,7 +135,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) out_free_namelist: for (i = 0; i < items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); out_free_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,7 +206,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out_free_namelist: for (i = 0; i < items; i++) - free(namelist[i]); + zfree(&namelist[i]); free(namelist); out_free_threads: diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 9f73bf43862c..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); } } 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)