diff options
Diffstat (limited to 'tools/perf/util/evsel.c')
| -rw-r--r-- | tools/perf/util/evsel.c | 57 | 
1 files changed, 46 insertions, 11 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a03a36b7908..e389815078d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -7,6 +7,8 @@   * Released under the GPL v2. (and only v2, not any later version)   */ +#include <byteswap.h> +#include "asm/bug.h"  #include "evsel.h"  #include "evlist.h"  #include "util.h" @@ -342,10 +344,20 @@ static bool sample_overlap(const union perf_event *event,  int perf_event__parse_sample(const union perf_event *event, u64 type,  			     int sample_size, bool sample_id_all, -			     struct perf_sample *data) +			     struct perf_sample *data, bool swapped)  {  	const u64 *array; +	/* +	 * used for cross-endian analysis. See git commit 65014ab3 +	 * for why this goofiness is needed. +	 */ +	union { +		u64 val64; +		u32 val32[2]; +	} u; + +  	data->cpu = data->pid = data->tid = -1;  	data->stream_id = data->id = data->time = -1ULL; @@ -366,9 +378,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,  	}  	if (type & PERF_SAMPLE_TID) { -		u32 *p = (u32 *)array; -		data->pid = p[0]; -		data->tid = p[1]; +		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]); +		} + +		data->pid = u.val32[0]; +		data->tid = u.val32[1];  		array++;  	} @@ -395,8 +414,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,  	}  	if (type & PERF_SAMPLE_CPU) { -		u32 *p = (u32 *)array; -		data->cpu = *p; + +		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]); +		} + +		data->cpu = u.val32[0];  		array++;  	} @@ -423,18 +449,27 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,  	}  	if (type & PERF_SAMPLE_RAW) { -		u32 *p = (u32 *)array; +		const u64 *pdata; + +		u.val64 = *array; +		if (WARN_ONCE(swapped, +			      "Endianness of raw data not corrected!\n")) { +			/* 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]); +		}  		if (sample_overlap(event, array, sizeof(u32)))  			return -EFAULT; -		data->raw_size = *p; -		p++; +		data->raw_size = u.val32[0]; +		pdata = (void *) array + sizeof(u32); -		if (sample_overlap(event, p, data->raw_size)) +		if (sample_overlap(event, pdata, data->raw_size))  			return -EFAULT; -		data->raw_data = p; +		data->raw_data = (void *) pdata;  	}  	return 0;  |