[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / lib / ProfileData / RawMemProfReader.cpp
blobf8d13c74fac39177d68b0d818beadc078fe66949
1 //===- RawMemProfReader.cpp - Instrumented memory profiling reader --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for reading MemProf profiling data.
11 //===----------------------------------------------------------------------===//
13 #include <cstdint>
14 #include <type_traits>
16 #include "llvm/ProfileData/InstrProf.h"
17 #include "llvm/ProfileData/MemProfData.inc"
18 #include "llvm/ProfileData/RawMemProfReader.h"
20 namespace llvm {
21 namespace memprof {
22 namespace {
24 struct Summary {
25 uint64_t Version;
26 uint64_t TotalSizeBytes;
27 uint64_t NumSegments;
28 uint64_t NumMIBInfo;
29 uint64_t NumStackOffsets;
32 template <class T = uint64_t> inline T alignedRead(const char *Ptr) {
33 static_assert(std::is_pod<T>::value, "Not a pod type.");
34 assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read");
35 return *reinterpret_cast<const T *>(Ptr);
38 Summary computeSummary(const char *Start) {
39 auto *H = reinterpret_cast<const Header *>(Start);
41 // Check alignment while reading the number of items in each section.
42 return Summary{
43 H->Version,
44 H->TotalSize,
45 alignedRead(Start + H->SegmentOffset),
46 alignedRead(Start + H->MIBOffset),
47 alignedRead(Start + H->StackOffset),
51 } // namespace
53 Expected<std::unique_ptr<RawMemProfReader>>
54 RawMemProfReader::create(const Twine &Path) {
55 auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
56 if (std::error_code EC = BufferOr.getError())
57 return errorCodeToError(EC);
59 std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release());
61 if (Buffer->getBufferSize() == 0)
62 return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
64 if (!RawMemProfReader::hasFormat(*Buffer))
65 return make_error<InstrProfError>(instrprof_error::bad_magic);
67 if (Buffer->getBufferSize() < sizeof(Header)) {
68 return make_error<InstrProfError>(instrprof_error::truncated);
71 // The size of the buffer can be > header total size since we allow repeated
72 // serialization of memprof profiles to the same file.
73 uint64_t TotalSize = 0;
74 const char *Next = Buffer->getBufferStart();
75 while (Next < Buffer->getBufferEnd()) {
76 auto *H = reinterpret_cast<const Header *>(Next);
77 if (H->Version != MEMPROF_RAW_VERSION) {
78 return make_error<InstrProfError>(instrprof_error::unsupported_version);
81 TotalSize += H->TotalSize;
82 Next += H->TotalSize;
85 if (Buffer->getBufferSize() != TotalSize) {
86 return make_error<InstrProfError>(instrprof_error::malformed);
89 return std::make_unique<RawMemProfReader>(std::move(Buffer));
92 bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) {
93 if (Buffer.getBufferSize() < sizeof(uint64_t))
94 return false;
95 // Aligned read to sanity check that the buffer was allocated with at least 8b
96 // alignment.
97 const uint64_t Magic = alignedRead(Buffer.getBufferStart());
98 return Magic == MEMPROF_RAW_MAGIC_64;
101 void RawMemProfReader::printSummaries(raw_ostream &OS) const {
102 int Count = 0;
103 const char *Next = DataBuffer->getBufferStart();
104 while (Next < DataBuffer->getBufferEnd()) {
105 auto Summary = computeSummary(Next);
106 OS << "MemProf Profile " << ++Count << "\n";
107 OS << " Version: " << Summary.Version << "\n";
108 OS << " TotalSizeBytes: " << Summary.TotalSizeBytes << "\n";
109 OS << " NumSegments: " << Summary.NumSegments << "\n";
110 OS << " NumMIBInfo: " << Summary.NumMIBInfo << "\n";
111 OS << " NumStackOffsets: " << Summary.NumStackOffsets << "\n";
112 // TODO: Print the build ids once we can record them using the
113 // sanitizer_procmaps library for linux.
115 auto *H = reinterpret_cast<const Header *>(Next);
116 Next += H->TotalSize;
120 } // namespace memprof
121 } // namespace llvm