summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 16:44:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 16:44:39 -0700
commit4d4abdcb1dee03a4f9d6d2021622ed07e14dfd17 (patch)
tree4ed4c74b70240451065165fda5fb2059f8c6b1e5 /tools/perf/util/session.c
parent0342cbcfced2ee937d7c8e1c63f3d3082da7c7dc (diff)
parent7fcfd1abd6480d3b9ef17f5759c175e036e835cf (diff)
downloadlinux-4d4abdcb1dee03a4f9d6d2021622ed07e14dfd17.tar.bz2
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (123 commits) perf: Remove the nmi parameter from the oprofile_perf backend x86, perf: Make copy_from_user_nmi() a library function perf: Remove perf_event_attr::type check x86, perf: P4 PMU - Fix typos in comments and style cleanup perf tools: Make test use the preset debugfs path perf tools: Add automated tests for events parsing perf tools: De-opt the parse_events function perf script: Fix display of IP address for non-callchain path perf tools: Fix endian conversion reading event attr from file header perf tools: Add missing 'node' alias to the hw_cache[] array perf probe: Support adding probes on offline kernel modules perf probe: Add probed module in front of function perf probe: Introduce debuginfo to encapsulate dwarf information perf-probe: Move dwarf library routines to dwarf-aux.{c, h} perf probe: Remove redundant dwarf functions perf probe: Move strtailcmp to string.c perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END tracing/kprobe: Update symbol reference when loading module tracing/kprobes: Support module init function probing kprobes: Return -ENOENT if probe point doesn't exist ...
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c132
1 files changed, 98 insertions, 34 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5a8fbdd3f76..72458d9da5b1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -12,6 +12,7 @@
#include "session.h"
#include "sort.h"
#include "util.h"
+#include "cpumap.h"
static int perf_session__open(struct perf_session *self, bool force)
{
@@ -247,9 +248,14 @@ int perf_session__resolve_callchain(struct perf_session *self,
callchain_cursor_reset(&self->callchain_cursor);
for (i = 0; i < chain->nr; i++) {
- u64 ip = chain->ips[i];
+ u64 ip;
struct addr_location al;
+ if (callchain_param.order == ORDER_CALLEE)
+ ip = chain->ips[i];
+ else
+ ip = chain->ips[chain->nr - i - 1];
+
if (ip >= PERF_CONTEXT_MAX) {
switch (ip) {
case PERF_CONTEXT_HV:
@@ -407,20 +413,26 @@ static void perf_event__read_swap(union perf_event *event)
event->read.id = bswap_64(event->read.id);
}
-static void perf_event__attr_swap(union perf_event *event)
+/* exported for swapping attributes in file header */
+void perf_event__attr_swap(struct perf_event_attr *attr)
+{
+ attr->type = bswap_32(attr->type);
+ attr->size = bswap_32(attr->size);
+ attr->config = bswap_64(attr->config);
+ attr->sample_period = bswap_64(attr->sample_period);
+ attr->sample_type = bswap_64(attr->sample_type);
+ attr->read_format = bswap_64(attr->read_format);
+ attr->wakeup_events = bswap_32(attr->wakeup_events);
+ attr->bp_type = bswap_32(attr->bp_type);
+ attr->bp_addr = bswap_64(attr->bp_addr);
+ attr->bp_len = bswap_64(attr->bp_len);
+}
+
+static void perf_event__hdr_attr_swap(union perf_event *event)
{
size_t size;
- event->attr.attr.type = bswap_32(event->attr.attr.type);
- event->attr.attr.size = bswap_32(event->attr.attr.size);
- event->attr.attr.config = bswap_64(event->attr.attr.config);
- event->attr.attr.sample_period = bswap_64(event->attr.attr.sample_period);
- event->attr.attr.sample_type = bswap_64(event->attr.attr.sample_type);
- event->attr.attr.read_format = bswap_64(event->attr.attr.read_format);
- event->attr.attr.wakeup_events = bswap_32(event->attr.attr.wakeup_events);
- event->attr.attr.bp_type = bswap_32(event->attr.attr.bp_type);
- event->attr.attr.bp_addr = bswap_64(event->attr.attr.bp_addr);
- event->attr.attr.bp_len = bswap_64(event->attr.attr.bp_len);
+ perf_event__attr_swap(&event->attr.attr);
size = event->header.size;
size -= (void *)&event->attr.id - (void *)event;
@@ -448,7 +460,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_LOST] = perf_event__all64_swap,
[PERF_RECORD_READ] = perf_event__read_swap,
[PERF_RECORD_SAMPLE] = perf_event__all64_swap,
- [PERF_RECORD_HEADER_ATTR] = perf_event__attr_swap,
+ [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
[PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
[PERF_RECORD_HEADER_BUILD_ID] = NULL,
@@ -708,9 +720,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
if (!dump_trace)
return;
- printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
+ printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
event->header.misc, sample->pid, sample->tid, sample->ip,
- sample->period);
+ sample->period, sample->addr);
if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
callchain__printf(sample);
@@ -1202,9 +1214,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
return NULL;
}
-void perf_session__print_symbols(union perf_event *event,
- struct perf_sample *sample,
- struct perf_session *session)
+void perf_session__print_ip(union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_session *session,
+ int print_sym, int print_dso)
{
struct addr_location al;
const char *symname, *dsoname;
@@ -1233,32 +1246,83 @@ void perf_session__print_symbols(union perf_event *event,
if (!node)
break;
- if (node->sym && node->sym->name)
- symname = node->sym->name;
+ printf("\t%16" PRIx64, node->ip);
+ if (print_sym) {
+ if (node->sym && node->sym->name)
+ symname = node->sym->name;
+ else
+ symname = "";
+
+ printf(" %s", symname);
+ }
+ if (print_dso) {
+ if (node->map && node->map->dso && node->map->dso->name)
+ dsoname = node->map->dso->name;
+ else
+ dsoname = "";
+
+ printf(" (%s)", dsoname);
+ }
+ printf("\n");
+
+ callchain_cursor_advance(cursor);
+ }
+
+ } else {
+ printf("%16" PRIx64, sample->ip);
+ if (print_sym) {
+ if (al.sym && al.sym->name)
+ symname = al.sym->name;
else
symname = "";
- if (node->map && node->map->dso && node->map->dso->name)
- dsoname = node->map->dso->name;
+ printf(" %s", symname);
+ }
+
+ if (print_dso) {
+ if (al.map && al.map->dso && al.map->dso->name)
+ dsoname = al.map->dso->name;
else
dsoname = "";
- printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
+ printf(" (%s)", dsoname);
+ }
+ }
+}
- callchain_cursor_advance(cursor);
+int perf_session__cpu_bitmap(struct perf_session *session,
+ const char *cpu_list, unsigned long *cpu_bitmap)
+{
+ int i;
+ struct cpu_map *map;
+
+ for (i = 0; i < PERF_TYPE_MAX; ++i) {
+ struct perf_evsel *evsel;
+
+ evsel = perf_session__find_first_evtype(session, i);
+ if (!evsel)
+ continue;
+
+ if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
+ pr_err("File does not contain CPU events. "
+ "Remove -c option to proceed.\n");
+ return -1;
}
+ }
- } else {
- if (al.sym && al.sym->name)
- symname = al.sym->name;
- else
- symname = "";
+ map = cpu_map__new(cpu_list);
- if (al.map && al.map->dso && al.map->dso->name)
- dsoname = al.map->dso->name;
- else
- dsoname = "";
+ for (i = 0; i < map->nr; i++) {
+ int cpu = map->map[i];
+
+ if (cpu >= MAX_NR_CPUS) {
+ pr_err("Requested CPU %d too large. "
+ "Consider raising MAX_NR_CPUS\n", cpu);
+ return -1;
+ }
- printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
+ set_bit(cpu, cpu_bitmap);
}
+
+ return 0;
}