aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/trace-event-parse.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-09-11 20:43:45 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-13 04:22:41 -0400
commit46538818023e8ea94f656acfa1e38297e2df20e2 (patch)
tree1cac2198d1b90036cbec61639ebee6a80d6238a3 /tools/perf/util/trace-event-parse.c
parentbcd3279f465cdcc1e0454b5f605f021c4ff4dbb5 (diff)
perf sched: Fix bad event alignment
perf sched raises the following error when it meets a sched switch event: perf: builtin-sched.c:286: register_pid: Assertion `!(pid >= 65536)' failed. Abandon Currently in x86-64, the sched switch events have a hole in the middle of the structure: u16 common_type; u8 common_flags; u8 common_preempt_count; u32 common_pid; u32 common_tgid; char prev_comm[16]; u32 prev_pid; u32 prev_prio; <--- there u64 prev_state; char next_comm[16]; u32 next_pid; u32 next_prio; Gcc inserts a 4 bytes hole there for prev_state to be u64 aligned. And the events are exported to userspace with this hole. But in userspace, from perf sched, we fetch it using a structure that has a new field in the beginning: u32 size. This is because our trace is exported with its size as a field. But now that we have this new field, the hole in the middle disappears because it makes prev_state becoming well aligned. And since we are using a pointer to the raw trace using this struct, instead of reading prev_state, we are reading the hole. We could fix it by keeping the size seperate from the struct but actually there a lot of other potential problems: some fields may be saved as long in a 64 bits system and later read as long in a 32 bits system. Also this direct cast doesn't care about the endianness differences between the host traced machine and the machine in which we do the post processing. So instead of using such dangerous direct casts, fetch the values using the trace parsing API that already takes care of all these problems. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/trace-event-parse.c')
-rw-r--r--tools/perf/util/trace-event-parse.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 16cf2d51c4e1..64d6e302751a 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1776,6 +1776,29 @@ static unsigned long long read_size(void *ptr, int size)
1776 } 1776 }
1777} 1777}
1778 1778
1779unsigned long long
1780raw_field_value(struct event *event, const char *name, void *data)
1781{
1782 struct format_field *field;
1783
1784 field = find_any_field(event, name);
1785 if (!field)
1786 return 0ULL;
1787
1788 return read_size(data + field->offset, field->size);
1789}
1790
1791void *raw_field_ptr(struct event *event, const char *name, void *data)
1792{
1793 struct format_field *field;
1794
1795 field = find_any_field(event, name);
1796 if (!field)
1797 return NULL;
1798
1799 return data + field->offset;
1800}
1801
1779static int get_common_info(const char *type, int *offset, int *size) 1802static int get_common_info(const char *type, int *offset, int *size)
1780{ 1803{
1781 struct event *event; 1804 struct event *event;