perf tool: fix endianness handling of u32 data in samples
PATCH 1/1 perf tool: fix endianness handling of u32 data in samples
Currently, analyzing PPC data files on x86 the cpu field is always 0 and the tid and pid are backwards. For example, analyzing a PPC file on PPC the pid/tid fields show:
rsyslogd 1210/1212
and analyzing the same PPC file using an x86 perf binary shows:
rsyslogd 1212/1210
The problem is that the swap_op method for samples is perf_event__all64_swap which assumes all elements in the sample_data struct are u64s. cpu, tid and pid are u32s and need to be handled individually. Given that the swap is done before the sample is parsed, the simplest solution is to undo the 64-bit swap of those elements when the sample is parsed and do the proper swap.
The RAW data field is generic and perf cannot have programmatic knowledge of how to treat that data. Instead a warning is given to the user.
Thanks to Anton Blanchard for providing a data file for a mult-CPU PPC system so I could verify the fix for the CPU fields.
v2 -> v3:
- used WARN_ONCE for message regarding raw data
- removed struct wrapper around union
- fixed whitespace issues
v1 -> v2:
- added a union for undoing the byte-swap on u64 and redoing swap on u32's to address compiler errors (see git commit 65014ab3)
--- tools/perf/builtin-test.c | 2 +- tools/perf/util/event.h | 2 +- tools/perf/util/evsel.c | 55 ++++++++++++++++++++++++++++++++++++--------- tools/perf/util/session.h | 3 +- 4 files changed, 48 insertions(+), 14 deletions(-)
tools/perf/builtin-test.c +1 -1
@@ -561,7 +561,7 @@ static int test__basic_mmap(void) } err =perf_event__parse_sample (event, attr.sample_type, sample_size, - false, &sample); + false, &sample, false);if (err) {pr_err ("Can't parse sample, err = %d\n" , err); goto out_munmap;
tools/perf/util/event.h +1 -1
@@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id);int perf_event__parse_sample (const union perf_event *event,u64 type,int sample_size,bool sample_id_all, -struct perf_sample *sample); +struct perf_sample *sample,bool swapped);#endif /* __PERF_RECORD_H */
tools/perf/util/evsel.c +44 -11
95 lines not on this page · raw message
tools/perf/util/session.h +2 -1
@@ -162,7 +162,8 @@ static inline int perf_session__parse_sample(struct perf_session *session, {return perf_event__parse_sample (event, session->sample_type, session->sample_size, - session->sample_id_all, sample); + session->sample_id_all, sample, + session->header.needs_swap); } struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
Signature · 1 line
1.7.6
Em Fri, Sep 02, 2011 at 01:41:51PM -0600, David Ahern escreveu:
Quoted 4 lines
tools/perf/util/evsel.c +0
-0@@ -423,18 +449,25 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, }if (type &PERF_SAMPLE_RAW ) {
tools/perf/util/evsel.c int perf_event__parse_sample(const union perf_event *event, u64 type, · line 460
Quoted 10 lines
tools/perf/util/evsel.c +9
-1-u32 *p = (u32 *)array; + u.val64 = *array; +if (swapped) { +/* undo swap of u64, then swap on individual u32s */ + u.val64 =bswap_64 (u.val64); + u.val32[0 ] =bswap_32 (u.val32[0 ]); + u.val32[1 ] =bswap_32 (u.val32[1 ]); + +WARN_ONCE (swapped,"Endianness of raw data not corrected!\n" ); + }
That works too, but then we'll be always testing swapped two times :-)
- Arnaldo
Quoted 18 lines · Arnaldo Carvalho de Melo
Em Fri, Sep 02, 2011 at 01:41:51PM -0600, David Ahern escreveu:
Quoted 4 lines
tools/perf/util/evsel.c +0
-0@@ -423,18 +449,25 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, }if (type &PERF_SAMPLE_RAW ) {tools/perf/util/evsel.c int perf_event__parse_sample(const union perf_event *event, u64 type, · line 460
Quoted 10 lines
tools/perf/util/evsel.c +9
-1-u32 *p = (u32 *)array; + u.val64 = *array; +if (swapped) { +/* undo swap of u64, then swap on individual u32s */ + u.val64 =bswap_64 (u.val64); + u.val32[0 ] =bswap_32 (u.val32[0 ]); + u.val32[1 ] =bswap_32 (u.val32[1 ]); + +WARN_ONCE (swapped,"Endianness of raw data not corrected!\n" ); + }That works too, but then we'll be always testing swapped two times :-)
Quoted 1 line
- Arnaldo
I did not see a WARN_ONCE with no 'condition' variable, so I went with the redundant test. I guess swapped really could be changed to '1' -- like an example I saw in the acpi code.
David