From a6f6ae99f12e8154d5cde6e8366fc228f68d6ae5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 17 Jul 2014 11:43:09 +0300 Subject: perf tools: Fix incorrect fd error comparison Zero is a valid fd. Error comparison should check for negative fd. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1405586590-13657-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index fc006fed8877..28cf7476b68c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -216,7 +216,7 @@ static int open_dso(struct dso *dso, struct machine *machine) { int fd = __open_dso(dso, machine); - if (fd > 0) { + if (fd >= 0) { dso__list_add(dso); /* * Check if we crossed the allowed number -- cgit 1.4.1 From deaff8b659cf4d34181c087b8cdf74f1eb17b02b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:10 +0300 Subject: perf tools: Fix jump label always changing during tracing Intel PT decoding walks the object code to reconstruct the trace. A jump label change during tracing causes decoding errors. The "Enable close-on-exec flag on perf file descriptor" patch caused there to be always a jump label change. It was found that using a per-cpu context instead of a per-thread context for the probe of the close-on-exec feature, made the problem go away. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cloexec.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index c5d05ec17220..6a37be53a5d2 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c @@ -1,3 +1,4 @@ +#include #include "util.h" #include "../perf.h" #include "cloexec.h" @@ -14,9 +15,13 @@ static int perf_flag_probe(void) }; int fd; int err; + int cpu = sched_getcpu(); + + if (cpu < 0) + cpu = 0; /* check cloexec flag */ - fd = sys_perf_event_open(&attr, 0, -1, -1, + fd = sys_perf_event_open(&attr, -1, cpu, -1, PERF_FLAG_FD_CLOEXEC); err = errno; @@ -30,7 +35,7 @@ static int perf_flag_probe(void) err, strerror(err)); /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ - fd = sys_perf_event_open(&attr, 0, -1, -1, 0); + fd = sys_perf_event_open(&attr, -1, cpu, -1, 0); err = errno; if (WARN_ONCE(fd < 0, -- cgit 1.4.1 From 8066be5fe755e95ee6a858bbcf4e6b9e933e1866 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:15 +0300 Subject: perf script: Improve srcline display for BTS Change the order of the output to put the srcline last. It puts the branch 'from address' and 'to address' on the same line, which is how it would be without the source line reference. So it makes it consistent and much easier to read. E.g. old format: 4028fc main+0x2c (/bin/ls) /build/buildd/coreutils-8.20/src/ls.c:1269 => 40d8a0 set_program_name+0x0 (/bin/ls) new format: 4028fc main+0x2c (/bin/ls) => 40d8a0 set_program_name+0x0 (/bin/ls) /build/buildd/coreutils-8.20/src/ls.c:1269 Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 9e9c91f5b7fa..333b15ebe72b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -427,15 +427,22 @@ static void print_sample_bts(union perf_event *event, struct addr_location *al) { struct perf_event_attr *attr = &evsel->attr; + bool print_srcline_last = false; /* print branch_from information */ if (PRINT_FIELD(IP)) { - if (!symbol_conf.use_callchain) - printf(" "); - else + unsigned int print_opts = output[attr->type].print_ip_opts; + + if (symbol_conf.use_callchain && sample->callchain) { printf("\n"); - perf_evsel__print_ip(evsel, sample, al, - output[attr->type].print_ip_opts, + } else { + printf(" "); + if (print_opts & PRINT_IP_OPT_SRCLINE) { + print_srcline_last = true; + print_opts &= ~PRINT_IP_OPT_SRCLINE; + } + } + perf_evsel__print_ip(evsel, sample, al, print_opts, PERF_MAX_STACK_DEPTH); } @@ -447,6 +454,9 @@ static void print_sample_bts(union perf_event *event, !output[attr->type].user_set)) print_sample_addr(event, sample, al->machine, thread, attr); + if (print_srcline_last) + map__fprintf_srcline(al->map, al->addr, "\n ", stdout); + printf("\n"); } -- cgit 1.4.1 From 578bea40058b68f83658827c2b68a596b08419fc Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:16 +0300 Subject: perf script: Do not print dangling '=>' for BTS When using: perf record -e branches:u -c1 usleep 1 perf script -f ip lines are displayed like: ffffffff813b23d5 => Change so that the dangling '=>' does not appear. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 333b15ebe72b..582da97872e5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -446,13 +446,13 @@ static void print_sample_bts(union perf_event *event, PERF_MAX_STACK_DEPTH); } - printf(" => "); - /* print branch_to information */ if (PRINT_FIELD(ADDR) || ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && - !output[attr->type].user_set)) + !output[attr->type].user_set)) { + printf(" => "); print_sample_addr(event, sample, al->machine, thread, attr); + } if (print_srcline_last) map__fprintf_srcline(al->map, al->addr, "\n ", stdout); -- cgit 1.4.1 From c27697d6dee02ef2389b6701c792a075bc9873dc Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:18 +0300 Subject: perf tools: Record whether a dso has data Add 'data.status' to record whether a dso has data (i.e. an object file). This is used to avoid repeatedly creating the file name and attempting to open a file that is not present. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-10-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 23 +++++++++++++++-------- tools/perf/util/dso.h | 7 +++++++ 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 28cf7476b68c..8827db3d2cba 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -331,26 +331,32 @@ int dso__data_fd(struct dso *dso, struct machine *machine) }; int i = 0; + if (dso->data.status == DSO_DATA_STATUS_ERROR) + return -1; + if (dso->data.fd >= 0) - return dso->data.fd; + goto out; if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) { dso->data.fd = open_dso(dso, machine); - return dso->data.fd; + goto out; } do { - int fd; - dso->binary_type = binary_type_data[i++]; - fd = open_dso(dso, machine); - if (fd >= 0) - return dso->data.fd = fd; + dso->data.fd = open_dso(dso, machine); + if (dso->data.fd >= 0) + goto out; } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND); +out: + if (dso->data.fd >= 0) + dso->data.status = DSO_DATA_STATUS_OK; + else + dso->data.status = DSO_DATA_STATUS_ERROR; - return -EINVAL; + return dso->data.fd; } static void @@ -701,6 +707,7 @@ struct dso *dso__new(const char *name) dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; dso->data.cache = RB_ROOT; dso->data.fd = -1; + dso->data.status = DSO_DATA_STATUS_UNKNOWN; dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; dso->is_64_bit = (sizeof(void *) == 8); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index c239e86541a3..aeb7bcbf0239 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -40,6 +40,12 @@ enum dso_swap_type { DSO_SWAP__YES, }; +enum dso_data_status { + DSO_DATA_STATUS_ERROR = -1, + DSO_DATA_STATUS_UNKNOWN = 0, + DSO_DATA_STATUS_OK = 1, +}; + #define DSO__SWAP(dso, type, val) \ ({ \ type ____r = val; \ @@ -104,6 +110,7 @@ struct dso { struct { struct rb_root cache; int fd; + int status; size_t file_size; struct list_head open_entry; } data; -- cgit 1.4.1 From 288be943b5024729cd6809b61b62f727960178f3 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:19 +0300 Subject: perf tools: Add dso__data_status_seen() Add a function to track whether a caller has seen the data status of a dso. This is needed to enable callers to report the error exactly once only per dso. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-11-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 12 ++++++++++++ tools/perf/util/dso.h | 6 ++++++ 2 files changed, 18 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 8827db3d2cba..84e4a0546a31 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -359,6 +359,18 @@ out: return dso->data.fd; } +bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by) +{ + u32 flag = 1 << by; + + if (dso->data.status_seen & flag) + return true; + + dso->data.status_seen |= flag; + + return false; +} + static void dso_cache__free(struct rb_root *root) { diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index aeb7bcbf0239..c805f604da1f 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -46,6 +46,10 @@ enum dso_data_status { DSO_DATA_STATUS_OK = 1, }; +enum dso_data_status_seen { + DSO_DATA_STATUS_SEEN_ITRACE, +}; + #define DSO__SWAP(dso, type, val) \ ({ \ type ____r = val; \ @@ -111,6 +115,7 @@ struct dso { struct rb_root cache; int fd; int status; + u32 status_seen; size_t file_size; struct list_head open_entry; } data; @@ -203,6 +208,7 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, ssize_t dso__data_read_addr(struct dso *dso, struct map *map, struct machine *machine, u64 addr, u8 *data, ssize_t size); +bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by); struct map *dso__new_map(const char *name); struct dso *dso__kernel_findnew(struct machine *machine, const char *name, -- cgit 1.4.1 From 1f625b0b3dd641b74ba21640a1fea19a3dd893a2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:23 +0300 Subject: perf tools: Add dsos__hit_all() Add ability to mark all dsos as hit. This is needed in the case of Instruction Tracing. It takes so long to decode an Instruction Trace that it is not worth doing just to determine which dsos are hit. A later patch takes this into use. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-15-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 41 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 2 ++ 2 files changed, 43 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 893f8e2df928..a588a3eb5753 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -200,6 +200,47 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id, return write_padded(fd, name, name_len + 1, len); } +static int __dsos__hit_all(struct list_head *head) +{ + struct dso *pos; + + list_for_each_entry(pos, head, node) + pos->hit = true; + + return 0; +} + +static int machine__hit_all_dsos(struct machine *machine) +{ + int err; + + err = __dsos__hit_all(&machine->kernel_dsos); + if (err) + return err; + + return __dsos__hit_all(&machine->user_dsos); +} + +int dsos__hit_all(struct perf_session *session) +{ + struct rb_node *nd; + int err; + + err = machine__hit_all_dsos(&session->machines.host); + if (err) + return err; + + for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + + err = machine__hit_all_dsos(pos); + if (err) + return err; + } + + return 0; +} + static int __dsos__write_buildid_table(struct list_head *head, struct machine *machine, pid_t pid, u16 misc, int fd) diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index d08cfe499404..8f5cbaea64a5 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -151,6 +151,8 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session); bool is_perf_magic(u64 magic); +int dsos__hit_all(struct perf_session *session); + /* * arch specific callback */ -- cgit 1.4.1 From bf49c35f630452d85c9cd7205a72df841e8d99b9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:24 +0300 Subject: perf tools: Add cpu to struct thread Tools may wish to track on which cpu a thread is running. Add 'cpu' to struct thread for that purpose. This will be used to determine the cpu when decoding a per-thread Instruction Trace. E.g: Intel PT decoding uses sched_switch events to determine which task is running on which cpu. The Intel PT data comes straight from the hardware which doesn't know about linux threads. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-16-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 1 + tools/perf/util/thread.h | 1 + 2 files changed, 2 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 9692c06a9e21..12c7a253a63c 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -34,6 +34,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) thread->pid_ = pid; thread->tid = tid; thread->ppid = -1; + thread->cpu = -1; INIT_LIST_HEAD(&thread->comm_list); comm_str = malloc(32); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 3c0c2724f82c..716b7723cce2 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -17,6 +17,7 @@ struct thread { pid_t pid_; /* Not all tools update this */ pid_t tid; pid_t ppid; + int cpu; char shortname[3]; bool comm_set; bool dead; /* if set thread has exited */ -- cgit 1.4.1 From b9d266baac0429f70df3f9cf751b045730d612e3 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:25 +0300 Subject: perf machine: Add ability to record the current tid for each cpu Add an array to struct machine to store the current tid running on each cpu. Add machine functions to get / set the tid for a cpu. This will be used to determine the tid when decoding a per-cpu Instruction Trace. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-17-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/machine.h | 5 +++++ 2 files changed, 51 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 93c8b6fbc799..cfc691000f13 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -45,6 +45,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) thread__set_comm(thread, comm, 0); } + machine->current_tid = NULL; + return 0; } @@ -104,6 +106,7 @@ void machine__exit(struct machine *machine) dsos__delete(&machine->user_dsos); dsos__delete(&machine->kernel_dsos); zfree(&machine->root_dir); + zfree(&machine->current_tid); } void machine__delete(struct machine *machine) @@ -1481,3 +1484,46 @@ int __machine__synthesize_threads(struct machine *machine, struct perf_tool *too /* command specified */ return 0; } + +pid_t machine__get_current_tid(struct machine *machine, int cpu) +{ + if (cpu < 0 || cpu >= MAX_NR_CPUS || !machine->current_tid) + return -1; + + return machine->current_tid[cpu]; +} + +int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, + pid_t tid) +{ + struct thread *thread; + + if (cpu < 0) + return -EINVAL; + + if (!machine->current_tid) { + int i; + + machine->current_tid = calloc(MAX_NR_CPUS, sizeof(pid_t)); + if (!machine->current_tid) + return -ENOMEM; + for (i = 0; i < MAX_NR_CPUS; i++) + machine->current_tid[i] = -1; + } + + if (cpu >= MAX_NR_CPUS) { + pr_err("Requested CPU %d too large. ", cpu); + pr_err("Consider raising MAX_NR_CPUS\n"); + return -EINVAL; + } + + machine->current_tid[cpu] = tid; + + thread = machine__findnew_thread(machine, pid, tid); + if (!thread) + return -ENOMEM; + + thread->cpu = cpu; + + return 0; +} diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index c8c74a119398..8771d0cbe9cb 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -33,6 +33,7 @@ struct machine { struct map_groups kmaps; struct map *vmlinux_maps[MAP__NR_TYPES]; symbol_filter_t symbol_filter; + pid_t *current_tid; }; static inline @@ -191,4 +192,8 @@ int machine__synthesize_threads(struct machine *machine, struct target *target, perf_event__process, data_mmap); } +pid_t machine__get_current_tid(struct machine *machine, int cpu); +int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, + pid_t tid); + #endif /* __PERF_MACHINE_H */ -- cgit 1.4.1 From a6a69db4b686e51045771945669bba6578af67c1 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:32 +0300 Subject: perf tools: Move rdtsc() function Move the rdtsc() function so it can be reusued. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-24-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/tsc.c | 9 +++++++++ tools/perf/tests/perf-time-to-tsc.c | 9 --------- tools/perf/util/tsc.c | 5 +++++ tools/perf/util/tsc.h | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index 3655f24c3170..fd2868490d00 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c @@ -37,3 +37,12 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, return 0; } + +u64 rdtsc(void) +{ + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((u64)high) << 32; +} diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c index 0372f6edca20..f238442b238a 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/tests/perf-time-to-tsc.c @@ -25,15 +25,6 @@ } \ } -static u64 rdtsc(void) -{ - unsigned int low, high; - - asm volatile("rdtsc" : "=a" (low), "=d" (high)); - - return low | ((u64)high) << 32; -} - /** * test__perf_time_to_tsc - test converting perf time to TSC. * diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c index ef4749836ce9..4d4210d4e13d 100644 --- a/tools/perf/util/tsc.c +++ b/tools/perf/util/tsc.c @@ -23,3 +23,8 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) return tc->time_zero + quot * tc->time_mult + ((rem * tc->time_mult) >> tc->time_shift); } + +u64 __weak rdtsc(void) +{ + return 0; +} diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h index 4eca84887c8a..a8b78f1b3243 100644 --- a/tools/perf/util/tsc.h +++ b/tools/perf/util/tsc.h @@ -7,5 +7,6 @@ u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); +u64 rdtsc(void); #endif -- cgit 1.4.1 From 6d363459d7e6e05f0afeb8e36e6de262a4964694 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:35 +0300 Subject: perf tools: Add dso__data_size() Add a function to return the dso data size, for use in estimating the size an instruction cache. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-27-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 22 ++++++++++++++++++++++ tools/perf/util/dso.h | 2 ++ 2 files changed, 24 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 84e4a0546a31..e657d86e82b9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -544,6 +544,28 @@ static int data_file_size(struct dso *dso) return 0; } +/** + * dso__data_size - Return dso data size + * @dso: dso object + * @machine: machine object + * + * Return: dso data size + */ +off_t dso__data_size(struct dso *dso, struct machine *machine) +{ + int fd; + + fd = dso__data_fd(dso, machine); + if (fd < 0) + return fd; + + if (data_file_size(dso)) + return -1; + + /* For now just estimate dso data size is close to file size */ + return dso->data.file_size; +} + static ssize_t data_read_offset(struct dso *dso, u64 offset, u8 *data, ssize_t size) { diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index c805f604da1f..af1c256aad4f 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -166,6 +166,7 @@ int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type t * The dso__data_* external interface provides following functions: * dso__data_fd * dso__data_close + * dso__data_size * dso__data_read_offset * dso__data_read_addr * @@ -203,6 +204,7 @@ int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type t int dso__data_fd(struct dso *dso, struct machine *machine); void dso__data_close(struct dso *dso); +off_t dso__data_size(struct dso *dso, struct machine *machine); ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size); ssize_t dso__data_read_addr(struct dso *dso, struct map *map, -- cgit 1.4.1 From 2a03068c5cfa104768703cbefa2e23a6353f8de5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:53 +0300 Subject: perf tools: Pass machine to vdso__dso_findnew() This is preparation for removing the global variables used in vdso.c and thereby fixing the lifetime of the VDSO temporary file. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-45-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 4 ++-- tools/perf/util/map.c | 7 ++++--- tools/perf/util/map.h | 2 +- tools/perf/util/vdso.c | 7 ++++--- tools/perf/util/vdso.h | 4 +++- 5 files changed, 14 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index cfc691000f13..a25f3ee1b5b3 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1095,7 +1095,7 @@ int machine__process_mmap2_event(struct machine *machine, else type = MAP__FUNCTION; - map = map__new(&machine->user_dsos, event->mmap2.start, + map = map__new(machine, event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, event->mmap2.pid, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, @@ -1145,7 +1145,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event else type = MAP__FUNCTION; - map = map__new(&machine->user_dsos, event->mmap.start, + map = map__new(machine, event->mmap.start, event->mmap.len, event->mmap.pgoff, event->mmap.pid, 0, 0, 0, 0, 0, 0, event->mmap.filename, diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 845f627e45f4..dffc8dce6046 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -13,6 +13,7 @@ #include "build-id.h" #include "util.h" #include "debug.h" +#include "machine.h" #include const char *map_type__name[MAP__NR_TYPES] = { @@ -137,7 +138,7 @@ void map__init(struct map *map, enum map_type type, map->erange_warned = false; } -struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, +struct map *map__new(struct machine *machine, u64 start, u64 len, u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, u64 ino_gen, u32 prot, u32 flags, char *filename, enum map_type type) @@ -173,9 +174,9 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, if (vdso) { pgoff = 0; - dso = vdso__dso_findnew(dsos__list); + dso = vdso__dso_findnew(machine); } else - dso = __dsos__findnew(dsos__list, filename); + dso = __dsos__findnew(&machine->user_dsos, filename); if (dso == NULL) goto out_delete; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 22d13a219590..a95e677f16e9 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -119,7 +119,7 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); void map__init(struct map *map, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso); -struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, +struct map *map__new(struct machine *machine, u64 start, u64 len, u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, u64 ino_gen, u32 prot, u32 flags, char *filename, enum map_type type); diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 290582452da3..da5ba4da2bd2 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -11,6 +11,7 @@ #include "vdso.h" #include "util.h" #include "symbol.h" +#include "machine.h" #include "linux/string.h" #include "debug.h" @@ -90,9 +91,9 @@ void vdso__exit(void) unlink(vdso_file); } -struct dso *vdso__dso_findnew(struct list_head *head) +struct dso *vdso__dso_findnew(struct machine *machine) { - struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true); + struct dso *dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); if (!dso) { char *file; @@ -103,7 +104,7 @@ struct dso *vdso__dso_findnew(struct list_head *head) dso = dso__new(VDSO__MAP_NAME); if (dso != NULL) { - dsos__add(head, dso); + dsos__add(&machine->user_dsos, dso); dso__set_long_name(dso, file, false); } } diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index 0f76e7caf6f8..9ab0738b6752 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h @@ -12,7 +12,9 @@ static inline bool is_vdso_map(const char *filename) return !strcmp(filename, VDSO__MAP_NAME); } -struct dso *vdso__dso_findnew(struct list_head *head); +struct machine; + +struct dso *vdso__dso_findnew(struct machine *machine); void vdso__exit(void); #endif /* __PERF_VDSO__ */ -- cgit 1.4.1 From 6f917c70998d22bda6d06cb168665068c6066cd4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 22:19:57 +0300 Subject: perf session: Add ability to 'skip' a non-piped event stream A piped event stream may contain arbitary sized tracepoint information following a PERF_RECORD_HEADER_TRACING_DATA event. The position in the stream has to be 'skipped' to match the start of the next event. Provide the same ability to a non-piped event stream to allow for Instruction Trace data that may also be in a non-piped event stream. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406143198-20732-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index eac14ce0ae8d..f4399b2087c4 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1284,6 +1284,7 @@ int __perf_session__process_events(struct perf_session *session, union perf_event *event; uint32_t size; struct ui_progress prog; + int skip; perf_tool__fill_defaults(tool); @@ -1344,7 +1345,8 @@ more: size = event->header.size; if (size < sizeof(struct perf_event_header) || - perf_session__process_event(session, event, tool, file_pos) < 0) { + (skip = perf_session__process_event(session, event, tool, file_pos)) + < 0) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", file_offset + head, event->header.size, event->header.type); @@ -1352,6 +1354,9 @@ more: goto out_err; } + if (skip) + size += skip; + head += size; file_pos += size; -- cgit 1.4.1 From d5652d865ea734a13a16cf563937291a84d4364d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 22:19:58 +0300 Subject: perf session: Add ability to skip 4GiB or more A session can be made to skip portions of the input file. Do not limit that size to 32-bits. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406143198-20732-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f4399b2087c4..d3da1055239f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -994,8 +994,10 @@ static int perf_session_deliver_event(struct perf_session *session, } } -static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, - struct perf_tool *tool, u64 file_offset) +static s64 perf_session__process_user_event(struct perf_session *session, + union perf_event *event, + struct perf_tool *tool, + u64 file_offset) { int fd = perf_data_file__fd(session->file); int err; @@ -1037,7 +1039,7 @@ static void event_swap(union perf_event *event, bool sample_id_all) swap(event, sample_id_all); } -static int perf_session__process_event(struct perf_session *session, +static s64 perf_session__process_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool, u64 file_offset) @@ -1148,7 +1150,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session, union perf_event *event; uint32_t size, cur_size = 0; void *buf = NULL; - int skip = 0; + s64 skip = 0; u64 head; ssize_t err; void *p; @@ -1277,14 +1279,13 @@ int __perf_session__process_events(struct perf_session *session, u64 file_size, struct perf_tool *tool) { int fd = perf_data_file__fd(session->file); - u64 head, page_offset, file_offset, file_pos; + u64 head, page_offset, file_offset, file_pos, size; int err, mmap_prot, mmap_flags, map_idx = 0; size_t mmap_size; char *buf, *mmaps[NUM_MMAPS]; union perf_event *event; - uint32_t size; struct ui_progress prog; - int skip; + s64 skip; perf_tool__fill_defaults(tool); -- cgit 1.4.1 From 30f4f815a45d0b148d17afb0d5a5575ae2ba4309 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:54 +0300 Subject: perf tools: Group VDSO global variables into a structure This is preparation for removing the global variables used in vdso.c and thereby fixing the lifetime of the VDSO temporary file. Also allowance is made for the later addition of support for compat VDSOs. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-46-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/vdso.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index da5ba4da2bd2..75245f081b60 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -15,8 +15,27 @@ #include "linux/string.h" #include "debug.h" -static bool vdso_found; -static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; +#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" + +struct vdso_file { + bool found; + bool error; + char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; + const char *dso_name; +}; + +struct vdso_info { + struct vdso_file vdso; +}; + +static struct vdso_info vdso_info_ = { + .vdso = { + .temp_file_name = VDSO__TEMP_FILE_NAME, + .dso_name = VDSO__MAP_NAME, + }, +}; + +static struct vdso_info *vdso_info = &vdso_info_; static int find_vdso_map(void **start, void **end) { @@ -49,7 +68,7 @@ static int find_vdso_map(void **start, void **end) return !found; } -static char *get_file(void) +static char *get_file(struct vdso_file *vdso_file) { char *vdso = NULL; char *buf = NULL; @@ -57,10 +76,10 @@ static char *get_file(void) size_t size; int fd; - if (vdso_found) - return vdso_file; + if (vdso_file->found) + return vdso_file->temp_file_name; - if (find_vdso_map(&start, &end)) + if (vdso_file->error || find_vdso_map(&start, &end)) return NULL; size = end - start; @@ -69,26 +88,27 @@ static char *get_file(void) if (!buf) return NULL; - fd = mkstemp(vdso_file); + fd = mkstemp(vdso_file->temp_file_name); if (fd < 0) goto out; if (size == (size_t) write(fd, buf, size)) - vdso = vdso_file; + vdso = vdso_file->temp_file_name; close(fd); out: free(buf); - vdso_found = (vdso != NULL); + vdso_file->found = (vdso != NULL); + vdso_file->error = !vdso_file->found; return vdso; } void vdso__exit(void) { - if (vdso_found) - unlink(vdso_file); + if (vdso_info->vdso.found) + unlink(vdso_info->vdso.temp_file_name); } struct dso *vdso__dso_findnew(struct machine *machine) @@ -98,7 +118,7 @@ struct dso *vdso__dso_findnew(struct machine *machine) if (!dso) { char *file; - file = get_file(); + file = get_file(&vdso_info->vdso); if (!file) return NULL; -- cgit 1.4.1 From d027b64001b21328cc92d35c6444e1a7a926ea76 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 14:23:00 +0300 Subject: perf machine: Fix the lifetime of the VDSO temporary file The VDSO temporary file is unlinked when a session is deleted. That precludes the possibilities that there is no session or there is more than one session. Correctly the vdso belongs to the machine so put the information on 'struct machine' and get rid of the global variables. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/53CF9B14.7040408@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 4 ++++ tools/perf/util/machine.h | 3 +++ tools/perf/util/session.c | 2 -- tools/perf/util/vdso.c | 39 +++++++++++++++++++++++++++++---------- tools/perf/util/vdso.h | 2 +- 5 files changed, 37 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a25f3ee1b5b3..65269b8ac186 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -8,6 +8,7 @@ #include "sort.h" #include "strlist.h" #include "thread.h" +#include "vdso.h" #include #include #include "unwind.h" @@ -23,6 +24,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) INIT_LIST_HEAD(&machine->dead_threads); machine->last_match = NULL; + machine->vdso_info = NULL; + machine->kmaps.machine = machine; machine->pid = pid; @@ -105,6 +108,7 @@ void machine__exit(struct machine *machine) map_groups__exit(&machine->kmaps); dsos__delete(&machine->user_dsos); dsos__delete(&machine->kernel_dsos); + vdso__exit(machine); zfree(&machine->root_dir); zfree(&machine->current_tid); } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 8771d0cbe9cb..b972824e6294 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -20,6 +20,8 @@ union perf_event; extern const char *ref_reloc_sym_names[]; +struct vdso_info; + struct machine { struct rb_node rb_node; pid_t pid; @@ -28,6 +30,7 @@ struct machine { struct rb_root threads; struct list_head dead_threads; struct thread *last_match; + struct vdso_info *vdso_info; struct list_head user_dsos; struct list_head kernel_dsos; struct map_groups kmaps; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d3da1055239f..fab5838c06be 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -14,7 +14,6 @@ #include "util.h" #include "cpumap.h" #include "perf_regs.h" -#include "vdso.h" static int perf_session__open(struct perf_session *session) { @@ -156,7 +155,6 @@ void perf_session__delete(struct perf_session *session) if (session->file) perf_data_file__close(session->file); free(session); - vdso__exit(); } static int process_event_synth_tracing_data_stub(struct perf_tool *tool diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 75245f081b60..fdaccaf67371 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -28,14 +28,17 @@ struct vdso_info { struct vdso_file vdso; }; -static struct vdso_info vdso_info_ = { - .vdso = { - .temp_file_name = VDSO__TEMP_FILE_NAME, - .dso_name = VDSO__MAP_NAME, - }, -}; - -static struct vdso_info *vdso_info = &vdso_info_; +static struct vdso_info *vdso_info__new(void) +{ + static const struct vdso_info vdso_info_init = { + .vdso = { + .temp_file_name = VDSO__TEMP_FILE_NAME, + .dso_name = VDSO__MAP_NAME, + }, + }; + + return memdup(&vdso_info_init, sizeof(vdso_info_init)); +} static int find_vdso_map(void **start, void **end) { @@ -105,16 +108,32 @@ static char *get_file(struct vdso_file *vdso_file) return vdso; } -void vdso__exit(void) +void vdso__exit(struct machine *machine) { + struct vdso_info *vdso_info = machine->vdso_info; + + if (!vdso_info) + return; + if (vdso_info->vdso.found) unlink(vdso_info->vdso.temp_file_name); + + zfree(&machine->vdso_info); } struct dso *vdso__dso_findnew(struct machine *machine) { - struct dso *dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); + struct vdso_info *vdso_info; + struct dso *dso; + + if (!machine->vdso_info) + machine->vdso_info = vdso_info__new(); + + vdso_info = machine->vdso_info; + if (!vdso_info) + return NULL; + dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); if (!dso) { char *file; diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index 9ab0738b6752..7cf1576863a4 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h @@ -15,6 +15,6 @@ static inline bool is_vdso_map(const char *filename) struct machine; struct dso *vdso__dso_findnew(struct machine *machine); -void vdso__exit(void); +void vdso__exit(struct machine *machine); #endif /* __PERF_VDSO__ */ -- cgit 1.4.1 From 4f71f2a0abe8b2a76669a4608a62f5020a64205a Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:56 +0300 Subject: perf tools: Add vdso__new() This is preparation for adding support for compat VDSOs. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-48-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/vdso.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index fdaccaf67371..946d927765c6 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -121,6 +121,20 @@ void vdso__exit(struct machine *machine) zfree(&machine->vdso_info); } +static struct dso *vdso__new(struct machine *machine, const char *short_name, + const char *long_name) +{ + struct dso *dso; + + dso = dso__new(short_name); + if (dso != NULL) { + dsos__add(&machine->user_dsos, dso); + dso__set_long_name(dso, long_name, false); + } + + return dso; +} + struct dso *vdso__dso_findnew(struct machine *machine) { struct vdso_info *vdso_info; @@ -141,11 +155,7 @@ struct dso *vdso__dso_findnew(struct machine *machine) if (!file) return NULL; - dso = dso__new(VDSO__MAP_NAME); - if (dso != NULL) { - dsos__add(&machine->user_dsos, dso); - dso__set_long_name(dso, file, false); - } + dso = vdso__new(machine, VDSO__MAP_NAME, file); } return dso; -- cgit 1.4.1 From 51682dc744c3db89e515ac47a4c1f7003fd81d20 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:57 +0300 Subject: perf tools: Separate the VDSO map name from the VDSO dso name This is in preparation for supporting 32-bit compatibility VDSOs. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-49-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 10 +++++----- tools/perf/util/symbol-elf.c | 2 +- tools/perf/util/vdso.c | 11 ++++++++--- tools/perf/util/vdso.h | 6 ++++++ 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a588a3eb5753..158c787ce0c4 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -256,9 +256,9 @@ static int __dsos__write_buildid_table(struct list_head *head, if (!pos->hit) continue; - if (is_vdso_map(pos->short_name)) { - name = (char *) VDSO__MAP_NAME; - name_len = sizeof(VDSO__MAP_NAME) + 1; + if (dso__is_vdso(pos)) { + name = pos->short_name; + name_len = pos->short_name_len + 1; } else if (dso__is_kcore(pos)) { machine__mmap_name(machine, nm, sizeof(nm)); name = nm; @@ -339,7 +339,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, len = scnprintf(filename, size, "%s%s%s", debugdir, slash ? "/" : "", - is_vdso ? VDSO__MAP_NAME : realname); + is_vdso ? DSO__NAME_VDSO : realname); if (mkdir_p(filename, 0755)) goto out_free; @@ -427,7 +427,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine, const char *debugdir) { bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; - bool is_vdso = is_vdso_map(dso->short_name); + bool is_vdso = dso__is_vdso(dso); const char *name = dso->long_name; char nm[PATH_MAX]; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index cef8f426356e..61b9cd456310 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -622,7 +622,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, GElf_Shdr shdr; ss->adjust_symbols = (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL || - is_vdso_map(dso->short_name) || + dso__is_vdso(dso) || elf_section_by_name(elf, &ehdr, &shdr, ".gnu.prelink_undo", NULL) != NULL); diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 946d927765c6..a9300f83654b 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -33,7 +33,7 @@ static struct vdso_info *vdso_info__new(void) static const struct vdso_info vdso_info_init = { .vdso = { .temp_file_name = VDSO__TEMP_FILE_NAME, - .dso_name = VDSO__MAP_NAME, + .dso_name = DSO__NAME_VDSO, }, }; @@ -147,7 +147,7 @@ struct dso *vdso__dso_findnew(struct machine *machine) if (!vdso_info) return NULL; - dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); + dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); if (!dso) { char *file; @@ -155,8 +155,13 @@ struct dso *vdso__dso_findnew(struct machine *machine) if (!file) return NULL; - dso = vdso__new(machine, VDSO__MAP_NAME, file); + dso = vdso__new(machine, DSO__NAME_VDSO, file); } return dso; } + +bool dso__is_vdso(struct dso *dso) +{ + return !strcmp(dso->short_name, DSO__NAME_VDSO); +} diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index 7cf1576863a4..be3eb4324c1e 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h @@ -7,11 +7,17 @@ #define VDSO__MAP_NAME "[vdso]" +#define DSO__NAME_VDSO "[vdso]" + static inline bool is_vdso_map(const char *filename) { return !strcmp(filename, VDSO__MAP_NAME); } +struct dso; + +bool dso__is_vdso(struct dso *dso); + struct machine; struct dso *vdso__dso_findnew(struct machine *machine); -- cgit 1.4.1 From 2b5b8bb27b9ec899cfba686dabec113ea0d4cbda Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:59 +0300 Subject: perf tools: Add dso__type() dso__type() determines wheather a dso is 32-bit, x32 (32-bit with 64-bit registers) or 64-bit. dso__type() will be used to determine the VDSO a program maps. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-51-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 11 +++++++++++ tools/perf/util/dso.h | 10 ++++++++++ tools/perf/util/symbol-elf.c | 33 +++++++++++++++++++++++++++++++++ tools/perf/util/symbol-minimal.c | 21 +++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 5 files changed, 77 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index e657d86e82b9..90d02c661dd4 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -940,3 +940,14 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) return ret; } + +enum dso_type dso__type(struct dso *dso, struct machine *machine) +{ + int fd; + + fd = dso__data_fd(dso, machine); + if (fd < 0) + return DSO__TYPE_UNKNOWN; + + return dso__type_fd(fd); +} diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index af1c256aad4f..5e463c0964d4 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "map.h" #include "build-id.h" @@ -50,6 +51,13 @@ enum dso_data_status_seen { DSO_DATA_STATUS_SEEN_ITRACE, }; +enum dso_type { + DSO__TYPE_UNKNOWN, + DSO__TYPE_64BIT, + DSO__TYPE_32BIT, + DSO__TYPE_X32BIT, +}; + #define DSO__SWAP(dso, type, val) \ ({ \ type ____r = val; \ @@ -245,4 +253,6 @@ static inline bool dso__is_kcore(struct dso *dso) void dso__free_a2l(struct dso *dso); +enum dso_type dso__type(struct dso *dso, struct machine *machine); + #endif /* __PERF_DSO */ diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 61b9cd456310..d75349979e65 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1028,6 +1028,39 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, return err; } +enum dso_type dso__type_fd(int fd) +{ + enum dso_type dso_type = DSO__TYPE_UNKNOWN; + GElf_Ehdr ehdr; + Elf_Kind ek; + Elf *elf; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + goto out; + + ek = elf_kind(elf); + if (ek != ELF_K_ELF) + goto out_end; + + if (gelf_getclass(elf) == ELFCLASS64) { + dso_type = DSO__TYPE_64BIT; + goto out_end; + } + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out_end; + + if (ehdr.e_machine == EM_X86_64) + dso_type = DSO__TYPE_X32BIT; + else + dso_type = DSO__TYPE_32BIT; +out_end: + elf_end(elf); +out: + return dso_type; +} + static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len) { ssize_t r; diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 101f55d407d0..c9541fea9514 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -305,6 +305,27 @@ static int fd__is_64_bit(int fd) return e_ident[EI_CLASS] == ELFCLASS64; } +enum dso_type dso__type_fd(int fd) +{ + Elf64_Ehdr ehdr; + int ret; + + ret = fd__is_64_bit(fd); + if (ret < 0) + return DSO__TYPE_UNKNOWN; + + if (ret) + return DSO__TYPE_64BIT; + + if (readn(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) + return DSO__TYPE_UNKNOWN; + + if (ehdr.e_machine == EM_X86_64) + return DSO__TYPE_X32BIT; + + return DSO__TYPE_32BIT; +} + int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, struct symsrc *ss, struct symsrc *runtime_ss __maybe_unused, diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index ee2d3ccd3ad1..e7295e93cff9 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -243,6 +243,8 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); struct symbol *dso__next_symbol(struct symbol *sym); +enum dso_type dso__type_fd(int fd); + int filename__read_build_id(const char *filename, void *bf, size_t size); int sysfs__read_build_id(const char *filename, void *bf, size_t size); int modules__parse(const char *filename, void *arg, -- cgit 1.4.1 From 5835eddab6f162b38e9a6a5447a2c3a128637956 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:18:00 +0300 Subject: perf tools: Add thread parameter to vdso__dso_findnew() The thread will be needed to determine the VDSO type. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-52-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 4 ++-- tools/perf/util/map.c | 4 ++-- tools/perf/util/map.h | 3 ++- tools/perf/util/vdso.c | 3 ++- tools/perf/util/vdso.h | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 65269b8ac186..16bba9fff2c8 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1106,7 +1106,7 @@ int machine__process_mmap2_event(struct machine *machine, event->mmap2.ino_generation, event->mmap2.prot, event->mmap2.flags, - event->mmap2.filename, type); + event->mmap2.filename, type, thread); if (map == NULL) goto out_problem; @@ -1153,7 +1153,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event event->mmap.len, event->mmap.pgoff, event->mmap.pid, 0, 0, 0, 0, 0, 0, event->mmap.filename, - type); + type, thread); if (map == NULL) goto out_problem; diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index dffc8dce6046..31b8905dd863 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -141,7 +141,7 @@ void map__init(struct map *map, enum map_type type, struct map *map__new(struct machine *machine, u64 start, u64 len, u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, u64 ino_gen, u32 prot, u32 flags, char *filename, - enum map_type type) + enum map_type type, struct thread *thread) { struct map *map = malloc(sizeof(*map)); @@ -174,7 +174,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len, if (vdso) { pgoff = 0; - dso = vdso__dso_findnew(machine); + dso = vdso__dso_findnew(machine, thread); } else dso = __dsos__findnew(&machine->user_dsos, filename); diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index a95e677f16e9..2f83954af050 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -104,6 +104,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip); u64 map__objdump_2mem(struct map *map, u64 ip); struct symbol; +struct thread; /* map__for_each_symbol - iterate over the symbols in the given map * @@ -122,7 +123,7 @@ void map__init(struct map *map, enum map_type type, struct map *map__new(struct machine *machine, u64 start, u64 len, u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, u64 ino_gen, u32 prot, u32 flags, - char *filename, enum map_type type); + char *filename, enum map_type type, struct thread *thread); struct map *map__new2(u64 start, struct dso *dso, enum map_type type); void map__delete(struct map *map); struct map *map__clone(struct map *map); diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index a9300f83654b..adca69384fcc 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -135,7 +135,8 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name, return dso; } -struct dso *vdso__dso_findnew(struct machine *machine) +struct dso *vdso__dso_findnew(struct machine *machine, + struct thread *thread __maybe_unused) { struct vdso_info *vdso_info; struct dso *dso; diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index be3eb4324c1e..af9d6929a215 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h @@ -19,8 +19,9 @@ struct dso; bool dso__is_vdso(struct dso *dso); struct machine; +struct thread; -struct dso *vdso__dso_findnew(struct machine *machine); +struct dso *vdso__dso_findnew(struct machine *machine, struct thread *thread); void vdso__exit(struct machine *machine); #endif /* __PERF_VDSO__ */ -- cgit 1.4.1 From 0524798cc3d74546e83ebd795e9a5ed44481eaa6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 23 Jul 2014 18:15:09 -0300 Subject: perf tools: Fix build on gcc 4.4.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [acme@sandy linux]$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3) Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [acme@sandy linux]$ make O=/tmp/build/perf -C tools/perf install-bin CC /tmp/build/perf/builtin-trace.o builtin-trace.c: In function ‘perf_evlist__add_pgfault’: builtin-trace.c:1997: error: unknown field ‘sample_period’ specified in initializer make[1]: *** [/tmp/build/perf/builtin-trace.o] Error 1 make: *** [install-bin] Error 2 make: Leaving directory `/home/acme/git/linux/tools/perf' [acme@sandy linux]$ make O=/tmp/build/perf -C tools/perf install-bin make O=/tmp/build/perf -C tools/perf install-bin make: Entering directory `/home/acme/git/linux/tools/perf' Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus 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-qt7h2g5fcf42qiw5hv7mgpjk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c4a5a7d7b2cf..a6c375224f46 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1994,10 +1994,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist, struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .mmap_data = 1, - .sample_period = 1, }; attr.config = config; + attr.sample_period = 1; event_attr_init(&attr); -- cgit 1.4.1 From c94b93cbca59435dfc0f2a838fea55bd632145d3 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Thu, 24 Jul 2014 00:47:18 -0700 Subject: perf powerpc: Include util/util.h and remove stringify macros The stringify macros are defined in tools/perf/util/util.h and don't need to be redfined specfiically for powerpc. Signed-off-by: Sukadev Bhattiprolu Cc: Andi Kleen Cc: Jiri Olsa Cc: Michael Ellerman Link: http://lkml.kernel.org/r/20140724074718.GB18829@us.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/util/header.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c index 2f7073d107fd..6c1b8a75db09 100644 --- a/tools/perf/arch/powerpc/util/header.c +++ b/tools/perf/arch/powerpc/util/header.c @@ -5,9 +5,7 @@ #include #include "../../util/header.h" - -#define __stringify_1(x) #x -#define __stringify(x) __stringify_1(x) +#include "../../util/util.h" #define mfspr(rn) ({unsigned long rval; \ asm volatile("mfspr %0," __stringify(rn) \ -- cgit 1.4.1 From f1dd1460a40894b00bbeacd753025e9251ec11bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 20 Jul 2014 23:55:45 +0200 Subject: perf session: Fix accounting of ordered samples queue Properly account flushed samples within the ordered samples queue. Signed-off-by: Jiri Olsa Acked-by: Adrian Hunter Acked-by: David Ahern Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jean Pihet Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1405893363-21967-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index fab5838c06be..88dfef70c13d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -509,6 +509,7 @@ static int flush_sample_queue(struct perf_session *s, os->last_flush = iter->timestamp; list_del(&iter->list); list_add(&iter->list, &os->sample_cache); + os->nr_samples--; if (show_progress) ui_progress__update(&prog, 1); @@ -521,8 +522,6 @@ static int flush_sample_queue(struct perf_session *s, list_entry(head->prev, struct sample_queue, list); } - os->nr_samples = 0; - return 0; } -- cgit 1.4.1 From 9b0d2d875d57d85fdfb35ac27f89951520a8b473 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:39 +0300 Subject: perf tools: Expose 'addr' functions so they can be reused Move some functions and functionality related to the use of 'addr' out of builtin-script so they can be reused. The moved functions are: is_bts_event() and sample_addr_correlates_sym() and a new function perf_event__preprocess_sample_addr() is created from bits of print_sample_addr(). perf_event__preprocess_sample_addr() is the equivalent of perf_event__preprocess_sample() but for 'addr' instead of 'ip'. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-31-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 34 +--------------------------------- tools/perf/util/event.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/event.h | 10 ++++++++++ 3 files changed, 53 insertions(+), 33 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 582da97872e5..f57035b89c15 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -358,27 +358,6 @@ static void print_sample_start(struct perf_sample *sample, } } -static bool is_bts_event(struct perf_event_attr *attr) -{ - return ((attr->type == PERF_TYPE_HARDWARE) && - (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && - (attr->sample_period == 1)); -} - -static bool sample_addr_correlates_sym(struct perf_event_attr *attr) -{ - if ((attr->type == PERF_TYPE_SOFTWARE) && - ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) || - (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) || - (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) - return true; - - if (is_bts_event(attr)) - return true; - - return false; -} - static void print_sample_addr(union perf_event *event, struct perf_sample *sample, struct machine *machine, @@ -386,24 +365,13 @@ static void print_sample_addr(union perf_event *event, struct perf_event_attr *attr) { struct addr_location al; - u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; printf("%16" PRIx64, sample->addr); if (!sample_addr_correlates_sym(attr)) return; - thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - sample->addr, &al); - if (!al.map) - thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, - sample->addr, &al); - - al.cpu = sample->cpu; - al.sym = NULL; - - if (al.map) - al.sym = map__find_symbol(al.map, al.addr, NULL); + perf_event__preprocess_sample_addr(event, sample, machine, thread, &al); if (PRINT_FIELD(SYM)) { printf(" "); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7e0e8ae568ec..1398c83d896d 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -874,3 +874,45 @@ int perf_event__preprocess_sample(const union perf_event *event, return 0; } + +bool is_bts_event(struct perf_event_attr *attr) +{ + return attr->type == PERF_TYPE_HARDWARE && + (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && + attr->sample_period == 1; +} + +bool sample_addr_correlates_sym(struct perf_event_attr *attr) +{ + if (attr->type == PERF_TYPE_SOFTWARE && + (attr->config == PERF_COUNT_SW_PAGE_FAULTS || + attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN || + attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)) + return true; + + if (is_bts_event(attr)) + return true; + + return false; +} + +void perf_event__preprocess_sample_addr(union perf_event *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread, + struct addr_location *al) +{ + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + + thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, + sample->addr, al); + if (!al->map) + thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, + sample->addr, al); + + al->cpu = sample->cpu; + al->sym = NULL; + + if (al->map) + al->sym = map__find_symbol(al->map, al->addr, NULL); +} diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index e5dd40addb30..94d6976180da 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -288,6 +288,16 @@ int perf_event__preprocess_sample(const union perf_event *event, struct addr_location *al, struct perf_sample *sample); +struct thread; + +bool is_bts_event(struct perf_event_attr *attr); +bool sample_addr_correlates_sym(struct perf_event_attr *attr); +void perf_event__preprocess_sample_addr(union perf_event *event, + struct perf_sample *sample, + struct machine *machine, + struct thread *thread, + struct addr_location *al); + const char *perf_event__name(unsigned int id); size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, -- cgit 1.4.1 From a7a2b8b4ce9e0bfd085c5797d535487594a71882 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Jul 2014 16:17:38 +0300 Subject: perf inject: Add --kallsyms parameter Let perf inject take --kallsyms parameter the same as perf script and perf report do. That is needed for decoding Instruction Trace data using a copy of /proc/kcore for the kernel object because the kallsyms path is used to locate that copy. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406035081-14301-30-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-inject.txt | 3 +++ tools/perf/builtin-inject.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt index a00a34276c54..dc7442cf3d7f 100644 --- a/tools/perf/Documentation/perf-inject.txt +++ b/tools/perf/Documentation/perf-inject.txt @@ -41,6 +41,9 @@ OPTIONS tasks slept. sched_switch contains a callchain where a task slept and sched_stat contains a timeslice how long a task slept. +--kallsyms=:: + kallsyms pathname + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index cf6a605a13e8..9a02807387d6 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -439,6 +439,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) "where and how long tasks slept"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show build ids, etc)"), + OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", + "kallsyms pathname"), OPT_END() }; const char * const inject_usage[] = { -- cgit 1.4.1 From 33bf7481971a622a2b8c8aaa0e5e61a6eaeecd71 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 25 Jul 2014 16:56:15 +0200 Subject: perf record: Always force PERF_RECORD_FINISHED_ROUND event The PERF_RECORD_FINISHED_ROUND synthetic record governs queue flushing in reporting, so it needs to be stored for any kind of event. The lack of such periodic flushing made the tools use more memory than needed, as the reordering was being done only after processing all events. This was the case when no tracepoints were in the mix. Forcing the PERF_RECORD_FINISHED_ROUND event to be stored for all event types. Signed-off-by: Jiri Olsa Acked-by: Adrian Hunter Acked-by: David Ahern Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jean Pihet Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1406300177-31805-18-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 378b85b731a7..4a1a54265b04 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -250,8 +250,7 @@ static int record__mmap_read_all(struct record *rec) } } - if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) - rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); + rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); out: return rc; -- cgit 1.4.1 From dcabb507fd3a2b19aed6b4068e2a954f5fd8de45 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 25 Jul 2014 16:56:16 +0200 Subject: perf record: Store PERF_RECORD_FINISHED_ROUND only for nonempty rounds Currently we store PERF_RECORD_FINISHED_ROUND event each time we go throught mmap buffers no matter if it contains any data, which is useless. Forcing the PERF_RECORD_FINISHED_ROUND event to be stored any time we finished the round AND wrote at least one event. Signed-off-by: Jiri Olsa Acked-by: Adrian Hunter Acked-by: David Ahern Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jean Pihet Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1406300177-31805-19-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4a1a54265b04..4869050e7194 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -238,6 +238,7 @@ static struct perf_event_header finished_round_event = { static int record__mmap_read_all(struct record *rec) { + u64 bytes_written = rec->bytes_written; int i; int rc = 0; @@ -250,7 +251,12 @@ static int record__mmap_read_all(struct record *rec) } } - rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); + /* + * Mark the round finished in case we wrote + * at least one event. + */ + if (bytes_written != rec->bytes_written) + rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); out: return rc; -- cgit 1.4.1