diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-02 21:49:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:49 +0000 |
commit | 4824e7fd18a1223177218d4aec1b3c6c5c4a444e (patch) | |
tree | 5ca6493b1b0bf6a41f257794c0116d5e50fbf37c /contrib/llvm-project/llvm/lib/ProfileData | |
parent | 5e801ac66d24704442eba426ed13c3effb8a34e7 (diff) | |
parent | f65dcba83ce5035ab88a85fe17628b447eb56e1b (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData')
5 files changed, 127 insertions, 10 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 94bd4807041d..c6691e321b3c 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -83,7 +83,6 @@ Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { Error RawCoverageReader::readSize(uint64_t &Result) { if (auto Err = readULEB128(Result)) return Err; - // Sanity check the number. if (Result > Data.size()) return make_error<CoverageMapError>(coveragemap_error::malformed); return Error::success(); diff --git a/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp b/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp index 1168ad27fe52..ab3487ecffe8 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp @@ -657,19 +657,18 @@ void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input, Input.sortByTargetValues(); auto I = ValueData.begin(); auto IE = ValueData.end(); - for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE; - ++J) { - while (I != IE && I->Value < J->Value) + for (const InstrProfValueData &J : Input.ValueData) { + while (I != IE && I->Value < J.Value) ++I; - if (I != IE && I->Value == J->Value) { + if (I != IE && I->Value == J.Value) { bool Overflowed; - I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed); + I->Count = SaturatingMultiplyAdd(J.Count, Weight, I->Count, &Overflowed); if (Overflowed) Warn(instrprof_error::counter_overflow); ++I; continue; } - ValueData.insert(I, *J); + ValueData.insert(I, J); } } diff --git a/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp index b4e8025dbef9..885c1fe49240 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp @@ -62,7 +62,6 @@ InstrProfReader::create(const Twine &Path) { Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { - // Sanity check the buffer. if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max()) return make_error<InstrProfError>(instrprof_error::too_large); @@ -113,7 +112,6 @@ IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) { Expected<std::unique_ptr<IndexedInstrProfReader>> IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer, std::unique_ptr<MemoryBuffer> RemappingBuffer) { - // Sanity check the buffer. if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max()) return make_error<InstrProfError>(instrprof_error::too_large); 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 diff --git a/contrib/llvm-project/llvm/lib/ProfileData/SampleProfReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/SampleProfReader.cpp index c99a19020511..eefb7c2ba627 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/SampleProfReader.cpp @@ -1709,7 +1709,7 @@ setupMemoryBuffer(const Twine &Filename) { return EC; auto Buffer = std::move(BufferOrErr.get()); - // Sanity check the file. + // Check the file. if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint32_t>::max()) return sampleprof_error::too_large; |