1 //===- RawMemProfReader.cpp - Instrumented memory profiling reader --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for reading MemProf profiling data. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include <cstdint> 14 #include <type_traits> 15 16 #include "llvm/ProfileData/InstrProf.h" 17 #include "llvm/ProfileData/MemProfData.inc" 18 #include "llvm/ProfileData/RawMemProfReader.h" 19 20 namespace llvm { 21 namespace memprof { 22 namespace { 23 24 struct Summary { 25 uint64_t Version; 26 uint64_t TotalSizeBytes; 27 uint64_t NumSegments; 28 uint64_t NumMIBInfo; 29 uint64_t NumStackOffsets; 30 }; 31 32 template <class T = uint64_t> inline T alignedRead(const char *Ptr) { 33 static_assert(std::is_pod<T>::value, "Not a pod type."); 34 assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read"); 35 return *reinterpret_cast<const T *>(Ptr); 36 } 37 38 Summary computeSummary(const char *Start) { 39 auto *H = reinterpret_cast<const Header *>(Start); 40 41 // Check alignment while reading the number of items in each section. 42 return Summary{ 43 H->Version, 44 H->TotalSize, 45 alignedRead(Start + H->SegmentOffset), 46 alignedRead(Start + H->MIBOffset), 47 alignedRead(Start + H->StackOffset), 48 }; 49 } 50 51 } // namespace 52 53 Expected<std::unique_ptr<RawMemProfReader>> 54 RawMemProfReader::create(const Twine &Path) { 55 auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true); 56 if (std::error_code EC = BufferOr.getError()) 57 return errorCodeToError(EC); 58 59 std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release()); 60 61 if (Buffer->getBufferSize() == 0) 62 return make_error<InstrProfError>(instrprof_error::empty_raw_profile); 63 64 if (!RawMemProfReader::hasFormat(*Buffer)) 65 return make_error<InstrProfError>(instrprof_error::bad_magic); 66 67 if (Buffer->getBufferSize() < sizeof(Header)) { 68 return make_error<InstrProfError>(instrprof_error::truncated); 69 } 70 71 // The size of the buffer can be > header total size since we allow repeated 72 // serialization of memprof profiles to the same file. 73 uint64_t TotalSize = 0; 74 const char *Next = Buffer->getBufferStart(); 75 while (Next < Buffer->getBufferEnd()) { 76 auto *H = reinterpret_cast<const Header *>(Next); 77 if (H->Version != MEMPROF_RAW_VERSION) { 78 return make_error<InstrProfError>(instrprof_error::unsupported_version); 79 } 80 81 TotalSize += H->TotalSize; 82 Next += H->TotalSize; 83 } 84 85 if (Buffer->getBufferSize() != TotalSize) { 86 return make_error<InstrProfError>(instrprof_error::malformed); 87 } 88 89 return std::make_unique<RawMemProfReader>(std::move(Buffer)); 90 } 91 92 bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) { 93 if (Buffer.getBufferSize() < sizeof(uint64_t)) 94 return false; 95 // Aligned read to sanity check that the buffer was allocated with at least 8b 96 // alignment. 97 const uint64_t Magic = alignedRead(Buffer.getBufferStart()); 98 return Magic == MEMPROF_RAW_MAGIC_64; 99 } 100 101 void RawMemProfReader::printSummaries(raw_ostream &OS) const { 102 int Count = 0; 103 const char *Next = DataBuffer->getBufferStart(); 104 while (Next < DataBuffer->getBufferEnd()) { 105 auto Summary = computeSummary(Next); 106 OS << "MemProf Profile " << ++Count << "\n"; 107 OS << " Version: " << Summary.Version << "\n"; 108 OS << " TotalSizeBytes: " << Summary.TotalSizeBytes << "\n"; 109 OS << " NumSegments: " << Summary.NumSegments << "\n"; 110 OS << " NumMIBInfo: " << Summary.NumMIBInfo << "\n"; 111 OS << " NumStackOffsets: " << Summary.NumStackOffsets << "\n"; 112 // TODO: Print the build ids once we can record them using the 113 // sanitizer_procmaps library for linux. 114 115 auto *H = reinterpret_cast<const Header *>(Next); 116 Next += H->TotalSize; 117 } 118 } 119 120 } // namespace memprof 121 } // namespace llvm 122