lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 22 Oct 2010 21:13:11 +0200
From:	Frederic Weisbecker <fweisbec@...il.com>
To:	LKML <linux-kernel@...r.kernel.org>
Cc:	LKML <linux-kernel@...r.kernel.org>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Ingo Molnar <mingo@...e.hu>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Arnaldo Carvalho de Melo <acme@...hat.com>,
	Paul Mackerras <paulus@...ba.org>,
	Stephane Eranian <eranian@...gle.com>,
	Cyrill Gorcunov <gorcunov@...nvz.org>,
	Tom Zanussi <tzanussi@...il.com>,
	Masami Hiramatsu <mhiramat@...hat.com>,
	Steven Rostedt <rostedt@...dmis.org>,
	Robert Richter <robert.richter@....com>,
	"Frank Ch. Eigler" <fche@...hat.com>
Subject: [RFC PATCH 10/11] perf: Support user regs and stack in sample parsing

This will be needed for stack unwinding.

Signed-off-by: Frederic Weisbecker <fweisbec@...il.com>
Cc: Ingo Molnar <mingo@...e.hu>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc: Arnaldo Carvalho de Melo <acme@...hat.com>
Cc: Paul Mackerras <paulus@...ba.org>
Cc: Stephane Eranian <eranian@...gle.com>
Cc: Cyrill Gorcunov <gorcunov@...nvz.org>
Cc: Tom Zanussi <tzanussi@...il.com>
Cc: Masami Hiramatsu <mhiramat@...hat.com>
Cc: Steven Rostedt <rostedt@...dmis.org>
Cc: Robert Richter <robert.richter@....com>
Cc: Frank Ch. Eigler <fche@...hat.com>
---
 tools/perf/builtin-kmem.c      |    2 +-
 tools/perf/builtin-lock.c      |    2 +-
 tools/perf/builtin-sched.c     |    2 +-
 tools/perf/builtin-timechart.c |    2 +-
 tools/perf/builtin-trace.c     |    2 +-
 tools/perf/util/event.c        |   28 ++++++++++++++++++++++++++--
 tools/perf/util/event.h        |   15 ++++++++++++++-
 tools/perf/util/header.c       |   33 +++++++++++++++++++++++++++++++--
 tools/perf/util/header.h       |    3 ++-
 tools/perf/util/session.c      |    4 ++--
 tools/perf/util/session.h      |    6 ++++++
 11 files changed, 86 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2..2fee906 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -314,7 +314,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 	data.cpu = -1;
 	data.period = 1;
 
-	event__parse_sample(event, session->sample_type, &data);
+	event__parse_sample(event, session, &data);
 
 	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
 		    data.pid, data.tid, data.ip, data.period);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 821c158..5791a25 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -840,7 +840,7 @@ static int process_sample_event(event_t *self, struct perf_session *s)
 	struct thread *thread;
 
 	bzero(&data, sizeof(data));
-	event__parse_sample(self, s->sample_type, &data);
+	event__parse_sample(self, s, &data);
 
 	thread = perf_session__findnew(s, data.tid);
 	if (thread == NULL) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 55f3b5d..5ef6075 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1619,7 +1619,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 	data.cpu = -1;
 	data.period = -1;
 
-	event__parse_sample(event, session->sample_type, &data);
+	event__parse_sample(event, session, &data);
 
 	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
 		    data.pid, data.tid, data.ip, data.period);
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 9bcc38f..7d752d5 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -477,7 +477,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 
 	memset(&data, 0, sizeof(data));
 
-	event__parse_sample(event, session->sample_type, &data);
+	event__parse_sample(event, session, &data);
 
 	if (session->sample_type & PERF_SAMPLE_TIME) {
 		if (!first_time || first_time > data.time)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 40a6a29..224c586 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -74,7 +74,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 	data.cpu = -1;
 	data.period = 1;
 
-	event__parse_sample(event, session->sample_type, &data);
+	event__parse_sample(event, session, &data);
 
 	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
 		    data.pid, data.tid, data.ip, data.period);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dab9e75..567f97a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -676,7 +676,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
 	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 	struct thread *thread;
 
-	event__parse_sample(self, session->sample_type, data);
+	event__parse_sample(self, session, data);
 
 	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n",
 		    self->header.misc, data->pid, data->tid, data->ip,
@@ -766,9 +766,11 @@ out_filtered:
 	return 0;
 }
 
-int event__parse_sample(const event_t *event, u64 type, struct sample_data *data)
+int event__parse_sample(const event_t *event, struct perf_session *session,
+			struct sample_data *data)
 {
 	const u64 *array = event->sample.array;
+	u64 type = session->sample_type;
 
 	if (type & PERF_SAMPLE_IP) {
 		data->ip = event->ip.ip;
@@ -830,6 +832,28 @@ int event__parse_sample(const event_t *event, u64 type, struct sample_data *data
 		data->raw_size = *p;
 		p++;
 		data->raw_data = p;
+		array += 1 + (data->raw_size * sizeof(u64));
+	}
+
+	if (session->sample_uregs_nr) {
+		data->uregs.version = *array++;
+
+		if (data->uregs.version) {
+			data->uregs.regs = (u64 *)array;
+			array += session->sample_uregs_nr;
+		}
+	}
+
+	if (session->sample_ustack) {
+		u64 size = *array++;
+
+		if (!size) {
+			data->stack.size = 0;
+		} else {
+			data->stack.data = (char *)array;
+			array += size / sizeof(*array);
+			data->stack.size = *array;
+		}
 	}
 
 	return 0;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e790da..5a05396 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,16 @@ struct sample_event {
 	u64 array[];
 };
 
+struct user_regs {
+	u64 version;
+	u64 *regs;
+};
+
+struct user_stack_dump {
+	u64 size;
+	char *data;
+};
+
 struct sample_data {
 	u64 ip;
 	u32 pid, tid;
@@ -73,6 +83,8 @@ struct sample_data {
 	u32 raw_size;
 	void *raw_data;
 	struct ip_callchain *callchain;
+	struct user_regs uregs;
+	struct user_stack_dump stack;
 };
 
 #define BUILD_ID_SIZE 20
@@ -160,7 +172,8 @@ struct addr_location;
 int event__preprocess_sample(const event_t *self, struct perf_session *session,
 			     struct addr_location *al, struct sample_data *data,
 			     symbol_filter_t filter);
-int event__parse_sample(const event_t *event, u64 type, struct sample_data *data);
+int event__parse_sample(const event_t *event, struct perf_session *session,
+			struct sample_data *data);
 
 extern const char *event__name[];
 
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d7e67b1..b73f481 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -922,9 +922,26 @@ out_errno:
 	return -errno;
 }
 
-u64 perf_header__sample_type(struct perf_header *header)
+static int regs_weight(u64 user_regs)
+{
+	int i, bits = 0;
+
+	for (i = 0; i < (int)sizeof(u64) * 8 && user_regs; i++) {
+		if (user_regs & 1)
+			bits++;
+
+		user_regs >>= 1;
+	}
+
+	return bits;
+}
+
+void perf_header__sample_type(struct perf_header *header,
+			      struct perf_session *session)
 {
 	u64 type = 0;
+	u64 uregs = 0;
+	int uregs_nr = 0, ustack = false;
 	int i;
 
 	for (i = 0; i < header->attrs; i++) {
@@ -934,9 +951,21 @@ u64 perf_header__sample_type(struct perf_header *header)
 			type = attr->attr.sample_type;
 		else if (type != attr->attr.sample_type)
 			die("non matching sample_type");
+
+		if (i == 0) {
+			uregs = attr->attr.user_regs;
+			uregs_nr = regs_weight(uregs);
+			ustack = !!attr->attr.ustack_dump_size;
+		} else if (uregs != attr->attr.user_regs ||
+			   ustack != !!attr->attr.ustack_dump_size) {
+			die("non matching sample_type");
+		}
 	}
 
-	return type;
+	session->sample_type = type;
+	session->sample_uregs = uregs;
+	session->sample_uregs_nr = uregs_nr;
+	session->sample_ustack = ustack;
 }
 
 struct perf_event_attr *
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 402ac24..6ec6af2 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -80,7 +80,8 @@ void perf_header_attr__delete(struct perf_header_attr *self);
 
 int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
 
-u64 perf_header__sample_type(struct perf_header *header);
+void perf_header__sample_type(struct perf_header *header,
+			      struct perf_session *session);
 struct perf_event_attr *
 perf_header__find_attr(u64 id, struct perf_header *header);
 void perf_header__set_feat(struct perf_header *self, int feat);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fa9d652..f0e427e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -67,7 +67,7 @@ out_close:
 
 void perf_session__update_sample_type(struct perf_session *self)
 {
-	self->sample_type = perf_header__sample_type(&self->header);
+	perf_header__sample_type(&self->header, self);
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
@@ -576,7 +576,7 @@ static int perf_session__process_sample(event_t *event, struct perf_session *s,
 		return ops->sample(event, s);
 
 	bzero(&data, sizeof(struct sample_data));
-	event__parse_sample(event, s->sample_type, &data);
+	event__parse_sample(event, s, &data);
 
 	queue_sample_event(event, &data, s);
 
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9fa0fc2..ab9ebbc 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -39,6 +39,12 @@ struct perf_session {
 	 */
 	struct hists		hists;
 	u64			sample_type;
+	u64			sample_uregs;
+	/* We should probably use a quick hweight64() in sample_uregs to get
+	 * this instead of storing it.
+	 */
+	int			sample_uregs_nr;
+	bool			sample_ustack;
 	int			fd;
 	bool			fd_pipe;
 	bool			repipe;
-- 
1.6.2.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ