1 //=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains support for reading profiling data for clang's 11 // instrumentation based PGO and coverage. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ProfileData/InstrProfReader.h" 16 #include "llvm/ProfileData/InstrProf.h" 17 18 #include "InstrProfIndexed.h" 19 20 #include <cassert> 21 22 using namespace llvm; 23 24 static std::error_code 25 setupMemoryBuffer(std::string Path, std::unique_ptr<MemoryBuffer> &Buffer) { 26 if (std::error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer)) 27 return EC; 28 29 // Sanity check the file. 30 if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 31 return instrprof_error::too_large; 32 return instrprof_error::success; 33 } 34 35 static std::error_code initializeReader(InstrProfReader &Reader) { 36 return Reader.readHeader(); 37 } 38 39 std::error_code 40 InstrProfReader::create(std::string Path, 41 std::unique_ptr<InstrProfReader> &Result) { 42 // Set up the buffer to read. 43 std::unique_ptr<MemoryBuffer> Buffer; 44 if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) 45 return EC; 46 47 // Create the reader. 48 if (IndexedInstrProfReader::hasFormat(*Buffer)) 49 Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 50 else if (RawInstrProfReader64::hasFormat(*Buffer)) 51 Result.reset(new RawInstrProfReader64(std::move(Buffer))); 52 else if (RawInstrProfReader32::hasFormat(*Buffer)) 53 Result.reset(new RawInstrProfReader32(std::move(Buffer))); 54 else 55 Result.reset(new TextInstrProfReader(std::move(Buffer))); 56 57 // Initialize the reader and return the result. 58 return initializeReader(*Result); 59 } 60 61 std::error_code IndexedInstrProfReader::create( 62 std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result) { 63 // Set up the buffer to read. 64 std::unique_ptr<MemoryBuffer> Buffer; 65 if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) 66 return EC; 67 68 // Create the reader. 69 if (!IndexedInstrProfReader::hasFormat(*Buffer)) 70 return instrprof_error::bad_magic; 71 Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 72 73 // Initialize the reader and return the result. 74 return initializeReader(*Result); 75 } 76 77 void InstrProfIterator::Increment() { 78 if (Reader->readNextRecord(Record)) 79 *this = InstrProfIterator(); 80 } 81 82 std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { 83 // Skip empty lines. 84 while (!Line.is_at_end() && Line->empty()) 85 ++Line; 86 // If we hit EOF while looking for a name, we're done. 87 if (Line.is_at_end()) 88 return error(instrprof_error::eof); 89 90 // Read the function name. 91 Record.Name = *Line++; 92 93 // Read the function hash. 94 if (Line.is_at_end()) 95 return error(instrprof_error::truncated); 96 if ((Line++)->getAsInteger(10, Record.Hash)) 97 return error(instrprof_error::malformed); 98 99 // Read the number of counters. 100 uint64_t NumCounters; 101 if (Line.is_at_end()) 102 return error(instrprof_error::truncated); 103 if ((Line++)->getAsInteger(10, NumCounters)) 104 return error(instrprof_error::malformed); 105 if (NumCounters == 0) 106 return error(instrprof_error::malformed); 107 108 // Read each counter and fill our internal storage with the values. 109 Counts.clear(); 110 Counts.reserve(NumCounters); 111 for (uint64_t I = 0; I < NumCounters; ++I) { 112 if (Line.is_at_end()) 113 return error(instrprof_error::truncated); 114 uint64_t Count; 115 if ((Line++)->getAsInteger(10, Count)) 116 return error(instrprof_error::malformed); 117 Counts.push_back(Count); 118 } 119 // Give the record a reference to our internal counter storage. 120 Record.Counts = Counts; 121 122 return success(); 123 } 124 125 template <class IntPtrT> 126 static uint64_t getRawMagic(); 127 128 template <> 129 uint64_t getRawMagic<uint64_t>() { 130 return 131 uint64_t(255) << 56 | 132 uint64_t('l') << 48 | 133 uint64_t('p') << 40 | 134 uint64_t('r') << 32 | 135 uint64_t('o') << 24 | 136 uint64_t('f') << 16 | 137 uint64_t('r') << 8 | 138 uint64_t(129); 139 } 140 141 template <> 142 uint64_t getRawMagic<uint32_t>() { 143 return 144 uint64_t(255) << 56 | 145 uint64_t('l') << 48 | 146 uint64_t('p') << 40 | 147 uint64_t('r') << 32 | 148 uint64_t('o') << 24 | 149 uint64_t('f') << 16 | 150 uint64_t('R') << 8 | 151 uint64_t(129); 152 } 153 154 template <class IntPtrT> 155 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 156 if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 157 return false; 158 uint64_t Magic = 159 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 160 return getRawMagic<IntPtrT>() == Magic || 161 sys::getSwappedBytes(getRawMagic<IntPtrT>()) == Magic; 162 } 163 164 template <class IntPtrT> 165 std::error_code RawInstrProfReader<IntPtrT>::readHeader() { 166 if (!hasFormat(*DataBuffer)) 167 return error(instrprof_error::bad_magic); 168 if (DataBuffer->getBufferSize() < sizeof(RawHeader)) 169 return error(instrprof_error::bad_header); 170 auto *Header = 171 reinterpret_cast<const RawHeader *>(DataBuffer->getBufferStart()); 172 ShouldSwapBytes = Header->Magic != getRawMagic<IntPtrT>(); 173 return readHeader(*Header); 174 } 175 176 template <class IntPtrT> 177 std::error_code 178 RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 179 const char *End = DataBuffer->getBufferEnd(); 180 // Skip zero padding between profiles. 181 while (CurrentPos != End && *CurrentPos == 0) 182 ++CurrentPos; 183 // If there's nothing left, we're done. 184 if (CurrentPos == End) 185 return instrprof_error::eof; 186 // If there isn't enough space for another header, this is probably just 187 // garbage at the end of the file. 188 if (CurrentPos + sizeof(RawHeader) > End) 189 return instrprof_error::malformed; 190 // The magic should have the same byte order as in the previous header. 191 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 192 if (Magic != swap(getRawMagic<IntPtrT>())) 193 return instrprof_error::bad_magic; 194 195 // There's another profile to read, so we need to process the header. 196 auto *Header = reinterpret_cast<const RawHeader *>(CurrentPos); 197 return readHeader(*Header); 198 } 199 200 static uint64_t getRawVersion() { 201 return 1; 202 } 203 204 template <class IntPtrT> 205 std::error_code 206 RawInstrProfReader<IntPtrT>::readHeader(const RawHeader &Header) { 207 if (swap(Header.Version) != getRawVersion()) 208 return error(instrprof_error::unsupported_version); 209 210 CountersDelta = swap(Header.CountersDelta); 211 NamesDelta = swap(Header.NamesDelta); 212 auto DataSize = swap(Header.DataSize); 213 auto CountersSize = swap(Header.CountersSize); 214 auto NamesSize = swap(Header.NamesSize); 215 216 ptrdiff_t DataOffset = sizeof(RawHeader); 217 ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize; 218 ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 219 size_t ProfileSize = NamesOffset + sizeof(char) * NamesSize; 220 221 auto *Start = reinterpret_cast<const char *>(&Header); 222 if (Start + ProfileSize > DataBuffer->getBufferEnd()) 223 return error(instrprof_error::bad_header); 224 225 Data = reinterpret_cast<const ProfileData *>(Start + DataOffset); 226 DataEnd = Data + DataSize; 227 CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 228 NamesStart = Start + NamesOffset; 229 ProfileEnd = Start + ProfileSize; 230 231 return success(); 232 } 233 234 template <class IntPtrT> 235 std::error_code 236 RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { 237 if (Data == DataEnd) 238 if (std::error_code EC = readNextHeader(ProfileEnd)) 239 return EC; 240 241 // Get the raw data. 242 StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize)); 243 uint32_t NumCounters = swap(Data->NumCounters); 244 if (NumCounters == 0) 245 return error(instrprof_error::malformed); 246 auto RawCounts = makeArrayRef(getCounter(Data->CounterPtr), NumCounters); 247 248 // Check bounds. 249 auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 250 if (RawName.data() < NamesStart || 251 RawName.data() + RawName.size() > DataBuffer->getBufferEnd() || 252 RawCounts.data() < CountersStart || 253 RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 254 return error(instrprof_error::malformed); 255 256 // Store the data in Record, byte-swapping as necessary. 257 Record.Hash = swap(Data->FuncHash); 258 Record.Name = RawName; 259 if (ShouldSwapBytes) { 260 Counts.clear(); 261 Counts.reserve(RawCounts.size()); 262 for (uint64_t Count : RawCounts) 263 Counts.push_back(swap(Count)); 264 Record.Counts = Counts; 265 } else 266 Record.Counts = RawCounts; 267 268 // Iterate. 269 ++Data; 270 return success(); 271 } 272 273 namespace llvm { 274 template class RawInstrProfReader<uint32_t>; 275 template class RawInstrProfReader<uint64_t>; 276 } 277 278 InstrProfLookupTrait::hash_value_type 279 InstrProfLookupTrait::ComputeHash(StringRef K) { 280 return IndexedInstrProf::ComputeHash(HashType, K); 281 } 282 283 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 284 if (DataBuffer.getBufferSize() < 8) 285 return false; 286 using namespace support; 287 uint64_t Magic = 288 endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 289 return Magic == IndexedInstrProf::Magic; 290 } 291 292 std::error_code IndexedInstrProfReader::readHeader() { 293 const unsigned char *Start = 294 (const unsigned char *)DataBuffer->getBufferStart(); 295 const unsigned char *Cur = Start; 296 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 297 return error(instrprof_error::truncated); 298 299 using namespace support; 300 301 // Check the magic number. 302 uint64_t Magic = endian::readNext<uint64_t, little, unaligned>(Cur); 303 if (Magic != IndexedInstrProf::Magic) 304 return error(instrprof_error::bad_magic); 305 306 // Read the version. 307 uint64_t Version = endian::readNext<uint64_t, little, unaligned>(Cur); 308 if (Version != IndexedInstrProf::Version) 309 return error(instrprof_error::unsupported_version); 310 311 // Read the maximal function count. 312 MaxFunctionCount = endian::readNext<uint64_t, little, unaligned>(Cur); 313 314 // Read the hash type and start offset. 315 IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 316 endian::readNext<uint64_t, little, unaligned>(Cur)); 317 if (HashType > IndexedInstrProf::HashT::Last) 318 return error(instrprof_error::unsupported_hash_type); 319 uint64_t HashOffset = endian::readNext<uint64_t, little, unaligned>(Cur); 320 321 // The rest of the file is an on disk hash table. 322 Index.reset(InstrProfReaderIndex::Create(Start + HashOffset, Cur, Start, 323 InstrProfLookupTrait(HashType))); 324 // Set up our iterator for readNextRecord. 325 RecordIterator = Index->data_begin(); 326 327 return success(); 328 } 329 330 std::error_code IndexedInstrProfReader::getFunctionCounts( 331 StringRef FuncName, uint64_t &FuncHash, std::vector<uint64_t> &Counts) { 332 const auto &Iter = Index->find(FuncName); 333 if (Iter == Index->end()) 334 return error(instrprof_error::unknown_function); 335 336 // Found it. Make sure it's valid before giving back a result. 337 const InstrProfRecord &Record = *Iter; 338 if (Record.Name.empty()) 339 return error(instrprof_error::malformed); 340 FuncHash = Record.Hash; 341 Counts = Record.Counts; 342 return success(); 343 } 344 345 std::error_code 346 IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { 347 // Are we out of records? 348 if (RecordIterator == Index->data_end()) 349 return error(instrprof_error::eof); 350 351 // Read the next one. 352 Record = *RecordIterator; 353 ++RecordIterator; 354 if (Record.Name.empty()) 355 return error(instrprof_error::malformed); 356 return success(); 357 } 358