Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:24

0001 //===- MemProfReader.h - Instrumented memory profiling reader ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains support for reading MemProf profiling data.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_PROFILEDATA_MEMPROFREADER_H_
0014 #define LLVM_PROFILEDATA_MEMPROFREADER_H_
0015 
0016 #include "llvm/ADT/DenseMap.h"
0017 #include "llvm/ADT/MapVector.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
0020 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
0021 #include "llvm/IR/GlobalValue.h"
0022 #include "llvm/Object/Binary.h"
0023 #include "llvm/Object/ObjectFile.h"
0024 #include "llvm/ProfileData/InstrProfReader.h"
0025 #include "llvm/ProfileData/MemProf.h"
0026 #include "llvm/ProfileData/MemProfData.inc"
0027 #include "llvm/Support/Error.h"
0028 #include "llvm/Support/MemoryBuffer.h"
0029 
0030 #include <functional>
0031 
0032 namespace llvm {
0033 namespace memprof {
0034 // A class for memprof profile data populated directly from external
0035 // sources.
0036 class MemProfReader {
0037 public:
0038   // The MemProfReader only holds memory profile information.
0039   InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; }
0040 
0041   using GuidMemProfRecordPair = std::pair<GlobalValue::GUID, MemProfRecord>;
0042   using Iterator = InstrProfIterator<GuidMemProfRecordPair, MemProfReader>;
0043   Iterator end() { return Iterator(); }
0044   Iterator begin() {
0045     Iter = MemProfData.Records.begin();
0046     return Iterator(this);
0047   }
0048 
0049   // Take the complete profile data.  Once this function is invoked,
0050   // MemProfReader no longer owns the MemProf profile.
0051   IndexedMemProfData takeMemProfData() { return std::move(MemProfData); }
0052 
0053   virtual Error
0054   readNextRecord(GuidMemProfRecordPair &GuidRecord,
0055                  std::function<const Frame(const FrameId)> Callback = nullptr) {
0056     if (MemProfData.Records.empty())
0057       return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
0058 
0059     if (Iter == MemProfData.Records.end())
0060       return make_error<InstrProfError>(instrprof_error::eof);
0061 
0062     if (Callback == nullptr)
0063       Callback =
0064           std::bind(&MemProfReader::idToFrame, this, std::placeholders::_1);
0065 
0066     CallStackIdConverter<decltype(MemProfData.CallStacks)> CSIdConv(
0067         MemProfData.CallStacks, Callback);
0068 
0069     const IndexedMemProfRecord &IndexedRecord = Iter->second;
0070     GuidRecord = {
0071         Iter->first,
0072         IndexedRecord.toMemProfRecord(CSIdConv),
0073     };
0074     if (CSIdConv.LastUnmappedId)
0075       return make_error<InstrProfError>(instrprof_error::hash_mismatch);
0076     Iter++;
0077     return Error::success();
0078   }
0079 
0080   // Allow default construction for derived classes which can populate the
0081   // contents after construction.
0082   MemProfReader() = default;
0083   virtual ~MemProfReader() = default;
0084 
0085   // Initialize the MemProfReader with the given MemProf profile.
0086   MemProfReader(IndexedMemProfData &&MemProfData)
0087       : MemProfData(std::move(MemProfData)) {}
0088 
0089 protected:
0090   // A helper method to extract the frame from the IdToFrame map.
0091   const Frame &idToFrame(const FrameId Id) const {
0092     auto It = MemProfData.Frames.find(Id);
0093     assert(It != MemProfData.Frames.end() && "Id not found in map.");
0094     return It->second;
0095   }
0096   // A complete pacakge of the MemProf profile.
0097   IndexedMemProfData MemProfData;
0098   // An iterator to the internal function profile data structure.
0099   llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord>::iterator Iter;
0100 };
0101 
0102 // Map from id (recorded from sanitizer stack depot) to virtual addresses for
0103 // each program counter address in the callstack.
0104 using CallStackMap = llvm::DenseMap<uint64_t, llvm::SmallVector<uint64_t>>;
0105 
0106 // Specializes the MemProfReader class to populate the contents from raw binary
0107 // memprof profiles from instrumentation based profiling.
0108 class RawMemProfReader final : public MemProfReader {
0109 public:
0110   RawMemProfReader(const RawMemProfReader &) = delete;
0111   RawMemProfReader &operator=(const RawMemProfReader &) = delete;
0112   virtual ~RawMemProfReader() override;
0113 
0114   // Prints the contents of the profile in YAML format.
0115   void printYAML(raw_ostream &OS);
0116 
0117   // Return true if the \p DataBuffer starts with magic bytes indicating it is
0118   // a raw binary memprof profile.
0119   static bool hasFormat(const MemoryBuffer &DataBuffer);
0120   // Return true if the file at \p Path starts with magic bytes indicating it is
0121   // a raw binary memprof profile.
0122   static bool hasFormat(const StringRef Path);
0123 
0124   // Create a RawMemProfReader after sanity checking the contents of the file at
0125   // \p Path or the \p Buffer. The binary from which the profile has been
0126   // collected is specified via a path in \p ProfiledBinary.
0127   static Expected<std::unique_ptr<RawMemProfReader>>
0128   create(const Twine &Path, StringRef ProfiledBinary, bool KeepName = false);
0129   static Expected<std::unique_ptr<RawMemProfReader>>
0130   create(std::unique_ptr<MemoryBuffer> Buffer, StringRef ProfiledBinary,
0131          bool KeepName = false);
0132 
0133   // Returns a list of build ids recorded in the segment information.
0134   static std::vector<std::string> peekBuildIds(MemoryBuffer *DataBuffer);
0135 
0136   Error
0137   readNextRecord(GuidMemProfRecordPair &GuidRecord,
0138                  std::function<const Frame(const FrameId)> Callback) override;
0139 
0140   // Constructor for unittests only.
0141   RawMemProfReader(std::unique_ptr<llvm::symbolize::SymbolizableModule> Sym,
0142                    llvm::SmallVectorImpl<SegmentEntry> &Seg,
0143                    llvm::MapVector<uint64_t, MemInfoBlock> &Prof,
0144                    CallStackMap &SM, bool KeepName = false)
0145       : SegmentInfo(Seg.begin(), Seg.end()), CallstackProfileData(Prof),
0146         StackMap(SM), KeepSymbolName(KeepName) {
0147     // We don't call initialize here since there is no raw profile to read. The
0148     // test should pass in the raw profile as structured data.
0149 
0150     // If there is an error here then the mock symbolizer has not been
0151     // initialized properly.
0152     if (Error E = symbolizeAndFilterStackFrames(std::move(Sym)))
0153       report_fatal_error(std::move(E));
0154     if (Error E = mapRawProfileToRecords())
0155       report_fatal_error(std::move(E));
0156   }
0157 
0158 private:
0159   RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName)
0160       : Binary(std::move(Bin)), KeepSymbolName(KeepName) {}
0161   // Initializes the RawMemProfReader with the contents in `DataBuffer`.
0162   Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer);
0163   // Read and parse the contents of the `DataBuffer` as a binary format profile.
0164   Error readRawProfile(std::unique_ptr<MemoryBuffer> DataBuffer);
0165   // Initialize the segment mapping information for symbolization.
0166   Error setupForSymbolization();
0167   // Symbolize and cache all the virtual addresses we encounter in the
0168   // callstacks from the raw profile. Also prune callstack frames which we can't
0169   // symbolize or those that belong to the runtime. For profile entries where
0170   // the entire callstack is pruned, we drop the entry from the profile.
0171   Error symbolizeAndFilterStackFrames(
0172       std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer);
0173   // Construct memprof records for each function and store it in the
0174   // `FunctionProfileData` map. A function may have allocation profile data or
0175   // callsite data or both.
0176   Error mapRawProfileToRecords();
0177 
0178   object::SectionedAddress getModuleOffset(uint64_t VirtualAddress);
0179 
0180   llvm::SmallVector<std::pair<uint64_t, MemInfoBlock>>
0181   readMemInfoBlocks(const char *Ptr);
0182 
0183   // The profiled binary.
0184   object::OwningBinary<object::Binary> Binary;
0185   // Version of raw memprof binary currently being read. Defaults to most up
0186   // to date version.
0187   uint64_t MemprofRawVersion = MEMPROF_RAW_VERSION;
0188   // The preferred load address of the executable segment.
0189   uint64_t PreferredTextSegmentAddress = 0;
0190   // The base address of the text segment in the process during profiling.
0191   uint64_t ProfiledTextSegmentStart = 0;
0192   // The limit address of the text segment in the process during profiling.
0193   uint64_t ProfiledTextSegmentEnd = 0;
0194 
0195   // The memory mapped segment information for all executable segments in the
0196   // profiled binary (filtered from the raw profile using the build id).
0197   llvm::SmallVector<SegmentEntry, 2> SegmentInfo;
0198 
0199   // A map from callstack id (same as key in CallStackMap below) to the heap
0200   // information recorded for that allocation context.
0201   llvm::MapVector<uint64_t, MemInfoBlock> CallstackProfileData;
0202   CallStackMap StackMap;
0203 
0204   // Cached symbolization from PC to Frame.
0205   llvm::DenseMap<uint64_t, llvm::SmallVector<FrameId>> SymbolizedFrame;
0206 
0207   // Whether to keep the symbol name for each frame after hashing.
0208   bool KeepSymbolName = false;
0209   // A mapping of the hash to symbol name, only used if KeepSymbolName is true.
0210   llvm::DenseMap<uint64_t, std::string> GuidToSymbolName;
0211 };
0212 
0213 class YAMLMemProfReader final : public MemProfReader {
0214 public:
0215   YAMLMemProfReader() = default;
0216 
0217   // Return true if the \p DataBuffer starts with "---" indicating it is a YAML
0218   // file.
0219   static bool hasFormat(const MemoryBuffer &DataBuffer);
0220   // Wrapper around hasFormat above, reading the file instead of the memory
0221   // buffer.
0222   static bool hasFormat(const StringRef Path);
0223 
0224   // Create a YAMLMemProfReader after sanity checking the contents of the file
0225   // at \p Path or the \p Buffer.
0226   static Expected<std::unique_ptr<YAMLMemProfReader>> create(const Twine &Path);
0227   static Expected<std::unique_ptr<YAMLMemProfReader>>
0228   create(std::unique_ptr<MemoryBuffer> Buffer);
0229 
0230   void parse(StringRef YAMLData);
0231 };
0232 } // namespace memprof
0233 } // namespace llvm
0234 
0235 #endif // LLVM_PROFILEDATA_MEMPROFREADER_H_