aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-08-07 09:20:45 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-08-10 15:47:02 -0400
commit0f6a30150ca2e0cf4f893e7173d61434a3c02e0e (patch)
tree0e20eb1977e7c811a75e5d19d32b67fb7eb7f8f1
parent6a40cd90f5deb6dec322eeb54587ae55a934db2c (diff)
perf tools: Support user regs and stack in sample parsing
Adding following info to be parsed out of the event sample: - user register set - user stack dump Both are global and specific to all events within the session. This info will be used in the unwind patches coming in shortly. Adding simple output printout (report -D) for both register and stack dumps. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Original-patch-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: "Frank Ch. Eigler" <fche@redhat.com> Cc: Arun Sharma <asharma@fb.com> Cc: Benjamin Redelings <benjamin.redelings@nescent.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Robert Richter <robert.richter@amd.com> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Ulrich Drepper <drepper@gmail.com> Link: http://lkml.kernel.org/r/1344345647-11536-11-git-send-email-jolsa@redhat.com [ Use evsel->attr.sample_regs_user ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/event.h12
-rw-r--r--tools/perf/util/evsel.c28
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/session.c41
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 {
69 u64 array[]; 69 u64 array[];
70}; 70};
71 71
72struct regs_dump {
73 u64 *regs;
74};
75
76struct stack_dump {
77 u16 offset;
78 u64 size;
79 char *data;
80};
81
72struct perf_sample { 82struct perf_sample {
73 u64 ip; 83 u64 ip;
74 u32 pid, tid; 84 u32 pid, tid;
@@ -82,6 +92,8 @@ struct perf_sample {
82 void *raw_data; 92 void *raw_data;
83 struct ip_callchain *callchain; 93 struct ip_callchain *callchain;
84 struct branch_stack *branch_stack; 94 struct branch_stack *branch_stack;
95 struct regs_dump user_regs;
96 struct stack_dump user_stack;
85}; 97};
86 98
87#define BUILD_ID_SIZE 20 99#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 @@
8 */ 8 */
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <linux/bitops.h>
11#include "asm/bug.h" 12#include "asm/bug.h"
12#include "evsel.h" 13#include "evsel.h"
13#include "evlist.h" 14#include "evlist.h"
@@ -733,6 +734,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
733 struct perf_sample *data, bool swapped) 734 struct perf_sample *data, bool swapped)
734{ 735{
735 u64 type = evsel->attr.sample_type; 736 u64 type = evsel->attr.sample_type;
737 u64 regs_user = evsel->attr.sample_regs_user;
736 const u64 *array; 738 const u64 *array;
737 739
738 /* 740 /*
@@ -869,6 +871,32 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
869 sz /= sizeof(u64); 871 sz /= sizeof(u64);
870 array += sz; 872 array += sz;
871 } 873 }
874
875 if (type & PERF_SAMPLE_REGS_USER) {
876 /* First u64 tells us if we have any regs in sample. */
877 u64 avail = *array++;
878
879 if (avail) {
880 data->user_regs.regs = (u64 *)array;
881 array += hweight_long(regs_user);
882 }
883 }
884
885 if (type & PERF_SAMPLE_STACK_USER) {
886 u64 size = *array++;
887
888 data->user_stack.offset = ((char *)(array - 1)
889 - (char *) event);
890
891 if (!size) {
892 data->user_stack.size = 0;
893 } else {
894 data->user_stack.data = (char *)array;
895 array += size / sizeof(*array);
896 data->user_stack.size = *array;
897 }
898 }
899
872 return 0; 900 return 0;
873} 901}
874 902
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[] = {
1830 [0] = PERF_ATTR_SIZE_VER0, 1830 [0] = PERF_ATTR_SIZE_VER0,
1831 [1] = PERF_ATTR_SIZE_VER1, 1831 [1] = PERF_ATTR_SIZE_VER1,
1832 [2] = PERF_ATTR_SIZE_VER2, 1832 [2] = PERF_ATTR_SIZE_VER2,
1833 [3] = PERF_ATTR_SIZE_VER3,
1834 [4] = PERF_ATTR_SIZE_VER4,
1833 0, 1835 0,
1834}; 1836};
1835 1837
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 @@
15#include "util.h" 15#include "util.h"
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h" 17#include "event-parse.h"
18#include "perf_regs.h"
18 19
19static int perf_session__open(struct perf_session *self, bool force) 20static int perf_session__open(struct perf_session *self, bool force)
20{ 21{
@@ -860,6 +861,34 @@ static void branch_stack__printf(struct perf_sample *sample)
860 sample->branch_stack->entries[i].to); 861 sample->branch_stack->entries[i].to);
861} 862}
862 863
864static void regs_dump__printf(u64 mask, u64 *regs)
865{
866 unsigned rid, i = 0;
867
868 for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {
869 u64 val = regs[i++];
870
871 printf(".... %-5s 0x%" PRIx64 "\n",
872 perf_reg_name(rid), val);
873 }
874}
875
876static void regs_user__printf(struct perf_sample *sample, u64 mask)
877{
878 struct regs_dump *user_regs = &sample->user_regs;
879
880 if (user_regs->regs) {
881 printf("... user regs: mask 0x%" PRIx64 "\n", mask);
882 regs_dump__printf(mask, user_regs->regs);
883 }
884}
885
886static void stack_user__printf(struct stack_dump *dump)
887{
888 printf("... ustack: size %" PRIu64 ", offset 0x%x\n",
889 dump->size, dump->offset);
890}
891
863static void perf_session__print_tstamp(struct perf_session *session, 892static void perf_session__print_tstamp(struct perf_session *session,
864 union perf_event *event, 893 union perf_event *event,
865 struct perf_sample *sample) 894 struct perf_sample *sample)
@@ -897,7 +926,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
897 event->header.size, perf_event__name(event->header.type)); 926 event->header.size, perf_event__name(event->header.type));
898} 927}
899 928
900static void dump_sample(struct perf_session *session, union perf_event *event, 929static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
901 struct perf_sample *sample) 930 struct perf_sample *sample)
902{ 931{
903 u64 sample_type; 932 u64 sample_type;
@@ -909,13 +938,19 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
909 event->header.misc, sample->pid, sample->tid, sample->ip, 938 event->header.misc, sample->pid, sample->tid, sample->ip,
910 sample->period, sample->addr); 939 sample->period, sample->addr);
911 940
912 sample_type = perf_evlist__sample_type(session->evlist); 941 sample_type = evsel->attr.sample_type;
913 942
914 if (sample_type & PERF_SAMPLE_CALLCHAIN) 943 if (sample_type & PERF_SAMPLE_CALLCHAIN)
915 callchain__printf(sample); 944 callchain__printf(sample);
916 945
917 if (sample_type & PERF_SAMPLE_BRANCH_STACK) 946 if (sample_type & PERF_SAMPLE_BRANCH_STACK)
918 branch_stack__printf(sample); 947 branch_stack__printf(sample);
948
949 if (sample_type & PERF_SAMPLE_REGS_USER)
950 regs_user__printf(sample, evsel->attr.sample_regs_user);
951
952 if (sample_type & PERF_SAMPLE_STACK_USER)
953 stack_user__printf(&sample->user_stack);
919} 954}
920 955
921static struct machine * 956static struct machine *
@@ -973,7 +1008,7 @@ static int perf_session_deliver_event(struct perf_session *session,
973 1008
974 switch (event->header.type) { 1009 switch (event->header.type) {
975 case PERF_RECORD_SAMPLE: 1010 case PERF_RECORD_SAMPLE:
976 dump_sample(session, event, sample); 1011 dump_sample(evsel, event, sample);
977 if (evsel == NULL) { 1012 if (evsel == NULL) {
978 ++session->hists.stats.nr_unknown_id; 1013 ++session->hists.stats.nr_unknown_id;
979 return 0; 1014 return 0;