From 0695b20d9adb555b89eb4e095ce377ff8ae04eee Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Sun, 23 Mar 2014 03:38:12 +0000 Subject: [PATCH] InstrProf: Check pointer size in raw profile Since the profile can come from 32-bit machines, we need to check the pointer size. Change the magic number to facilitate this. Adds tests for reading 32-bit and 64-bit binaries (both big- and little-endian). The tests write a binary using printf in RUN lines (like raw-magic-but-no-header.test). Assuming the bots don't complain, this seems like a better way forward for testing RawInstrProfReader than committing binary files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204557 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/InstrProfReader.h | 15 ++++-- lib/ProfileData/InstrProfReader.cpp | 51 +++++++++++++++----- test/tools/llvm-profdata/raw-32-bits-be.test | 42 ++++++++++++++++ test/tools/llvm-profdata/raw-32-bits-le.test | 42 ++++++++++++++++ test/tools/llvm-profdata/raw-64-bits-be.test | 42 ++++++++++++++++ test/tools/llvm-profdata/raw-64-bits-le.test | 42 ++++++++++++++++ 6 files changed, 219 insertions(+), 15 deletions(-) create mode 100644 test/tools/llvm-profdata/raw-32-bits-be.test create mode 100644 test/tools/llvm-profdata/raw-32-bits-le.test create mode 100644 test/tools/llvm-profdata/raw-64-bits-be.test create mode 100644 test/tools/llvm-profdata/raw-64-bits-le.test diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index a14bb4d5b1d..2c070b9706a 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -126,6 +126,10 @@ public: /// /// This format is a raw memory dump of the instrumentation-baed profiling data /// from the runtime. It has no index. +/// +/// Templated on the unsigned type whose size matches pointers on the platform +/// that wrote the profile. +template class RawInstrProfReader : public InstrProfReader { private: /// The profile data file contents. @@ -136,8 +140,8 @@ private: const uint32_t NameSize; const uint32_t NumCounters; const uint64_t FuncHash; - const uint64_t NamePtr; - const uint64_t CounterPtr; + const IntPtrT NamePtr; + const IntPtrT CounterPtr; }; struct RawHeader { const uint64_t Magic; @@ -174,16 +178,19 @@ private: IntT swap(IntT Int) const { return ShouldSwapBytes ? sys::SwapByteOrder(Int) : Int; } - const uint64_t *getCounter(uint64_t CounterPtr) const { + const uint64_t *getCounter(IntPtrT CounterPtr) const { ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); return CountersStart + Offset; } - const char *getName(uint64_t NamePtr) const { + const char *getName(IntPtrT NamePtr) const { ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char); return NamesStart + Offset; } }; +typedef RawInstrProfReader RawInstrProfReader32; +typedef RawInstrProfReader RawInstrProfReader64; + } // end namespace llvm #endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index 48e740eaf42..47853ad8b72 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -30,8 +30,10 @@ error_code InstrProfReader::create(std::string Path, return instrprof_error::too_large; // Create the reader. - if (RawInstrProfReader::hasFormat(*Buffer)) - Result.reset(new RawInstrProfReader(std::move(Buffer))); + if (RawInstrProfReader64::hasFormat(*Buffer)) + Result.reset(new RawInstrProfReader64(std::move(Buffer))); + else if (RawInstrProfReader32::hasFormat(*Buffer)) + Result.reset(new RawInstrProfReader32(std::move(Buffer))); else Result.reset(new TextInstrProfReader(std::move(Buffer))); @@ -85,7 +87,11 @@ error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { return success(); } -static uint64_t getRawMagic() { +template +static uint64_t getRawMagic(); + +template <> +uint64_t getRawMagic() { return uint64_t(255) << 56 | uint64_t('l') << 48 | @@ -97,21 +103,36 @@ static uint64_t getRawMagic() { uint64_t(129); } -bool RawInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { - if (DataBuffer.getBufferSize() < sizeof(getRawMagic())) +template <> +uint64_t getRawMagic() { + return + uint64_t(255) << 56 | + uint64_t('l') << 48 | + uint64_t('p') << 40 | + uint64_t('r') << 32 | + uint64_t('o') << 24 | + uint64_t('f') << 16 | + uint64_t('R') << 8 | + uint64_t(129); +} + +template +bool RawInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { + if (DataBuffer.getBufferSize() < sizeof(getRawMagic())) return false; const RawHeader *Header = (const RawHeader *)DataBuffer.getBufferStart(); - return getRawMagic() == Header->Magic || - sys::SwapByteOrder(getRawMagic()) == Header->Magic; + return getRawMagic() == Header->Magic || + sys::SwapByteOrder(getRawMagic()) == Header->Magic; } -error_code RawInstrProfReader::readHeader() { +template +error_code RawInstrProfReader::readHeader() { if (!hasFormat(*DataBuffer)) return error(instrprof_error::bad_magic); if (DataBuffer->getBufferSize() < sizeof(RawHeader)) return error(instrprof_error::bad_header); const RawHeader *Header = (const RawHeader *)DataBuffer->getBufferStart(); - ShouldSwapBytes = Header->Magic != getRawMagic(); + ShouldSwapBytes = Header->Magic != getRawMagic(); return readHeader(*Header); } @@ -119,7 +140,8 @@ static uint64_t getRawVersion() { return 1; } -error_code RawInstrProfReader::readHeader(const RawHeader &Header) { +template +error_code RawInstrProfReader::readHeader(const RawHeader &Header) { if (swap(Header.Version) != getRawVersion()) return error(instrprof_error::unsupported_version); @@ -145,7 +167,9 @@ error_code RawInstrProfReader::readHeader(const RawHeader &Header) { return success(); } -error_code RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { +template +error_code +RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { if (Data == DataEnd) return error(instrprof_error::eof); @@ -177,3 +201,8 @@ error_code RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { ++Data; return success(); } + +namespace llvm { +template class RawInstrProfReader; +template class RawInstrProfReader; +} diff --git a/test/tools/llvm-profdata/raw-32-bits-be.test b/test/tools/llvm-profdata/raw-32-bits-be.test new file mode 100644 index 00000000000..86ac56d39f2 --- /dev/null +++ b/test/tools/llvm-profdata/raw-32-bits-be.test @@ -0,0 +1,42 @@ +RUN: printf '\377lprofR\201' > %t +RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\2' >> %t +RUN: printf '\0\0\0\0\0\0\0\3' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t +RUN: printf '\0\0\0\0\1\0\0\0' >> %t +RUN: printf '\0\0\0\0\2\0\0\0' >> %t + +RUN: printf '\0\0\0\3' >> %t +RUN: printf '\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\2\0\0\0' >> %t +RUN: printf '\1\0\0\0' >> %t + +RUN: printf '\0\0\0\3' >> %t +RUN: printf '\0\0\0\2' >> %t +RUN: printf '\0\0\0\0\0\0\0\2' >> %t +RUN: printf '\2\0\0\03' >> %t +RUN: printf '\1\0\0\10' >> %t + +RUN: printf '\0\0\0\0\0\0\0\023' >> %t +RUN: printf '\0\0\0\0\0\0\0\067' >> %t +RUN: printf '\0\0\0\0\0\0\0\101' >> %t +RUN: printf 'foobar' >> %t + +RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s + +CHECK: Counters: +CHECK: foo: +CHECK: Hash: 0x0000000000000001 +CHECK: Counters: 1 +CHECK: Function count: 19 +CHECK: Block counts: [] +CHECK: bar: +CHECK: Hash: 0x0000000000000002 +CHECK: Counters: 2 +CHECK: Function count: 55 +CHECK: Block counts: [65] +CHECK: Functions shown: 2 +CHECK: Total functions: 2 +CHECK: Maximum function count: 55 +CHECK: Maximum internal block count: 65 diff --git a/test/tools/llvm-profdata/raw-32-bits-le.test b/test/tools/llvm-profdata/raw-32-bits-le.test new file mode 100644 index 00000000000..9325e7eb0f5 --- /dev/null +++ b/test/tools/llvm-profdata/raw-32-bits-le.test @@ -0,0 +1,42 @@ +RUN: printf '\201Rforpl\377' > %t +RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\2\0\0\0\0\0\0\0' >> %t +RUN: printf '\3\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\1\0\0\0\0' >> %t +RUN: printf '\0\0\0\2\0\0\0\0' >> %t + +RUN: printf '\3\0\0\0' >> %t +RUN: printf '\1\0\0\0' >> %t +RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\2' >> %t +RUN: printf '\0\0\0\1' >> %t + +RUN: printf '\3\0\0\0' >> %t +RUN: printf '\2\0\0\0' >> %t +RUN: printf '\02\0\0\0\0\0\0\0' >> %t +RUN: printf '\03\0\0\2' >> %t +RUN: printf '\10\0\0\1' >> %t + +RUN: printf '\023\0\0\0\0\0\0\0' >> %t +RUN: printf '\067\0\0\0\0\0\0\0' >> %t +RUN: printf '\101\0\0\0\0\0\0\0' >> %t +RUN: printf 'foobar' >> %t + +RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s + +CHECK: Counters: +CHECK: foo: +CHECK: Hash: 0x0000000000000001 +CHECK: Counters: 1 +CHECK: Function count: 19 +CHECK: Block counts: [] +CHECK: bar: +CHECK: Hash: 0x0000000000000002 +CHECK: Counters: 2 +CHECK: Function count: 55 +CHECK: Block counts: [65] +CHECK: Functions shown: 2 +CHECK: Total functions: 2 +CHECK: Maximum function count: 55 +CHECK: Maximum internal block count: 65 diff --git a/test/tools/llvm-profdata/raw-64-bits-be.test b/test/tools/llvm-profdata/raw-64-bits-be.test new file mode 100644 index 00000000000..b97d8b5dac6 --- /dev/null +++ b/test/tools/llvm-profdata/raw-64-bits-be.test @@ -0,0 +1,42 @@ +RUN: printf '\377lprofr\201' > %t +RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\2' >> %t +RUN: printf '\0\0\0\0\0\0\0\3' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t +RUN: printf '\0\0\0\1\0\4\0\0' >> %t +RUN: printf '\0\0\0\2\0\4\0\0' >> %t + +RUN: printf '\0\0\0\3' >> %t +RUN: printf '\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\0\0\0\2\0\4\0\0' >> %t +RUN: printf '\0\0\0\1\0\4\0\0' >> %t + +RUN: printf '\0\0\0\3' >> %t +RUN: printf '\0\0\0\2' >> %t +RUN: printf '\0\0\0\0\0\0\0\02' >> %t +RUN: printf '\0\0\0\2\0\4\0\03' >> %t +RUN: printf '\0\0\0\1\0\4\0\10' >> %t + +RUN: printf '\0\0\0\0\0\0\0\023' >> %t +RUN: printf '\0\0\0\0\0\0\0\067' >> %t +RUN: printf '\0\0\0\0\0\0\0\101' >> %t +RUN: printf 'foobar' >> %t + +RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s + +CHECK: Counters: +CHECK: foo: +CHECK: Hash: 0x0000000000000001 +CHECK: Counters: 1 +CHECK: Function count: 19 +CHECK: Block counts: [] +CHECK: bar: +CHECK: Hash: 0x0000000000000002 +CHECK: Counters: 2 +CHECK: Function count: 55 +CHECK: Block counts: [65] +CHECK: Functions shown: 2 +CHECK: Total functions: 2 +CHECK: Maximum function count: 55 +CHECK: Maximum internal block count: 65 diff --git a/test/tools/llvm-profdata/raw-64-bits-le.test b/test/tools/llvm-profdata/raw-64-bits-le.test new file mode 100644 index 00000000000..0e6853811ec --- /dev/null +++ b/test/tools/llvm-profdata/raw-64-bits-le.test @@ -0,0 +1,42 @@ +RUN: printf '\201rforpl\377' > %t +RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\2\0\0\0\0\0\0\0' >> %t +RUN: printf '\3\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\4\0\1\0\0\0' >> %t +RUN: printf '\0\0\4\0\2\0\0\0' >> %t + +RUN: printf '\3\0\0\0' >> %t +RUN: printf '\1\0\0\0' >> %t +RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\4\0\2\0\0\0' >> %t +RUN: printf '\0\0\4\0\1\0\0\0' >> %t + +RUN: printf '\03\0\0\0' >> %t +RUN: printf '\02\0\0\0' >> %t +RUN: printf '\02\0\0\0\0\0\0\0' >> %t +RUN: printf '\03\0\4\0\2\0\0\0' >> %t +RUN: printf '\10\0\4\0\1\0\0\0' >> %t + +RUN: printf '\023\0\0\0\0\0\0\0' >> %t +RUN: printf '\067\0\0\0\0\0\0\0' >> %t +RUN: printf '\101\0\0\0\0\0\0\0' >> %t +RUN: printf 'foobar' >> %t + +RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s + +CHECK: Counters: +CHECK: foo: +CHECK: Hash: 0x0000000000000001 +CHECK: Counters: 1 +CHECK: Function count: 19 +CHECK: Block counts: [] +CHECK: bar: +CHECK: Hash: 0x0000000000000002 +CHECK: Counters: 2 +CHECK: Function count: 55 +CHECK: Block counts: [65] +CHECK: Functions shown: 2 +CHECK: Total functions: 2 +CHECK: Maximum function count: 55 +CHECK: Maximum internal block count: 65 -- 2.34.1