#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #ifndef LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ #define LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ //===- MemProfReader.h - Instrumented memory profiling reader ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains support for reading MemProf profiling data. // //===----------------------------------------------------------------------===// #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/IR/GlobalValue.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/MemProf.h" #include "llvm/ProfileData/MemProfData.inc" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include namespace llvm { namespace memprof { // Map from id (recorded from sanitizer stack depot) to virtual addresses for // each program counter address in the callstack. using CallStackMap = llvm::DenseMap>; class RawMemProfReader { public: RawMemProfReader(const RawMemProfReader &) = delete; RawMemProfReader &operator=(const RawMemProfReader &) = delete; // Prints the contents of the profile in YAML format. void printYAML(raw_ostream &OS); // Return true if the \p DataBuffer starts with magic bytes indicating it is // a raw binary memprof profile. static bool hasFormat(const MemoryBuffer &DataBuffer); // Return true if the file at \p Path starts with magic bytes indicating it is // a raw binary memprof profile. static bool hasFormat(const StringRef Path); // Create a RawMemProfReader after sanity checking the contents of the file at // \p Path. The binary from which the profile has been collected is specified // via a path in \p ProfiledBinary. static Expected> create(const Twine &Path, const StringRef ProfiledBinary, bool KeepName = false); using GuidMemProfRecordPair = std::pair; using Iterator = InstrProfIterator; Iterator end() { return Iterator(); } Iterator begin() { Iter = FunctionProfileData.begin(); return Iterator(this); } Error readNextRecord(GuidMemProfRecordPair &GuidRecord); // The RawMemProfReader only holds memory profile information. InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } // Constructor for unittests only. RawMemProfReader(std::unique_ptr Sym, llvm::SmallVectorImpl &Seg, llvm::MapVector &Prof, CallStackMap &SM, bool KeepName = false) : Symbolizer(std::move(Sym)), SegmentInfo(Seg.begin(), Seg.end()), CallstackProfileData(Prof), StackMap(SM), KeepSymbolName(KeepName) { // We don't call initialize here since there is no raw profile to read. The // test should pass in the raw profile as structured data. // If there is an error here then the mock symbolizer has not been // initialized properly. if (Error E = symbolizeAndFilterStackFrames()) report_fatal_error(std::move(E)); if (Error E = mapRawProfileToRecords()) report_fatal_error(std::move(E)); } // Return a const reference to the internal Id to Frame mappings. const llvm::DenseMap &getFrameMapping() const { return IdToFrame; } // Return a const reference to the internal function profile data. const llvm::MapVector & getProfileData() const { return FunctionProfileData; } private: RawMemProfReader(object::OwningBinary &&Bin, bool KeepName) : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} // Initializes the RawMemProfReader with the contents in `DataBuffer`. Error initialize(std::unique_ptr DataBuffer); // Read and parse the contents of the `DataBuffer` as a binary format profile. Error readRawProfile(std::unique_ptr DataBuffer); // Symbolize and cache all the virtual addresses we encounter in the // callstacks from the raw profile. Also prune callstack frames which we can't // symbolize or those that belong to the runtime. For profile entries where // the entire callstack is pruned, we drop the entry from the profile. Error symbolizeAndFilterStackFrames(); // Construct memprof records for each function and store it in the // `FunctionProfileData` map. A function may have allocation profile data or // callsite data or both. Error mapRawProfileToRecords(); // A helper method to extract the frame from the IdToFrame map. const Frame &idToFrame(const FrameId Id) const { auto It = IdToFrame.find(Id); assert(It != IdToFrame.end() && "Id not found in map."); return It->getSecond(); } object::SectionedAddress getModuleOffset(uint64_t VirtualAddress); object::OwningBinary Binary; std::unique_ptr Symbolizer; // The contents of the raw profile. llvm::SmallVector SegmentInfo; // A map from callstack id (same as key in CallStackMap below) to the heap // information recorded for that allocation context. llvm::MapVector CallstackProfileData; CallStackMap StackMap; // Cached symbolization from PC to Frame. llvm::DenseMap> SymbolizedFrame; llvm::DenseMap IdToFrame; llvm::MapVector FunctionProfileData; llvm::MapVector::iterator Iter; // Whether to keep the symbol name for each frame after hashing. bool KeepSymbolName = false; // A mapping of the hash to symbol name, only used if KeepSymbolName is true. llvm::DenseMap GuidToSymbolName; }; } // namespace memprof } // namespace llvm #endif // LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ #ifdef __GNUC__ #pragma GCC diagnostic pop #endif