summaryrefslogtreecommitdiff
path: root/lib/ProfileData
diff options
context:
space:
mode:
authorJustin Bogner <mail@justinbogner.com>2014-05-16 00:38:00 +0000
committerJustin Bogner <mail@justinbogner.com>2014-05-16 00:38:00 +0000
commit6d81fc75c495e8ed20f1508042bcd2edba1a8058 (patch)
tree2e9bf4b426f9639b8a27cca4fffad706bdddced1 /lib/ProfileData
parent9364e63d79c5efb8b9a10df7f3f3f09a9c9cd2a4 (diff)
downloadllvm-6d81fc75c495e8ed20f1508042bcd2edba1a8058.tar.gz
llvm-6d81fc75c495e8ed20f1508042bcd2edba1a8058.tar.bz2
llvm-6d81fc75c495e8ed20f1508042bcd2edba1a8058.tar.xz
ProfileData: Allow multiple profiles in RawInstrProfReader
Allow multiple raw profiles to coexist in a single .profraw file, given the following conditions: - Zero padding at the end of or between profiles will be skipped. - Each profile must start with a valid header. - Mixing endianness or pointer sizes in concatenated profiles files is not allowed. This is needed to handle cases where a program's shared libraries are profiled as well as the main executable itself, as we'll need to emit each executable's counters. Combining the tables in the runtime would be expensive for the instrumented program. rdar://16918688 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208938 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ProfileData')
-rw-r--r--lib/ProfileData/InstrProfReader.cpp33
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp
index 2ab0eb9449..7014f5e5cc 100644
--- a/lib/ProfileData/InstrProfReader.cpp
+++ b/lib/ProfileData/InstrProfReader.cpp
@@ -172,6 +172,29 @@ error_code RawInstrProfReader<IntPtrT>::readHeader() {
return readHeader(*Header);
}
+template <class IntPtrT>
+error_code RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
+ const char *End = DataBuffer->getBufferEnd();
+ // Skip zero padding between profiles.
+ while (CurrentPos != End && *CurrentPos == 0)
+ ++CurrentPos;
+ // If there's nothing left, we're done.
+ if (CurrentPos == End)
+ return instrprof_error::eof;
+ // If there isn't enough space for another header, this is probably just
+ // garbage at the end of the file.
+ if (CurrentPos + sizeof(RawHeader) > End)
+ return instrprof_error::malformed;
+ // The magic should have the same byte order as in the previous header.
+ uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
+ if (Magic != swap(getRawMagic<IntPtrT>()))
+ return instrprof_error::bad_magic;
+
+ // There's another profile to read, so we need to process the header.
+ auto *Header = reinterpret_cast<const RawHeader *>(CurrentPos);
+ return readHeader(*Header);
+}
+
static uint64_t getRawVersion() {
return 1;
}
@@ -190,16 +213,17 @@ error_code RawInstrProfReader<IntPtrT>::readHeader(const RawHeader &Header) {
ptrdiff_t DataOffset = sizeof(RawHeader);
ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize;
ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
- size_t FileSize = NamesOffset + sizeof(char) * NamesSize;
+ size_t ProfileSize = NamesOffset + sizeof(char) * NamesSize;
- if (FileSize != DataBuffer->getBufferSize())
+ auto *Start = reinterpret_cast<const char *>(&Header);
+ if (Start + ProfileSize > DataBuffer->getBufferEnd())
return error(instrprof_error::bad_header);
- const char *Start = DataBuffer->getBufferStart();
Data = reinterpret_cast<const ProfileData *>(Start + DataOffset);
DataEnd = Data + DataSize;
CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
NamesStart = Start + NamesOffset;
+ ProfileEnd = Start + ProfileSize;
return success();
}
@@ -208,7 +232,8 @@ template <class IntPtrT>
error_code
RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
if (Data == DataEnd)
- return error(instrprof_error::eof);
+ if (error_code EC = readNextHeader(ProfileEnd))
+ return EC;
// Get the raw data.
StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize));