diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-07 05:36:59 (GMT) |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-07 05:36:59 (GMT) |
commit | 479d875835a49e849683743ec50c30b6a429696b (patch) | |
tree | 616b96197e489d3fbd5ef8bdde5a59a50d6dcd76 | |
parent | bab57e994d6311298b4e3915d2c75296cd81638c (diff) | |
parent | 275ef3878f698941353780440fec6926107a320b (diff) | |
download | linux-fsl-qoriq-479d875835a49e849683743ec50c30b6a429696b.tar.xz |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
- Rename libtraceevent 'private' struct member to 'priv' so that it works
in C++, from Steven Rostedt
- Remove lots of exit()/die() calls from tools so that the main perf exit
routine can take place, from David Ahern
- Fix x86 build on x86-64, from David Ahern.
- Remove some headers that prevented perf from building on Android,
from David Ahern
- {int,str,rb}list fixes from Suzuki K Poulose
- perf.data header fixes from Namhyung Kim
- Replace needless mempcpy with memcpy, to allow build on Android, from Irina Tirdea
- Allow user to indicate objdump path, needed in cross environments, from
Maciek Borzecki
- Fix hardware cache event name generation, fix from Jiri Olsa
- Add round trip test for sw, hw and cache event names, catching the
problem Jiri fixed, after Jiri's patch, the test passes successfully.
- Clean target should do clean for lib/traceevent too, fix from David Ahern
- Check the right variable for allocation failure, fix from Namhyung Kim
- Set up evsel->tp_format regardless of evsel->name being set already,
fix from Namhyung Kim
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
27 files changed, 550 insertions, 202 deletions
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 527df03..863a0bb 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -49,7 +49,7 @@ struct pevent_record { int cpu; int ref_count; int locked; /* Do not free, even if ref_count is zero */ - void *private; + void *priv; #if DEBUG_RECORD struct pevent_record *prev; struct pevent_record *next; @@ -106,7 +106,7 @@ struct plugin_option { char *plugin_alias; char *description; char *value; - void *private; + void *priv; int set; }; diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index c89f9e1..c8ffd9f 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -85,6 +85,9 @@ OPTIONS -M:: --disassembler-style=:: Set disassembler style for objdump. +--objdump=<path>:: + Path to objdump binary. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 495210a..f4d91be 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -168,6 +168,9 @@ OPTIONS branch stacks and it will automatically switch to the branch view mode, unless --no-branch-stack is used. +--objdump=<path>:: + Path to objdump binary. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-annotate[1] diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 722ddee..afd5075 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -64,12 +64,12 @@ AR = $(CROSS_COMPILE)ar # Additional ARCH settings for x86 ifeq ($(ARCH),i386) - ARCH := x86 + override ARCH := x86 NO_PERF_REGS := 0 LIBUNWIND_LIBS = -lunwind -lunwind-x86 endif ifeq ($(ARCH),x86_64) - ARCH := x86 + override ARCH := x86 IS_X86_64 := 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) @@ -917,6 +917,9 @@ $(LIB_FILE): $(LIB_OBJS) $(LIBTRACEEVENT): $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a +$(LIBTRACEEVENT)-clean: + $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean + help: @echo 'Perf make targets:' @echo ' doc - make *all* documentation (see below)' @@ -1056,7 +1059,7 @@ quick-install-html: ### Cleaning rules -clean: +clean: $(LIBTRACEEVENT)-clean $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(RM) $(ALL_PROGRAMS) perf $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 67522cf..2f3f002 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -282,6 +282,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), + OPT_STRING(0, "objdump", &objdump_path, "path", + "objdump binary to use for disassembly and annotations"), OPT_END() }; diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 6d5a8a7..f9daae5 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -24,13 +24,14 @@ static struct man_viewer_info_list { } *man_viewer_info_list; enum help_format { + HELP_FORMAT_NONE, HELP_FORMAT_MAN, HELP_FORMAT_INFO, HELP_FORMAT_WEB, }; static bool show_all = false; -static enum help_format help_format = HELP_FORMAT_MAN; +static enum help_format help_format = HELP_FORMAT_NONE; static struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), @@ -54,7 +55,9 @@ static enum help_format parse_help_format(const char *format) return HELP_FORMAT_INFO; if (!strcmp(format, "web") || !strcmp(format, "html")) return HELP_FORMAT_WEB; - die("unrecognized help format '%s'", format); + + pr_err("unrecognized help format '%s'", format); + return HELP_FORMAT_NONE; } static const char *get_man_viewer_info(const char *name) @@ -259,6 +262,8 @@ static int perf_help_config(const char *var, const char *value, void *cb) if (!value) return config_error_nonbool(var); help_format = parse_help_format(value); + if (help_format == HELP_FORMAT_NONE) + return -1; return 0; } if (!strcmp(var, "man.viewer")) { @@ -352,7 +357,7 @@ static void exec_viewer(const char *name, const char *page) warning("'%s': unknown man viewer.", name); } -static void show_man_page(const char *perf_cmd) +static int show_man_page(const char *perf_cmd) { struct man_viewer_list *viewer; const char *page = cmd_to_page(perf_cmd); @@ -365,28 +370,35 @@ static void show_man_page(const char *perf_cmd) if (fallback) exec_viewer(fallback, page); exec_viewer("man", page); - die("no man viewer handled the request"); + + pr_err("no man viewer handled the request"); + return -1; } -static void show_info_page(const char *perf_cmd) +static int show_info_page(const char *perf_cmd) { const char *page = cmd_to_page(perf_cmd); setenv("INFOPATH", system_path(PERF_INFO_PATH), 1); execlp("info", "info", "perfman", page, NULL); + return -1; } -static void get_html_page_path(struct strbuf *page_path, const char *page) +static int get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; const char *html_path = system_path(PERF_HTML_PATH); /* Check that we have a perf documentation directory. */ if (stat(mkpath("%s/perf.html", html_path), &st) - || !S_ISREG(st.st_mode)) - die("'%s': not a documentation directory.", html_path); + || !S_ISREG(st.st_mode)) { + pr_err("'%s': not a documentation directory.", html_path); + return -1; + } strbuf_init(page_path, 0); strbuf_addf(page_path, "%s/%s.html", html_path, page); + + return 0; } /* @@ -401,19 +413,23 @@ static void open_html(const char *path) } #endif -static void show_html_page(const char *perf_cmd) +static int show_html_page(const char *perf_cmd) { const char *page = cmd_to_page(perf_cmd); struct strbuf page_path; /* it leaks but we exec bellow */ - get_html_page_path(&page_path, page); + if (get_html_page_path(&page_path, page) != 0) + return -1; open_html(page_path.buf); + + return 0; } int cmd_help(int argc, const char **argv, const char *prefix __used) { const char *alias; + int rc = 0; load_command_list("perf-", &main_cmds, &other_cmds); @@ -444,16 +460,20 @@ int cmd_help(int argc, const char **argv, const char *prefix __used) switch (help_format) { case HELP_FORMAT_MAN: - show_man_page(argv[0]); + rc = show_man_page(argv[0]); break; case HELP_FORMAT_INFO: - show_info_page(argv[0]); + rc = show_info_page(argv[0]); break; case HELP_FORMAT_WEB: - show_html_page(argv[0]); + rc = show_html_page(argv[0]); + break; + case HELP_FORMAT_NONE: + /* fall-through */ default: + rc = -1; break; } - return 0; + return rc; } diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 585aae2..75153c8 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -161,8 +161,10 @@ static struct thread_stat *thread_stat_findnew_after_first(u32 tid) return st; st = zalloc(sizeof(struct thread_stat)); - if (!st) - die("memory allocation failed\n"); + if (!st) { + pr_err("memory allocation failed\n"); + return NULL; + } st->tid = tid; INIT_LIST_HEAD(&st->seq_list); @@ -181,8 +183,10 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid) struct thread_stat *st; st = zalloc(sizeof(struct thread_stat)); - if (!st) - die("memory allocation failed\n"); + if (!st) { + pr_err("memory allocation failed\n"); + return NULL; + } st->tid = tid; INIT_LIST_HEAD(&st->seq_list); @@ -248,18 +252,20 @@ struct lock_key keys[] = { { NULL, NULL } }; -static void select_key(void) +static int select_key(void) { int i; for (i = 0; keys[i].name; i++) { if (!strcmp(keys[i].name, sort_key)) { compare = keys[i].key; - return; + return 0; } } - die("Unknown compare key:%s\n", sort_key); + pr_err("Unknown compare key: %s\n", sort_key); + + return -1; } static void insert_to_result(struct lock_stat *st, @@ -324,7 +330,8 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) return new; alloc_failed: - die("memory allocation failed\n"); + pr_err("memory allocation failed\n"); + return NULL; } static const char *input_name; @@ -356,16 +363,16 @@ struct trace_release_event { }; struct trace_lock_handler { - void (*acquire_event)(struct trace_acquire_event *, + int (*acquire_event)(struct trace_acquire_event *, const struct perf_sample *sample); - void (*acquired_event)(struct trace_acquired_event *, + int (*acquired_event)(struct trace_acquired_event *, const struct perf_sample *sample); - void (*contended_event)(struct trace_contended_event *, + int (*contended_event)(struct trace_contended_event *, const struct perf_sample *sample); - void (*release_event)(struct trace_release_event *, + int (*release_event)(struct trace_release_event *, const struct perf_sample *sample); }; @@ -379,8 +386,10 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) } seq = zalloc(sizeof(struct lock_seq_stat)); - if (!seq) - die("Not enough memory\n"); + if (!seq) { + pr_err("memory allocation failed\n"); + return NULL; + } seq->state = SEQ_STATE_UNINITIALIZED; seq->addr = addr; @@ -403,7 +412,7 @@ enum acquire_flags { READ_LOCK = 2, }; -static void +static int report_lock_acquire_event(struct trace_acquire_event *acquire_event, const struct perf_sample *sample) { @@ -412,11 +421,18 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, struct lock_seq_stat *seq; ls = lock_stat_findnew(acquire_event->addr, acquire_event->name); + if (!ls) + return -1; if (ls->discard) - return; + return 0; ts = thread_stat_findnew(sample->tid); + if (!ts) + return -1; + seq = get_seq(ts, acquire_event->addr); + if (!seq) + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -461,10 +477,10 @@ broken: ls->nr_acquire++; seq->prev_event_time = sample->time; end: - return; + return 0; } -static void +static int report_lock_acquired_event(struct trace_acquired_event *acquired_event, const struct perf_sample *sample) { @@ -475,16 +491,23 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, u64 contended_term; ls = lock_stat_findnew(acquired_event->addr, acquired_event->name); + if (!ls) + return -1; if (ls->discard) - return; + return 0; ts = thread_stat_findnew(sample->tid); + if (!ts) + return -1; + seq = get_seq(ts, acquired_event->addr); + if (!seq) + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: /* orphan event, do nothing */ - return; + return 0; case SEQ_STATE_ACQUIRING: break; case SEQ_STATE_CONTENDED: @@ -515,10 +538,10 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, ls->nr_acquired++; seq->prev_event_time = timestamp; end: - return; + return 0; } -static void +static int report_lock_contended_event(struct trace_contended_event *contended_event, const struct perf_sample *sample) { @@ -527,16 +550,23 @@ report_lock_contended_event(struct trace_contended_event *contended_event, struct lock_seq_stat *seq; ls = lock_stat_findnew(contended_event->addr, contended_event->name); + if (!ls) + return -1; if (ls->discard) - return; + return 0; ts = thread_stat_findnew(sample->tid); + if (!ts) + return -1; + seq = get_seq(ts, contended_event->addr); + if (!seq) + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: /* orphan event, do nothing */ - return; + return 0; case SEQ_STATE_ACQUIRING: break; case SEQ_STATE_RELEASED: @@ -559,10 +589,10 @@ report_lock_contended_event(struct trace_contended_event *contended_event, ls->nr_contended++; seq->prev_event_time = sample->time; end: - return; + return 0; } -static void +static int report_lock_release_event(struct trace_release_event *release_event, const struct perf_sample *sample) { @@ -571,11 +601,18 @@ report_lock_release_event(struct trace_release_event *release_event, struct lock_seq_stat *seq; ls = lock_stat_findnew(release_event->addr, release_event->name); + if (!ls) + return -1; if (ls->discard) - return; + return 0; ts = thread_stat_findnew(sample->tid); + if (!ts) + return -1; + seq = get_seq(ts, release_event->addr); + if (!seq) + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -609,7 +646,7 @@ free_seq: list_del(&seq->list); free(seq); end: - return; + return 0; } /* lock oriented handlers */ @@ -623,13 +660,14 @@ static struct trace_lock_handler report_lock_ops = { static struct trace_lock_handler *trace_handler; -static void perf_evsel__process_lock_acquire(struct perf_evsel *evsel, +static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel, struct perf_sample *sample) { struct trace_acquire_event acquire_event; struct event_format *event = evsel->tp_format; void *data = sample->raw_data; u64 tmp; /* this is required for casting... */ + int rc = 0; tmp = raw_field_value(event, "lockdep_addr", data); memcpy(&acquire_event.addr, &tmp, sizeof(void *)); @@ -637,70 +675,84 @@ static void perf_evsel__process_lock_acquire(struct perf_evsel *evsel, acquire_event.flag = (int)raw_field_value(event, "flag", data); if (trace_handler->acquire_event) - trace_handler->acquire_event(&acquire_event, sample); + rc = trace_handler->acquire_event(&acquire_event, sample); + + return rc; } -static void perf_evsel__process_lock_acquired(struct perf_evsel *evsel, +static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel, struct perf_sample *sample) { struct trace_acquired_event acquired_event; struct event_format *event = evsel->tp_format; void *data = sample->raw_data; u64 tmp; /* this is required for casting... */ + int rc = 0; tmp = raw_field_value(event, "lockdep_addr", data); memcpy(&acquired_event.addr, &tmp, sizeof(void *)); acquired_event.name = (char *)raw_field_ptr(event, "name", data); - if (trace_handler->acquire_event) - trace_handler->acquired_event(&acquired_event, sample); + if (trace_handler->acquired_event) + rc = trace_handler->acquired_event(&acquired_event, sample); + + return rc; } -static void perf_evsel__process_lock_contended(struct perf_evsel *evsel, +static int perf_evsel__process_lock_contended(struct perf_evsel *evsel, struct perf_sample *sample) { struct trace_contended_event contended_event; struct event_format *event = evsel->tp_format; void *data = sample->raw_data; u64 tmp; /* this is required for casting... */ + int rc = 0; tmp = raw_field_value(event, "lockdep_addr", data); memcpy(&contended_event.addr, &tmp, sizeof(void *)); contended_event.name = (char *)raw_field_ptr(event, "name", data); - if (trace_handler->acquire_event) - trace_handler->contended_event(&contended_event, sample); + if (trace_handler->contended_event) + rc = trace_handler->contended_event(&contended_event, sample); + + return rc; } -static void perf_evsel__process_lock_release(struct perf_evsel *evsel, +static int perf_evsel__process_lock_release(struct perf_evsel *evsel, struct perf_sample *sample) { struct trace_release_event release_event; struct event_format *event = evsel->tp_format; void *data = sample->raw_data; u64 tmp; /* this is required for casting... */ + int rc = 0; tmp = raw_field_value(event, "lockdep_addr", data); memcpy(&release_event.addr, &tmp, sizeof(void *)); release_event.name = (char *)raw_field_ptr(event, "name", data); - if (trace_handler->acquire_event) - trace_handler->release_event(&release_event, sample); + if (trace_handler->release_event) + rc = trace_handler->release_event(&release_event, sample); + + return rc; } -static void perf_evsel__process_lock_event(struct perf_evsel *evsel, +static int perf_evsel__process_lock_event(struct perf_evsel *evsel, struct perf_sample *sample) { struct event_format *event = evsel->tp_format; + int rc = 0; if (!strcmp(event->name, "lock_acquire")) - perf_evsel__process_lock_acquire(evsel, sample); + rc = perf_evsel__process_lock_acquire(evsel, sample); if (!strcmp(event->name, "lock_acquired")) - perf_evsel__process_lock_acquired(evsel, sample); + rc = perf_evsel__process_lock_acquired(evsel, sample); if (!strcmp(event->name, "lock_contended")) - perf_evsel__process_lock_contended(evsel, sample); + rc = perf_evsel__process_lock_contended(evsel, sample); if (!strcmp(event->name, "lock_release")) - perf_evsel__process_lock_release(evsel, sample); + rc = perf_evsel__process_lock_release(evsel, sample); + + return rc; } static void print_bad_events(int bad, int total) @@ -802,14 +854,20 @@ static void dump_map(void) } } -static void dump_info(void) +static int dump_info(void) { + int rc = 0; + if (info_threads) dump_threads(); else if (info_map) dump_map(); - else - die("Unknown type of information\n"); + else { + rc = -1; + pr_err("Unknown type of information\n"); + } + + return rc; } static int process_sample_event(struct perf_tool *tool __used, @@ -826,8 +884,7 @@ static int process_sample_event(struct perf_tool *tool __used, return -1; } - perf_evsel__process_lock_event(evsel, sample); - return 0; + return perf_evsel__process_lock_event(evsel, sample); } static struct perf_tool eops = { @@ -839,8 +896,10 @@ static struct perf_tool eops = { static int read_events(void) { session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); - if (!session) - die("Initializing perf session failed\n"); + if (!session) { + pr_err("Initializing perf session failed\n"); + return -1; + } return perf_session__process_events(session, &eops); } @@ -857,13 +916,18 @@ static void sort_result(void) } } -static void __cmd_report(void) +static int __cmd_report(void) { setup_pager(); - select_key(); - read_events(); + + if ((select_key() != 0) || + (read_events() != 0)) + return -1; + sort_result(); print_result(); + + return 0; } static const char * const report_usage[] = { @@ -959,6 +1023,7 @@ static int __cmd_record(int argc, const char **argv) int cmd_lock(int argc, const char **argv, const char *prefix __used) { unsigned int i; + int rc = 0; symbol__init(); for (i = 0; i < LOCKHASH_SIZE; i++) @@ -993,11 +1058,13 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used) /* recycling report_lock_ops */ trace_handler = &report_lock_ops; setup_pager(); - read_events(); - dump_info(); + if (read_events() != 0) + rc = -1; + else + rc = dump_info(); } else { usage_with_options(lock_usage, lock_options); } - return 0; + return rc; } diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 479ff2a..7b8b891 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size) rec->bytes_written += size; } -static void write_output(struct perf_record *rec, void *buf, size_t size) +static int write_output(struct perf_record *rec, void *buf, size_t size) { while (size) { int ret = write(rec->output, buf, size); - if (ret < 0) - die("failed to write"); + if (ret < 0) { + pr_err("failed to write\n"); + return -1; + } size -= ret; buf += ret; rec->bytes_written += ret; } + + return 0; } static int process_synthesized_event(struct perf_tool *tool, @@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool, struct machine *machine __used) { struct perf_record *rec = container_of(tool, struct perf_record, tool); - write_output(rec, event, event->header.size); + if (write_output(rec, event, event->header.size) < 0) + return -1; + return 0; } -static void perf_record__mmap_read(struct perf_record *rec, +static int perf_record__mmap_read(struct perf_record *rec, struct perf_mmap *md) { unsigned int head = perf_mmap__read_head(md); @@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec, unsigned char *data = md->base + rec->page_size; unsigned long size; void *buf; + int rc = 0; if (old == head) - return; + return 0; rec->samples++; @@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec, size = md->mask + 1 - (old & md->mask); old += size; - write_output(rec, buf, size); + if (write_output(rec, buf, size) < 0) { + rc = -1; + goto out; + } } buf = &data[old & md->mask]; size = head - old; old += size; - write_output(rec, buf, size); + if (write_output(rec, buf, size) < 0) { + rc = -1; + goto out; + } md->prev = old; perf_mmap__write_tail(md, old); + +out: + return rc; } static volatile int done = 0; @@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, return true; } -static void perf_record__open(struct perf_record *rec) +static int perf_record__open(struct perf_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; + int rc = 0; perf_evlist__config_attrs(evlist, opts); @@ -222,10 +239,13 @@ try_again: if (err == EPERM || err == EACCES) { ui__error_paranoid(); - exit(EXIT_FAILURE); + rc = -err; + goto out; } else if (err == ENODEV && opts->target.cpu_list) { - die("No such device - did you specify" - " an out-of-range profile CPU?\n"); + pr_err("No such device - did you specify" + " an out-of-range profile CPU?\n"); + rc = -err; + goto out; } else if (err == EINVAL) { if (!opts->exclude_guest_missing && (attr->exclude_guest || attr->exclude_host)) { @@ -272,7 +292,8 @@ try_again: if (err == ENOENT) { ui__error("The %s event is not supported.\n", perf_evsel__name(pos)); - exit(EXIT_FAILURE); + rc = -err; + goto out; } printf("\n"); @@ -280,34 +301,46 @@ try_again: err, strerror(err)); #if defined(__i386__) || defined(__x86_64__) - if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) - die("No hardware sampling interrupt available." - " No APIC? If so then you can boot the kernel" - " with the \"lapic\" boot parameter to" - " force-enable it.\n"); + if (attr->type == PERF_TYPE_HARDWARE && + err == EOPNOTSUPP) { + pr_err("No hardware sampling interrupt available." + " No APIC? If so then you can boot the kernel" + " with the \"lapic\" boot parameter to" + " force-enable it.\n"); + rc = -err; + goto out; + } #endif - die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + rc = -err; + goto out; } } if (perf_evlist__set_filters(evlist)) { error("failed to set filter with %d (%s)\n", errno, strerror(errno)); - exit(-1); + rc = -1; + goto out; } if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { - if (errno == EPERM) - die("Permission error mapping pages.\n" - "Consider increasing " - "/proc/sys/kernel/perf_event_mlock_kb,\n" - "or try again with a smaller value of -m/--mmap_pages.\n" - "(current value: %d)\n", opts->mmap_pages); - else if (!is_power_of_2(opts->mmap_pages)) - die("--mmap_pages/-m value must be a power of two."); - - die("failed to mmap with %d (%s)\n", errno, strerror(errno)); + if (errno == EPERM) { + pr_err("Permission error mapping pages.\n" + "Consider increasing " + "/proc/sys/kernel/perf_event_mlock_kb,\n" + "or try again with a smaller value of -m/--mmap_pages.\n" + "(current value: %d)\n", opts->mmap_pages); + rc = -errno; + } else if (!is_power_of_2(opts->mmap_pages)) { + pr_err("--mmap_pages/-m value must be a power of two."); + rc = -EINVAL; + } else { + pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); + rc = -errno; + } + goto out; } if (rec->file_new) @@ -315,11 +348,14 @@ try_again: else { if (!perf_evlist__equal(session->evlist, evlist)) { fprintf(stderr, "incompatible append\n"); - exit(-1); + rc = -1; + goto out; } } perf_session__set_id_hdr_size(session); +out: + return rc; } static int process_buildids(struct perf_record *rec) @@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec) size, &build_id__mark_dso_hit_ops); } -static void perf_record__exit(int status __used, void *arg) +static void perf_record__exit(int status, void *arg) { struct perf_record *rec = arg; + if (status != 0) + return; + if (!rec->opts.pipe_output) { rec->session->header.data_size += rec->bytes_written; @@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = { .type = PERF_RECORD_FINISHED_ROUND, }; -static void perf_record__mmap_read_all(struct perf_record *rec) +static int perf_record__mmap_read_all(struct perf_record *rec) { int i; + int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { - if (rec->evlist->mmap[i].base) - perf_record__mmap_read(rec, &rec->evlist->mmap[i]); + if (rec->evlist->mmap[i].base) { + if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { + rc = -1; + goto out; + } + } } if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) - write_output(rec, &finished_round_event, sizeof(finished_round_event)); + rc = write_output(rec, &finished_round_event, + sizeof(finished_round_event)); + +out: + return rc; } static int __cmd_record(struct perf_record *rec, int argc, const char **argv) @@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) output = open(output_name, flags, S_IRUSR | S_IWUSR); if (output < 0) { perror("failed to create output file"); - exit(-1); + return -1; } rec->output = output; @@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } - perf_record__open(rec); + if (perf_record__open(rec) != 0) { + err = -1; + goto out_delete_session; + } /* * perf_session__delete(session) will be called at perf_record__exit() @@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (opts->pipe_output) { err = perf_header__write_pipe(output); if (err < 0) - return err; + goto out_delete_session; } else if (rec->file_new) { err = perf_session__write_header(session, evsel_list, output, false); if (err < 0) - return err; + goto out_delete_session; } if (!rec->no_buildid && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { pr_err("Couldn't generate buildids. " "Use --no-buildid to profile anyway.\n"); - return -1; + err = -1; + goto out_delete_session; } rec->post_processing_offset = lseek(output, 0, SEEK_CUR); @@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) machine = perf_session__find_host_machine(session); if (!machine) { pr_err("Couldn't find native kernel information.\n"); - return -1; + err = -1; + goto out_delete_session; } if (opts->pipe_output) { @@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) process_synthesized_event); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); - return err; + goto out_delete_session; } err = perf_event__synthesize_event_types(tool, process_synthesized_event, machine); if (err < 0) { pr_err("Couldn't synthesize event_types.\n"); - return err; + goto out_delete_session; } if (have_tracepoints(&evsel_list->entries)) { @@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) process_synthesized_event); if (err <= 0) { pr_err("Couldn't record tracing data.\n"); - return err; + goto out_delete_session; } advance_output(rec, err); } @@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os); if (!opts->target.system_wide) - perf_event__synthesize_thread_map(tool, evsel_list->threads, + err = perf_event__synthesize_thread_map(tool, evsel_list->threads, process_synthesized_event, machine); else - perf_event__synthesize_threads(tool, process_synthesized_event, + err = perf_event__synthesize_threads(tool, process_synthesized_event, machine); + if (err != 0) + goto out_delete_session; + if (rec->realtime_prio) { struct sched_param param; param.sched_priority = rec->realtime_prio; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { pr_err("Could not set realtime priority.\n"); - exit(-1); + err = -1; + goto out_delete_session; } } @@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) for (;;) { int hits = rec->samples; - perf_record__mmap_read_all(rec); + if (perf_record__mmap_read_all(rec) < 0) { + err = -1; + goto out_delete_session; + } if (hits == rec->samples) { if (done) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index d618253..1f8d11b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -638,6 +638,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) "Show a column with the sum of periods"), OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", "use branch records for histogram filling", parse_branch_mode), + OPT_STRING(0, "objdump", &objdump_path, "path", + "objdump binary to use for disassembly and annotations"), OPT_END() }; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 2d6e3b2..c350cfe 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1153,18 +1153,23 @@ static const struct option options[] = { OPT_END() }; -static bool have_cmd(int argc, const char **argv) +static int have_cmd(int argc, const char **argv) { char **__argv = malloc(sizeof(const char *) * argc); - if (!__argv) - die("malloc"); + if (!__argv) { + pr_err("malloc failed\n"); + return -1; + } + memcpy(__argv, argv, sizeof(const char *) * argc); argc = parse_options(argc, (const char **)__argv, record_options, NULL, PARSE_OPT_STOP_AT_NON_OPTION); free(__argv); - return argc != 0; + system_wide = (argc == 0); + + return 0; } int cmd_script(int argc, const char **argv, const char *prefix __used) @@ -1231,13 +1236,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) if (pipe(live_pipe) < 0) { perror("failed to create pipe"); - exit(-1); + return -1; } pid = fork(); if (pid < 0) { perror("failed to fork"); - exit(-1); + return -1; } if (!pid) { @@ -1249,13 +1254,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) if (is_top_script(argv[0])) { system_wide = true; } else if (!system_wide) { - system_wide = !have_cmd(argc - rep_args, - &argv[rep_args]); + if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) { + err = -1; + goto out; + } } __argv = malloc((argc + 6) * sizeof(const char *)); - if (!__argv) - die("malloc"); + if (!__argv) { + pr_err("malloc failed\n"); + err = -ENOMEM; + goto out; + } __argv[j++] = "/bin/sh"; __argv[j++] = rec_script_path; @@ -1277,8 +1287,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) close(live_pipe[1]); __argv = malloc((argc + 4) * sizeof(const char *)); - if (!__argv) - die("malloc"); + if (!__argv) { + pr_err("malloc failed\n"); + err = -ENOMEM; + goto out; + } + j = 0; __argv[j++] = "/bin/sh"; __argv[j++] = rep_script_path; @@ -1303,12 +1317,20 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) if (!rec_script_path) system_wide = false; - else if (!system_wide) - system_wide = !have_cmd(argc - 1, &argv[1]); + else if (!system_wide) { + if (have_cmd(argc - 1, &argv[1]) != 0) { + err = -1; + goto out; + } + } __argv = malloc((argc + 2) * sizeof(const char *)); - if (!__argv) - die("malloc"); + if (!__argv) { + pr_err("malloc failed\n"); + err = -ENOMEM; + goto out; + } + __argv[j++] = "/bin/sh"; __argv[j++] = script_path; if (system_wide) @@ -1357,18 +1379,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) input = open(session->filename, O_RDONLY); /* input_name */ if (input < 0) { perror("failed to open file"); - exit(-1); + return -1; } err = fstat(input, &perf_stat); if (err < 0) { perror("failed to stat file"); - exit(-1); + return -1; } if (!perf_stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); - exit(0); + return 0; } scripting_ops = script_spec__lookup(generate_script_lang); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d53d8ab..02f49eb 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -428,7 +428,7 @@ static int run_perf_stat(int argc __used, const char **argv) if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { perror("failed to create pipes"); - exit(1); + return -1; } if (forks) { @@ -510,7 +510,8 @@ static int run_perf_stat(int argc __used, const char **argv) } if (child_pid != -1) kill(child_pid, SIGTERM); - die("Not all events could be opened.\n"); + + pr_err("Not all events could be opened.\n"); return -1; } counter->supported = true; @@ -1189,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) output = fopen(output_name, mode); if (!output) { perror("failed to create output file"); - exit(-1); + return -1; } clock_gettime(CLOCK_REALTIME, &tm); fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 381d5ab..cf33e50 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1092,6 +1092,116 @@ static int test__perf_pmu(void) return perf_pmu__test(); } +static int perf_evsel__roundtrip_cache_name_test(void) +{ + char name[128]; + int type, op, err = 0, ret = 0, i, idx; + struct perf_evsel *evsel; + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + + if (evlist == NULL) + return -ENOMEM; + + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!perf_evsel__is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + __perf_evsel__hw_cache_type_op_res_name(type, op, i, + name, sizeof(name)); + err = parse_events(evlist, name, 0); + if (err) + ret = err; + } + } + } + + idx = 0; + evsel = perf_evlist__first(evlist); + + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!perf_evsel__is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + __perf_evsel__hw_cache_type_op_res_name(type, op, i, + name, sizeof(name)); + if (evsel->idx != idx) + continue; + + ++idx; + + if (strcmp(perf_evsel__name(evsel), name)) { + pr_debug("%s != %s\n", perf_evsel__name(evsel), name); + ret = -1; + } + + evsel = perf_evsel__next(evsel); + } + } + } + + perf_evlist__delete(evlist); + return ret; +} + +static int __perf_evsel__name_array_test(const char *names[], int nr_names) +{ + int i, err; + struct perf_evsel *evsel; + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + + if (evlist == NULL) + return -ENOMEM; + + for (i = 0; i < nr_names; ++i) { + err = parse_events(evlist, names[i], 0); + if (err) { + pr_debug("failed to parse event '%s', err %d\n", + names[i], err); + goto out_delete_evlist; + } + } + + err = 0; + list_for_each_entry(evsel, &evlist->entries, node) { + if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { + --err; + pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); + } + } + +out_delete_evlist: + perf_evlist__delete(evlist); + return err; +} + +#define perf_evsel__name_array_test(names) \ + __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) + +static int perf_evsel__roundtrip_name_test(void) +{ + int err = 0, ret = 0; + + err = perf_evsel__name_array_test(perf_evsel__hw_names); + if (err) + ret = err; + + err = perf_evsel__name_array_test(perf_evsel__sw_names); + if (err) + ret = err; + + err = perf_evsel__roundtrip_cache_name_test(); + if (err) + ret = err; + + return ret; +} + static struct test { const char *desc; int (*func)(void); @@ -1135,6 +1245,10 @@ static struct test { .func = dso__test_data, }, { + .desc = "roundtrip evsel->name check", + .func = perf_evsel__roundtrip_name_test, + }, + { .func = NULL, }, }; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 3a282c0..51ef69c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -17,6 +17,7 @@ #include <pthread.h> const char *disassembler_style; +const char *objdump_path; static struct ins *ins__find(const char *name); static int disasm_line__parse(char *line, char **namep, char **rawp); @@ -820,9 +821,10 @@ fallback: dso, dso->long_name, sym, sym->name); snprintf(command, sizeof(command), - "objdump %s%s --start-address=0x%016" PRIx64 + "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -d %s %s -C %s|grep -v %s|expand", + objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "", map__rip_2objdump(map, sym->start), diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 78a5692..a6d6bc5 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -152,5 +152,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, #endif extern const char *disassembler_style; +extern const char *objdump_path; #endif /* __PERF_ANNOTATE_H */ diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 3a0f1a5..84ff6f16 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -120,7 +120,9 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, if (!full) { event->comm.tid = pid; - process(tool, event, &synth_sample, machine); + if (process(tool, event, &synth_sample, machine) != 0) + return -1; + goto out; } @@ -151,7 +153,10 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, event->comm.tid = pid; - process(tool, event, &synth_sample, machine); + if (process(tool, event, &synth_sample, machine) != 0) { + tgid = -1; + break; + } } closedir(tasks); @@ -167,6 +172,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, { char filename[PATH_MAX]; FILE *fp; + int rc = 0; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); @@ -231,18 +237,22 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, event->mmap.pid = tgid; event->mmap.tid = pid; - process(tool, event, &synth_sample, machine); + if (process(tool, event, &synth_sample, machine) != 0) { + rc = -1; + break; + } } } fclose(fp); - return 0; + return rc; } int perf_event__synthesize_modules(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine) { + int rc = 0; struct rb_node *nd; struct map_groups *kmaps = &machine->kmaps; union perf_event *event = zalloc((sizeof(event->mmap) + @@ -284,11 +294,14 @@ int perf_event__synthesize_modules(struct perf_tool *tool, memcpy(event->mmap.filename, pos->dso->long_name, pos->dso->long_name_len + 1); - process(tool, event, &synth_sample, machine); + if (process(tool, event, &synth_sample, machine) != 0) { + rc = -1; + break; + } } free(event); - return 0; + return rc; } static int __event__synthesize_thread(union perf_event *comm_event, @@ -392,12 +405,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (*end) /* only interested in proper numerical dirents */ continue; - __event__synthesize_thread(comm_event, mmap_event, pid, 1, - process, tool, machine); + if (__event__synthesize_thread(comm_event, mmap_event, pid, 1, + process, tool, machine) != 0) { + err = -1; + goto out_closedir; + } } - closedir(proc); err = 0; +out_closedir: + closedir(proc); out_free_mmap: free(mmap_event); out_free_comm: diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4774ac1..8923537 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -889,3 +889,16 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even struct perf_evsel *evsel = perf_evlist__first(evlist); return perf_evsel__parse_sample(evsel, event, sample, swapped); } + +size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) +{ + struct perf_evsel *evsel; + size_t printed = 0; + + list_for_each_entry(evsel, &evlist->entries, node) { + printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", + perf_evsel__name(evsel)); + } + + return printed + fprintf(fp, "\n");; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 2ed2557..3f2e1e4 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -143,4 +143,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) { return list_entry(evlist->entries.prev, struct perf_evsel, node); } + +size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7ff3c8f..06f7644 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -68,7 +68,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) return evsel; } -static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { +const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { "cycles", "instructions", "cache-references", @@ -131,12 +131,12 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } -static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { +const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { "cpu-clock", "task-clock", "page-faults", "context-switches", - "CPU-migrations", + "cpu-migrations", "minor-faults", "major-faults", "alignment-faults", diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 94f6ba1..a3f562c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -97,8 +97,10 @@ extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] [PERF_EVSEL__MAX_ALIASES]; extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] [PERF_EVSEL__MAX_ALIASES]; -const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] - [PERF_EVSEL__MAX_ALIASES]; +extern const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] + [PERF_EVSEL__MAX_ALIASES]; +extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX]; +extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size); const char *perf_evsel__name(struct perf_evsel *evsel); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9696e64..d07bc13 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -610,11 +610,10 @@ static int write_event_desc(int fd, struct perf_header *h __used, struct perf_evlist *evlist) { struct perf_evsel *evsel; - u32 nre = 0, nri, sz; + u32 nre, nri, sz; int ret; - list_for_each_entry(evsel, &evlist->entries, node) - nre++; + nre = evlist->nr_entries; /* * write number of events @@ -1441,6 +1440,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp) if (ret != sizeof(pmu_num)) goto error; + if (ph->needs_swap) + pmu_num = bswap_32(pmu_num); + if (!pmu_num) { fprintf(fp, "# pmu mappings: not available\n"); return; @@ -1449,6 +1451,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp) while (pmu_num) { if (read(fd, &type, sizeof(type)) != sizeof(type)) break; + if (ph->needs_swap) + type = bswap_32(type); + name = do_read_string(fd, ph); if (!name) break; @@ -2290,33 +2295,39 @@ static int read_attr(int fd, struct perf_header *ph, return ret <= 0 ? -1 : 0; } -static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel, - struct pevent *pevent) +static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, + struct pevent *pevent) { - struct event_format *event = pevent_find_event(pevent, - evsel->attr.config); + struct event_format *event; char bf[128]; + /* already prepared */ + if (evsel->tp_format) + return 0; + + event = pevent_find_event(pevent, evsel->attr.config); if (event == NULL) return -1; - snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); - evsel->name = strdup(bf); - if (event->name == NULL) - return -1; + if (!evsel->name) { + snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); + evsel->name = strdup(bf); + if (evsel->name == NULL) + return -1; + } evsel->tp_format = event; return 0; } -static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist, - struct pevent *pevent) +static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, + struct pevent *pevent) { struct perf_evsel *pos; list_for_each_entry(pos, &evlist->entries, node) { if (pos->attr.type == PERF_TYPE_TRACEPOINT && - perf_evsel__set_tracepoint_name(pos, pevent)) + perf_evsel__prepare_tracepoint_event(pos, pevent)) return -1; } @@ -2404,7 +2415,8 @@ int perf_session__read_header(struct perf_session *session, int fd) lseek(fd, header->data_offset, SEEK_SET); - if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent)) + if (perf_evlist__prepare_tracepoint_events(session->evlist, + session->pevent)) goto out_delete_evlist; header->frozen = 1; @@ -2638,7 +2650,8 @@ int perf_event__process_tracing_data(union perf_event *event, if (size_read + padding != size) die("tracing data size mismatch"); - perf_evlist__set_tracepoint_names(session->evlist, session->pevent); + perf_evlist__prepare_tracepoint_events(session->evlist, + session->pevent); return size_read + padding; } diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c index fd530dc..77c504f 100644 --- a/tools/perf/util/intlist.c +++ b/tools/perf/util/intlist.c @@ -52,9 +52,9 @@ int intlist__add(struct intlist *ilist, int i) return rblist__add_node(&ilist->rblist, (void *)((long)i)); } -void intlist__remove(struct intlist *ilist __used, struct int_node *node) +void intlist__remove(struct intlist *ilist, struct int_node *node) { - int_node__delete(node); + rblist__remove_node(&ilist->rblist, &node->rb_node); } struct int_node *intlist__find(struct intlist *ilist, int i) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index b246303..a031ee1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -308,7 +308,7 @@ int parse_events_add_cache(struct list_head **list, int *idx, for (i = 0; (i < 2) && (op_result[i]); i++) { char *str = op_result[i]; - snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); + n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); if (cache_op == -1) { cache_op = parse_aliases(str, perf_evsel__hw_cache_op, diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d280010..94e6736 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -25,16 +25,16 @@ #include <ctype.h> #include <errno.h> -#include "../../perf.h" #include "../util.h" +#include <EXTERN.h> +#include <perl.h> + +#include "../../perf.h" #include "../thread.h" #include "../event.h" #include "../trace-event.h" #include "../evsel.h" -#include <EXTERN.h> -#include <perl.h> - void boot_Perf__Trace__Context(pTHX_ CV *cv); void boot_DynaLoader(pTHX_ CV *cv); typedef PerlInterpreter * INTERP; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f7bb7ae..9453758 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -692,7 +692,7 @@ static int perf_session_deliver_event(struct perf_session *session, struct perf_tool *tool, u64 file_offset); -static void flush_sample_queue(struct perf_session *s, +static int flush_sample_queue(struct perf_session *s, struct perf_tool *tool) { struct ordered_samples *os = &s->ordered_samples; @@ -705,7 +705,7 @@ static void flush_sample_queue(struct perf_session *s, int ret; if (!tool->ordered_samples || !limit) - return; + return 0; list_for_each_entry_safe(iter, tmp, head, list) { if (iter->timestamp > limit) @@ -715,9 +715,12 @@ static void flush_sample_queue(struct perf_session *s, s->header.needs_swap); if (ret) pr_err("Can't parse sample, err = %d\n", ret); - else - perf_session_deliver_event(s, iter->event, &sample, tool, - iter->file_offset); + else { + ret = perf_session_deliver_event(s, iter->event, &sample, tool, + iter->file_offset); + if (ret) + return ret; + } os->last_flush = iter->timestamp; list_del(&iter->list); @@ -737,6 +740,8 @@ static void flush_sample_queue(struct perf_session *s, } os->nr_samples = 0; + + return 0; } /* @@ -782,10 +787,11 @@ static int process_finished_round(struct perf_tool *tool, union perf_event *event __used, struct perf_session *session) { - flush_sample_queue(session, tool); - session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; + int ret = flush_sample_queue(session, tool); + if (!ret) + session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; - return 0; + return ret; } /* The queue is ordered by time */ @@ -1443,7 +1449,7 @@ more: err = 0; /* do the final flush for ordered samples */ session->ordered_samples.next_flush = ULLONG_MAX; - flush_sample_queue(session, tool); + err = flush_sample_queue(session, tool); out_err: perf_session__warn_about_errors(session, tool); perf_session_free_sample_buffers(session); diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index 95856ff..155d8b7 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c @@ -93,7 +93,7 @@ out: void strlist__remove(struct strlist *slist, struct str_node *snode) { - str_node__delete(snode, slist->dupstr); + rblist__remove_node(&slist->rblist, &snode->rb_node); } struct str_node *strlist__find(struct strlist *slist, const char *entry) diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 051eaa6..065528b 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c @@ -117,8 +117,8 @@ int perf_target__strerror(struct perf_target *target, int errnum, if (err != buf) { size_t len = strlen(err); - char *c = mempcpy(buf, err, min(buflen - 1, len)); - *c = '\0'; + memcpy(buf, err, min(buflen - 1, len)); + *(buf + min(buflen - 1, len)) = '\0'; } return 0; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 00a93a9..67a3713 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -69,11 +69,6 @@ #include <sys/poll.h> #include <sys/socket.h> #include <sys/ioctl.h> -#include <sys/select.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> #include <inttypes.h> #include "../../../include/linux/magic.h" #include "types.h" |