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_ |