diff options
-rw-r--r-- | tools/perf/util/event.h | 12 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 28 | ||||
-rw-r--r-- | tools/perf/util/header.c | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 41 |
4 files changed, 80 insertions, 3 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index d84870b06426..0e088d046e56 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -69,6 +69,16 @@ struct sample_event { u64 array[]; }; +struct regs_dump { + u64 *regs; +}; + +struct stack_dump { + u16 offset; + u64 size; + char *data; +}; + struct perf_sample { u64 ip; u32 pid, tid; @@ -82,6 +92,8 @@ struct perf_sample { void *raw_data; struct ip_callchain *callchain; struct branch_stack *branch_stack; + struct regs_dump user_regs; + struct stack_dump user_stack; }; #define BUILD_ID_SIZE 20 diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2eaae140def2..a2da682db819 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -8,6 +8,7 @@ */ #include <byteswap.h> +#include <linux/bitops.h> #include "asm/bug.h" #include "evsel.h" #include "evlist.h" @@ -733,6 +734,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *data, bool swapped) { u64 type = evsel->attr.sample_type; + u64 regs_user = evsel->attr.sample_regs_user; const u64 *array; /* @@ -869,6 +871,32 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, sz /= sizeof(u64); array += sz; } + + if (type & PERF_SAMPLE_REGS_USER) { + /* First u64 tells us if we have any regs in sample. */ + u64 avail = *array++; + + if (avail) { + data->user_regs.regs = (u64 *)array; + array += hweight_long(regs_user); + } + } + + if (type & PERF_SAMPLE_STACK_USER) { + u64 size = *array++; + + data->user_stack.offset = ((char *)(array - 1) + - (char *) event); + + if (!size) { + data->user_stack.size = 0; + } else { + data->user_stack.data = (char *)array; + array += size / sizeof(*array); + data->user_stack.size = *array; + } + } + return 0; } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index dd5a53c2944a..7e7d34fc5572 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1830,6 +1830,8 @@ static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, [2] = PERF_ATTR_SIZE_VER2, + [3] = PERF_ATTR_SIZE_VER3, + [4] = PERF_ATTR_SIZE_VER4, 0, }; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 2437fb0b463a..c9ed7e3cf231 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -15,6 +15,7 @@ #include "util.h" #include "cpumap.h" #include "event-parse.h" +#include "perf_regs.h" static int perf_session__open(struct perf_session *self, bool force) { @@ -860,6 +861,34 @@ static void branch_stack__printf(struct perf_sample *sample) sample->branch_stack->entries[i].to); } +static void regs_dump__printf(u64 mask, u64 *regs) +{ + unsigned rid, i = 0; + + for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) { + u64 val = regs[i++]; + + printf(".... %-5s 0x%" PRIx64 "\n", + perf_reg_name(rid), val); + } +} + +static void regs_user__printf(struct perf_sample *sample, u64 mask) +{ + struct regs_dump *user_regs = &sample->user_regs; + + if (user_regs->regs) { + printf("... user regs: mask 0x%" PRIx64 "\n", mask); + regs_dump__printf(mask, user_regs->regs); + } +} + +static void stack_user__printf(struct stack_dump *dump) +{ + printf("... ustack: size %" PRIu64 ", offset 0x%x\n", + dump->size, dump->offset); +} + static void perf_session__print_tstamp(struct perf_session *session, union perf_event *event, struct perf_sample *sample) @@ -897,7 +926,7 @@ static void dump_event(struct perf_session *session, union perf_event *event, event->header.size, perf_event__name(event->header.type)); } -static void dump_sample(struct perf_session *session, union perf_event *event, +static void dump_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample) { u64 sample_type; @@ -909,13 +938,19 @@ static void dump_sample(struct perf_session *session, union perf_event *event, event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); - sample_type = perf_evlist__sample_type(session->evlist); + sample_type = evsel->attr.sample_type; if (sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(sample); if (sample_type & PERF_SAMPLE_BRANCH_STACK) branch_stack__printf(sample); + + if (sample_type & PERF_SAMPLE_REGS_USER) + regs_user__printf(sample, evsel->attr.sample_regs_user); + + if (sample_type & PERF_SAMPLE_STACK_USER) + stack_user__printf(&sample->user_stack); } static struct machine * @@ -973,7 +1008,7 @@ static int perf_session_deliver_event(struct perf_session *session, switch (event->header.type) { case PERF_RECORD_SAMPLE: - dump_sample(session, event, sample); + dump_sample(evsel, event, sample); if (evsel == NULL) { ++session->hists.stats.nr_unknown_id; return 0; |