From 831eafbeca6f220942a27e245ea812029cd389c5 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 22 Aug 2011 18:43:49 -0600 Subject: [PATCH] perf tool: fix endianness handling with feature bits Feature bitmap is declared as an array of unsigned longs -- not good. We need to handle endianness of the feature bitmap, but we don't know the size of the unsigned long where the file was generated. So, best guess at determining it: try 64 bit swap first (ie., file created on 64-bit host), then check if buildid feature bit is set. If not, try a 32-bit swap. If buildid bit is still not set, punt and fallback to original behavior -- clearing all feature bits and setting buildid Signed-off-by: David Ahern --- tools/perf/util/header.c | 40 +++++++++++++++++++++++++++++----------- 1 files changed, 29 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6b189d5..601ec0d 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -687,21 +687,39 @@ int perf_file_header__read(struct perf_file_header *header, bitmap_zero(header->adds_features, HEADER_FEAT_BITS); else return -1; + } else if (ph->needs_swap){ + unsigned int i; + /* + * feature bitmap is declared as an array of unsigned longs -- not + * good since host that generated the file and host analyzing file + * can be of different sizes. + * + * We need to handle endianness, but we don't know the size of the + * unsigned long where the file was generated. So, take a best guess + * at determining it: try 64 bit swap first (ie., file created on a + * 64-bit host), then check if buildid feature bit is set. If not, + * undo the 64-bit swap and try a 32-bit swap. If buildid bit is still + * not set, punt and fallback to the original behavior -- clearing all + * feature bits and setting buildid. + */ + for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) + header->adds_features[i] = bswap_64(header->adds_features[i]); + + if (!test_bit(HEADER_BUILD_ID, header->adds_features)) { + for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) { + header->adds_features[i] = bswap_64(header->adds_features[i]); + header->adds_features[i] = bswap_32(header->adds_features[i]); + } + } + + if (!test_bit(HEADER_BUILD_ID, header->adds_features)) { + bitmap_zero(header->adds_features, HEADER_FEAT_BITS); + set_bit(HEADER_BUILD_ID, header->adds_features); + } } memcpy(&ph->adds_features, &header->adds_features, sizeof(ph->adds_features)); - /* - * FIXME: hack that assumes that if we need swap the perf.data file - * may be coming from an arch with a different word-size, ergo different - * DEFINE_BITMAP format, investigate more later, but for now its mostly - * safe to assume that we have a build-id section. Trace files probably - * have several other issues in this realm anyway... - */ - if (ph->needs_swap) { - memset(&ph->adds_features, 0, sizeof(ph->adds_features)); - perf_header__set_feat(ph, HEADER_BUILD_ID); - } ph->event_offset = header->event_types.offset; ph->event_size = header->event_types.size; -- 1.7.6