diff options
-rw-r--r-- | llvm/include/llvm/ProfileData/MemProfReader.h | 214 | ||||
-rw-r--r-- | llvm/include/llvm/ProfileData/RawMemProfReader.h | 207 | ||||
-rw-r--r-- | llvm/lib/ProfileData/CMakeLists.txt | 2 | ||||
-rw-r--r-- | llvm/lib/ProfileData/MemProfReader.cpp (renamed from llvm/lib/ProfileData/RawMemProfReader.cpp) | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-profdata/llvm-profdata.cpp | 2 | ||||
-rw-r--r-- | llvm/unittests/ProfileData/MemProfTest.cpp | 2 | ||||
-rw-r--r-- | llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn | 2 |
7 files changed, 227 insertions, 208 deletions
diff --git a/llvm/include/llvm/ProfileData/MemProfReader.h b/llvm/include/llvm/ProfileData/MemProfReader.h new file mode 100644 index 0000000..89f49a2 --- /dev/null +++ b/llvm/include/llvm/ProfileData/MemProfReader.h @@ -0,0 +1,214 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_MEMPROFREADER_H_ +#define LLVM_PROFILEDATA_MEMPROFREADER_H_ + +#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 <functional> + +namespace llvm { +namespace memprof { +// A class for memprof profile data populated directly from external +// sources. +class MemProfReader { +public: + // The MemProfReader only holds memory profile information. + InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } + + using GuidMemProfRecordPair = std::pair<GlobalValue::GUID, MemProfRecord>; + using Iterator = InstrProfIterator<GuidMemProfRecordPair, MemProfReader>; + Iterator end() { return Iterator(); } + Iterator begin() { + Iter = FunctionProfileData.begin(); + return Iterator(this); + } + + // Return a const reference to the internal Id to Frame mappings. + const llvm::DenseMap<FrameId, Frame> &getFrameMapping() const { + return IdToFrame; + } + + // Return a const reference to the internal function profile data. + const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> & + getProfileData() const { + return FunctionProfileData; + } + + virtual Error + readNextRecord(GuidMemProfRecordPair &GuidRecord, + std::function<const Frame(const FrameId)> Callback = nullptr) { + if (FunctionProfileData.empty()) + return make_error<InstrProfError>(instrprof_error::empty_raw_profile); + + if (Iter == FunctionProfileData.end()) + return make_error<InstrProfError>(instrprof_error::eof); + + if (Callback == nullptr) + Callback = + std::bind(&MemProfReader::idToFrame, this, std::placeholders::_1); + + const IndexedMemProfRecord &IndexedRecord = Iter->second; + GuidRecord = {Iter->first, MemProfRecord(IndexedRecord, Callback)}; + Iter++; + return Error::success(); + } + + // Allow default construction for derived classes which can populate the + // contents after construction. + MemProfReader() = default; + virtual ~MemProfReader() = default; + + // Initialize the MemProfReader with the frame mappings and profile contents. + MemProfReader( + llvm::DenseMap<FrameId, Frame> FrameIdMap, + llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> ProfData) + : IdToFrame(std::move(FrameIdMap)), + FunctionProfileData(std::move(ProfData)) {} + +protected: + // 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(); + } + // A mapping from FrameId (a hash of the contents) to the frame. + llvm::DenseMap<FrameId, Frame> IdToFrame; + // A mapping from function GUID, hash of the canonical function symbol to the + // memprof profile data for that function, i.e allocation and callsite info. + llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> FunctionProfileData; + // An iterator to the internal function profile data structure. + llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord>::iterator Iter; +}; + +// Map from id (recorded from sanitizer stack depot) to virtual addresses for +// each program counter address in the callstack. +using CallStackMap = llvm::DenseMap<uint64_t, llvm::SmallVector<uint64_t>>; + +// Specializes the MemProfReader class to populate the contents from raw binary +// memprof profiles from instrumentation based profiling. +class RawMemProfReader final : public MemProfReader { +public: + RawMemProfReader(const RawMemProfReader &) = delete; + RawMemProfReader &operator=(const RawMemProfReader &) = delete; + virtual ~RawMemProfReader() override = default; + + // 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 or the \p Buffer. The binary from which the profile has been + // collected is specified via a path in \p ProfiledBinary. + static Expected<std::unique_ptr<RawMemProfReader>> + create(const Twine &Path, StringRef ProfiledBinary, bool KeepName = false); + static Expected<std::unique_ptr<RawMemProfReader>> + create(std::unique_ptr<MemoryBuffer> Buffer, StringRef ProfiledBinary, + bool KeepName = false); + + // Returns a list of build ids recorded in the segment information. + static std::vector<std::string> peekBuildIds(MemoryBuffer *DataBuffer); + + virtual Error + readNextRecord(GuidMemProfRecordPair &GuidRecord, + std::function<const Frame(const FrameId)> Callback) override; + + // Constructor for unittests only. + RawMemProfReader(std::unique_ptr<llvm::symbolize::SymbolizableModule> Sym, + llvm::SmallVectorImpl<SegmentEntry> &Seg, + llvm::MapVector<uint64_t, MemInfoBlock> &Prof, + CallStackMap &SM, bool KeepName = false) + : 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(std::move(Sym))) + report_fatal_error(std::move(E)); + if (Error E = mapRawProfileToRecords()) + report_fatal_error(std::move(E)); + } + +private: + RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName) + : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} + // Initializes the RawMemProfReader with the contents in `DataBuffer`. + Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer); + // Read and parse the contents of the `DataBuffer` as a binary format profile. + Error readRawProfile(std::unique_ptr<MemoryBuffer> DataBuffer); + // Initialize the segment mapping information for symbolization. + Error setupForSymbolization(); + // 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( + std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer); + // 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(); + + object::SectionedAddress getModuleOffset(uint64_t VirtualAddress); + + // The profiled binary. + object::OwningBinary<object::Binary> Binary; + // The preferred load address of the executable segment. + uint64_t PreferredTextSegmentAddress = 0; + // The base address of the text segment in the process during profiling. + uint64_t ProfiledTextSegmentStart = 0; + // The limit address of the text segment in the process during profiling. + uint64_t ProfiledTextSegmentEnd = 0; + + // The memory mapped segment information for all executable segments in the + // profiled binary (filtered from the raw profile using the build id). + llvm::SmallVector<SegmentEntry, 2> SegmentInfo; + + // A map from callstack id (same as key in CallStackMap below) to the heap + // information recorded for that allocation context. + llvm::MapVector<uint64_t, MemInfoBlock> CallstackProfileData; + CallStackMap StackMap; + + // Cached symbolization from PC to Frame. + llvm::DenseMap<uint64_t, llvm::SmallVector<FrameId>> SymbolizedFrame; + + // 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<uint64_t, std::string> GuidToSymbolName; +}; +} // namespace memprof +} // namespace llvm + +#endif // LLVM_PROFILEDATA_MEMPROFREADER_H_ diff --git a/llvm/include/llvm/ProfileData/RawMemProfReader.h b/llvm/include/llvm/ProfileData/RawMemProfReader.h index 6aa5cae..5e06f26 100644 --- a/llvm/include/llvm/ProfileData/RawMemProfReader.h +++ b/llvm/include/llvm/ProfileData/RawMemProfReader.h @@ -1,6 +1,4 @@ -#ifndef LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ -#define LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ -//===- MemProfReader.h - Instrumented memory profiling reader ---*- C++ -*-===// +//===- RawMemProfReader.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. @@ -8,207 +6,14 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for reading MemProf profiling data. +// This file just includes MemProfReader.h for compatibility with +// out-of-tree users. // //===----------------------------------------------------------------------===// -#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 <functional> - -namespace llvm { -namespace memprof { -// A class for memprof profile data populated directly from external -// sources. -// TODO: Rename this file to MemProfReader.h to better reflect the contents. -class MemProfReader { -public: - // The MemProfReader only holds memory profile information. - InstrProfKind getProfileKind() const { return InstrProfKind::MemProf; } - - using GuidMemProfRecordPair = std::pair<GlobalValue::GUID, MemProfRecord>; - using Iterator = InstrProfIterator<GuidMemProfRecordPair, MemProfReader>; - Iterator end() { return Iterator(); } - Iterator begin() { - Iter = FunctionProfileData.begin(); - return Iterator(this); - } - - // Return a const reference to the internal Id to Frame mappings. - const llvm::DenseMap<FrameId, Frame> &getFrameMapping() const { - return IdToFrame; - } - - // Return a const reference to the internal function profile data. - const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> & - getProfileData() const { - return FunctionProfileData; - } - - virtual Error - readNextRecord(GuidMemProfRecordPair &GuidRecord, - std::function<const Frame(const FrameId)> Callback = nullptr) { - if (FunctionProfileData.empty()) - return make_error<InstrProfError>(instrprof_error::empty_raw_profile); - - if (Iter == FunctionProfileData.end()) - return make_error<InstrProfError>(instrprof_error::eof); - - if (Callback == nullptr) - Callback = - std::bind(&MemProfReader::idToFrame, this, std::placeholders::_1); - - const IndexedMemProfRecord &IndexedRecord = Iter->second; - GuidRecord = {Iter->first, MemProfRecord(IndexedRecord, Callback)}; - Iter++; - return Error::success(); - } - - // Allow default construction for derived classes which can populate the - // contents after construction. - MemProfReader() = default; - virtual ~MemProfReader() = default; - - // Initialize the MemProfReader with the frame mappings and profile contents. - MemProfReader( - llvm::DenseMap<FrameId, Frame> FrameIdMap, - llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> ProfData) - : IdToFrame(std::move(FrameIdMap)), - FunctionProfileData(std::move(ProfData)) {} - -protected: - // 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(); - } - // A mapping from FrameId (a hash of the contents) to the frame. - llvm::DenseMap<FrameId, Frame> IdToFrame; - // A mapping from function GUID, hash of the canonical function symbol to the - // memprof profile data for that function, i.e allocation and callsite info. - llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> FunctionProfileData; - // An iterator to the internal function profile data structure. - llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord>::iterator Iter; -}; - -// Map from id (recorded from sanitizer stack depot) to virtual addresses for -// each program counter address in the callstack. -using CallStackMap = llvm::DenseMap<uint64_t, llvm::SmallVector<uint64_t>>; - -// Specializes the MemProfReader class to populate the contents from raw binary -// memprof profiles from instrumentation based profiling. -class RawMemProfReader final : public MemProfReader { -public: - RawMemProfReader(const RawMemProfReader &) = delete; - RawMemProfReader &operator=(const RawMemProfReader &) = delete; - virtual ~RawMemProfReader() override = default; - - // 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 or the \p Buffer. The binary from which the profile has been - // collected is specified via a path in \p ProfiledBinary. - static Expected<std::unique_ptr<RawMemProfReader>> - create(const Twine &Path, StringRef ProfiledBinary, bool KeepName = false); - static Expected<std::unique_ptr<RawMemProfReader>> - create(std::unique_ptr<MemoryBuffer> Buffer, StringRef ProfiledBinary, - bool KeepName = false); - - // Returns a list of build ids recorded in the segment information. - static std::vector<std::string> peekBuildIds(MemoryBuffer *DataBuffer); - - virtual Error - readNextRecord(GuidMemProfRecordPair &GuidRecord, - std::function<const Frame(const FrameId)> Callback) override; - - // Constructor for unittests only. - RawMemProfReader(std::unique_ptr<llvm::symbolize::SymbolizableModule> Sym, - llvm::SmallVectorImpl<SegmentEntry> &Seg, - llvm::MapVector<uint64_t, MemInfoBlock> &Prof, - CallStackMap &SM, bool KeepName = false) - : 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(std::move(Sym))) - report_fatal_error(std::move(E)); - if (Error E = mapRawProfileToRecords()) - report_fatal_error(std::move(E)); - } - -private: - RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName) - : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} - // Initializes the RawMemProfReader with the contents in `DataBuffer`. - Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer); - // Read and parse the contents of the `DataBuffer` as a binary format profile. - Error readRawProfile(std::unique_ptr<MemoryBuffer> DataBuffer); - // Initialize the segment mapping information for symbolization. - Error setupForSymbolization(); - // 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( - std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer); - // 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(); - - object::SectionedAddress getModuleOffset(uint64_t VirtualAddress); - - // The profiled binary. - object::OwningBinary<object::Binary> Binary; - // The preferred load address of the executable segment. - uint64_t PreferredTextSegmentAddress = 0; - // The base address of the text segment in the process during profiling. - uint64_t ProfiledTextSegmentStart = 0; - // The limit address of the text segment in the process during profiling. - uint64_t ProfiledTextSegmentEnd = 0; - - // The memory mapped segment information for all executable segments in the - // profiled binary (filtered from the raw profile using the build id). - llvm::SmallVector<SegmentEntry, 2> SegmentInfo; - - // A map from callstack id (same as key in CallStackMap below) to the heap - // information recorded for that allocation context. - llvm::MapVector<uint64_t, MemInfoBlock> CallstackProfileData; - CallStackMap StackMap; - - // Cached symbolization from PC to Frame. - llvm::DenseMap<uint64_t, llvm::SmallVector<FrameId>> SymbolizedFrame; +#ifndef LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ +#define LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ - // 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<uint64_t, std::string> GuidToSymbolName; -}; -} // namespace memprof -} // namespace llvm +#include "llvm/ProfileData/MemProfReader.h" #endif // LLVM_PROFILEDATA_RAWMEMPROFREADER_H_ diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 99617a4..408f9ff 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -6,8 +6,8 @@ add_llvm_component_library(LLVMProfileData InstrProfWriter.cpp ItaniumManglingCanonicalizer.cpp MemProf.cpp + MemProfReader.cpp ProfileSummaryBuilder.cpp - RawMemProfReader.cpp SampleProf.cpp SampleProfReader.cpp SampleProfWriter.cpp diff --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/MemProfReader.cpp index e93fbc7..4ccec26 100644 --- a/llvm/lib/ProfileData/RawMemProfReader.cpp +++ b/llvm/lib/ProfileData/MemProfReader.cpp @@ -32,7 +32,7 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/MemProf.h" #include "llvm/ProfileData/MemProfData.inc" -#include "llvm/ProfileData/RawMemProfReader.h" +#include "llvm/ProfileData/MemProfReader.h" #include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" @@ -295,8 +295,8 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) { // Check whether the profiled binary was built with position independent code // (PIC). Perform sanity checks for assumptions we rely on to simplify // symbolization. - auto* Elf64LEObject = llvm::cast<llvm::object::ELF64LEObjectFile>(ElfObject); - const llvm::object::ELF64LEFile& ElfFile = Elf64LEObject->getELFFile(); + auto *Elf64LEObject = llvm::cast<llvm::object::ELF64LEObjectFile>(ElfObject); + const llvm::object::ELF64LEFile &ElfFile = Elf64LEObject->getELFFile(); auto PHdrsOr = ElfFile.program_headers(); if (!PHdrsOr) return report( diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 0b78564..6a70773 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -19,8 +19,8 @@ #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/ProfileData/MemProf.h" +#include "llvm/ProfileData/MemProfReader.h" #include "llvm/ProfileData/ProfileCommon.h" -#include "llvm/ProfileData/RawMemProfReader.h" #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ProfileData/SampleProfWriter.h" #include "llvm/Support/BalancedPartitioning.h" diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp index f1aa6f3..9cf3074 100644 --- a/llvm/unittests/ProfileData/MemProfTest.cpp +++ b/llvm/unittests/ProfileData/MemProfTest.cpp @@ -6,7 +6,7 @@ #include "llvm/IR/Value.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ProfileData/MemProfData.inc" -#include "llvm/ProfileData/RawMemProfReader.h" +#include "llvm/ProfileData/MemProfReader.h" #include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn index 51568ac..9dbfe0f 100644 --- a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn @@ -16,8 +16,8 @@ static_library("ProfileData") { "InstrProfWriter.cpp", "ItaniumManglingCanonicalizer.cpp", "MemProf.cpp", + "MemProfReader.cpp", "ProfileSummaryBuilder.cpp", - "RawMemProfReader.cpp", "SampleProf.cpp", "SampleProfReader.cpp", "SampleProfWriter.cpp", |