aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp
new file mode 100644
index 000000000000..f8d13c74fac3
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp
@@ -0,0 +1,121 @@
+//===- RawMemProfReader.cpp - Instrumented memory profiling reader --------===//
+//
+// 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 <cstdint>
+#include <type_traits>
+
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/MemProfData.inc"
+#include "llvm/ProfileData/RawMemProfReader.h"
+
+namespace llvm {
+namespace memprof {
+namespace {
+
+struct Summary {
+ uint64_t Version;
+ uint64_t TotalSizeBytes;
+ uint64_t NumSegments;
+ uint64_t NumMIBInfo;
+ uint64_t NumStackOffsets;
+};
+
+template <class T = uint64_t> inline T alignedRead(const char *Ptr) {
+ static_assert(std::is_pod<T>::value, "Not a pod type.");
+ assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read");
+ return *reinterpret_cast<const T *>(Ptr);
+}
+
+Summary computeSummary(const char *Start) {
+ auto *H = reinterpret_cast<const Header *>(Start);
+
+ // Check alignment while reading the number of items in each section.
+ return Summary{
+ H->Version,
+ H->TotalSize,
+ alignedRead(Start + H->SegmentOffset),
+ alignedRead(Start + H->MIBOffset),
+ alignedRead(Start + H->StackOffset),
+ };
+}
+
+} // namespace
+
+Expected<std::unique_ptr<RawMemProfReader>>
+RawMemProfReader::create(const Twine &Path) {
+ auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
+ if (std::error_code EC = BufferOr.getError())
+ return errorCodeToError(EC);
+
+ std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release());
+
+ if (Buffer->getBufferSize() == 0)
+ return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
+
+ if (!RawMemProfReader::hasFormat(*Buffer))
+ return make_error<InstrProfError>(instrprof_error::bad_magic);
+
+ if (Buffer->getBufferSize() < sizeof(Header)) {
+ return make_error<InstrProfError>(instrprof_error::truncated);
+ }
+
+ // The size of the buffer can be > header total size since we allow repeated
+ // serialization of memprof profiles to the same file.
+ uint64_t TotalSize = 0;
+ const char *Next = Buffer->getBufferStart();
+ while (Next < Buffer->getBufferEnd()) {
+ auto *H = reinterpret_cast<const Header *>(Next);
+ if (H->Version != MEMPROF_RAW_VERSION) {
+ return make_error<InstrProfError>(instrprof_error::unsupported_version);
+ }
+
+ TotalSize += H->TotalSize;
+ Next += H->TotalSize;
+ }
+
+ if (Buffer->getBufferSize() != TotalSize) {
+ return make_error<InstrProfError>(instrprof_error::malformed);
+ }
+
+ return std::make_unique<RawMemProfReader>(std::move(Buffer));
+}
+
+bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) {
+ if (Buffer.getBufferSize() < sizeof(uint64_t))
+ return false;
+ // Aligned read to sanity check that the buffer was allocated with at least 8b
+ // alignment.
+ const uint64_t Magic = alignedRead(Buffer.getBufferStart());
+ return Magic == MEMPROF_RAW_MAGIC_64;
+}
+
+void RawMemProfReader::printSummaries(raw_ostream &OS) const {
+ int Count = 0;
+ const char *Next = DataBuffer->getBufferStart();
+ while (Next < DataBuffer->getBufferEnd()) {
+ auto Summary = computeSummary(Next);
+ OS << "MemProf Profile " << ++Count << "\n";
+ OS << " Version: " << Summary.Version << "\n";
+ OS << " TotalSizeBytes: " << Summary.TotalSizeBytes << "\n";
+ OS << " NumSegments: " << Summary.NumSegments << "\n";
+ OS << " NumMIBInfo: " << Summary.NumMIBInfo << "\n";
+ OS << " NumStackOffsets: " << Summary.NumStackOffsets << "\n";
+ // TODO: Print the build ids once we can record them using the
+ // sanitizer_procmaps library for linux.
+
+ auto *H = reinterpret_cast<const Header *>(Next);
+ Next += H->TotalSize;
+ }
+}
+
+} // namespace memprof
+} // namespace llvm