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