Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | #ifndef LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ | 
| 2 | #define LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ | ||
| 3 | //===- MemProfReader.h - Instrumented memory profiling reader ---*- C++ -*-===// | ||
| 4 | // | ||
| 5 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 6 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 7 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 8 | // | ||
| 9 | //===----------------------------------------------------------------------===// | ||
| 10 | // | ||
| 11 | // This file contains support for reading MemProf profiling data. | ||
| 12 | // | ||
| 13 | //===----------------------------------------------------------------------===// | ||
| 14 | |||
| 15 | #include "llvm/ADT/DenseMap.h" | ||
| 16 | #include "llvm/ADT/MapVector.h" | ||
| 17 | #include "llvm/ADT/StringRef.h" | ||
| 18 | #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" | ||
| 19 | #include "llvm/DebugInfo/Symbolize/Symbolize.h" | ||
| 20 | #include "llvm/IR/GlobalValue.h" | ||
| 21 | #include "llvm/Object/Binary.h" | ||
| 22 | #include "llvm/Object/ObjectFile.h" | ||
| 23 | #include "llvm/ProfileData/InstrProfReader.h" | ||
| 24 | #include "llvm/ProfileData/MemProf.h" | ||
| 25 | #include "llvm/ProfileData/MemProfData.inc" | ||
| 26 | #include "llvm/Support/Error.h" | ||
| 27 | #include "llvm/Support/MemoryBuffer.h" | ||
| 28 | |||
| 29 | #include <cstddef> | ||
| 30 | |||
| 31 | namespace llvm { | ||
| 32 | namespace memprof { | ||
| 33 | |||
| 34 | // Map from id (recorded from sanitizer stack depot) to virtual addresses for | ||
| 35 | // each program counter address in the callstack. | ||
| 36 | using CallStackMap = llvm::DenseMap<uint64_t, llvm::SmallVector<uint64_t>>; | ||
| 37 | |||
| 38 | class RawMemProfReader { | ||
| 39 | public: | ||
| 40 | RawMemProfReader(const RawMemProfReader &) = delete; | ||
| 41 | RawMemProfReader &operator=(const RawMemProfReader &) = delete; | ||
| 42 | |||
| 43 |   // Prints the contents of the profile in YAML format. | ||
| 44 | void printYAML(raw_ostream &OS); | ||
| 45 | |||
| 46 |   // Return true if the \p DataBuffer starts with magic bytes indicating it is | ||
| 47 |   // a raw binary memprof profile. | ||
| 48 | static bool hasFormat(const MemoryBuffer &DataBuffer); | ||
| 49 |   // Return true if the file at \p Path starts with magic bytes indicating it is | ||
| 50 |   // a raw binary memprof profile. | ||
| 51 | static bool hasFormat(const StringRef Path); | ||
| 52 | |||
| 53 |   // Create a RawMemProfReader after sanity checking the contents of the file at | ||
| 54 |   // \p Path. The binary from which the profile has been collected is specified | ||
| 55 |   // via a path in \p ProfiledBinary. | ||
| 56 | static Expected<std::unique_ptr<RawMemProfReader>> | ||
| 57 | create(const Twine &Path, const StringRef ProfiledBinary, | ||
| 58 | bool KeepName = false); | ||
| 59 | |||
| 60 | using GuidMemProfRecordPair = std::pair<GlobalValue::GUID, MemProfRecord>; | ||
| 61 | using Iterator = InstrProfIterator<GuidMemProfRecordPair, RawMemProfReader>; | ||
| 62 | Iterator end() { return Iterator(); } | ||
| 63 | Iterator begin() { | ||
| 64 | Iter = FunctionProfileData.begin(); | ||
| 65 | return Iterator(this); | ||
| 66 |   } | ||
| 67 | |||
| 68 | Error readNextRecord(GuidMemProfRecordPair &GuidRecord); | ||
| 69 | |||
| 70 |   // The RawMemProfReader only holds memory profile information. | ||
| 71 | InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } | ||
| 72 | |||
| 73 |   // Constructor for unittests only. | ||
| 74 | RawMemProfReader(std::unique_ptr<llvm::symbolize::SymbolizableModule> Sym, | ||
| 75 | llvm::SmallVectorImpl<SegmentEntry> &Seg, | ||
| 76 | llvm::MapVector<uint64_t, MemInfoBlock> &Prof, | ||
| 77 | CallStackMap &SM, bool KeepName = false) | ||
| 78 | : Symbolizer(std::move(Sym)), SegmentInfo(Seg.begin(), Seg.end()), | ||
| 79 | CallstackProfileData(Prof), StackMap(SM), KeepSymbolName(KeepName) { | ||
| 80 |     // We don't call initialize here since there is no raw profile to read. The | ||
| 81 |     // test should pass in the raw profile as structured data. | ||
| 82 | |||
| 83 |     // If there is an error here then the mock symbolizer has not been | ||
| 84 |     // initialized properly. | ||
| 85 | if (Error E = symbolizeAndFilterStackFrames()) | ||
| 86 | report_fatal_error(std::move(E)); | ||
| 87 | if (Error E = mapRawProfileToRecords()) | ||
| 88 | report_fatal_error(std::move(E)); | ||
| 89 |   } | ||
| 90 | |||
| 91 |   // Return a const reference to the internal Id to Frame mappings. | ||
| 92 | const llvm::DenseMap<FrameId, Frame> &getFrameMapping() const { | ||
| 93 | return IdToFrame; | ||
| 94 |   } | ||
| 95 | |||
| 96 |   // Return a const reference to the internal function profile data. | ||
| 97 | const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> & | ||
| 98 | getProfileData() const { | ||
| 99 | return FunctionProfileData; | ||
| 100 |   } | ||
| 101 | |||
| 102 | private: | ||
| 103 | RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName) | ||
| 104 | : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} | ||
| 105 |   // Initializes the RawMemProfReader with the contents in `DataBuffer`. | ||
| 106 | Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer); | ||
| 107 |   // Read and parse the contents of the `DataBuffer` as a binary format profile. | ||
| 108 | Error readRawProfile(std::unique_ptr<MemoryBuffer> DataBuffer); | ||
| 109 |   // Symbolize and cache all the virtual addresses we encounter in the | ||
| 110 |   // callstacks from the raw profile. Also prune callstack frames which we can't | ||
| 111 |   // symbolize or those that belong to the runtime. For profile entries where | ||
| 112 |   // the entire callstack is pruned, we drop the entry from the profile. | ||
| 113 | Error symbolizeAndFilterStackFrames(); | ||
| 114 |   // Construct memprof records for each function and store it in the | ||
| 115 |   // `FunctionProfileData` map. A function may have allocation profile data or | ||
| 116 |   // callsite data or both. | ||
| 117 | Error mapRawProfileToRecords(); | ||
| 118 | |||
| 119 |   // A helper method to extract the frame from the IdToFrame map. | ||
| 120 | const Frame &idToFrame(const FrameId Id) const { | ||
| 121 | auto It = IdToFrame.find(Id); | ||
| 122 | assert(It != IdToFrame.end() && "Id not found in map."); | ||
| 123 | return It->getSecond(); | ||
| 124 |   } | ||
| 125 | |||
| 126 | object::SectionedAddress getModuleOffset(uint64_t VirtualAddress); | ||
| 127 | |||
| 128 | object::OwningBinary<object::Binary> Binary; | ||
| 129 | std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer; | ||
| 130 | |||
| 131 |   // The contents of the raw profile. | ||
| 132 | llvm::SmallVector<SegmentEntry, 16> SegmentInfo; | ||
| 133 |   // A map from callstack id (same as key in CallStackMap below) to the heap | ||
| 134 |   // information recorded for that allocation context. | ||
| 135 | llvm::MapVector<uint64_t, MemInfoBlock> CallstackProfileData; | ||
| 136 |   CallStackMap StackMap; | ||
| 137 | |||
| 138 |   // Cached symbolization from PC to Frame. | ||
| 139 | llvm::DenseMap<uint64_t, llvm::SmallVector<FrameId>> SymbolizedFrame; | ||
| 140 | llvm::DenseMap<FrameId, Frame> IdToFrame; | ||
| 141 | |||
| 142 | llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> FunctionProfileData; | ||
| 143 | llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord>::iterator Iter; | ||
| 144 | |||
| 145 |   // Whether to keep the symbol name for each frame after hashing. | ||
| 146 | bool KeepSymbolName = false; | ||
| 147 |   // A mapping of the hash to symbol name, only used if KeepSymbolName is true. | ||
| 148 | llvm::DenseMap<uint64_t, std::string> GuidToSymbolName; | ||
| 149 | }; | ||
| 150 | } // namespace memprof | ||
| 151 | } // namespace llvm | ||
| 152 | |||
| 153 | #endif // LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ |