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