RawMemProfReader.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include <cstdint>
  13. #include <type_traits>
  14. #include "llvm/ProfileData/InstrProf.h"
  15. #include "llvm/ProfileData/MemProfData.inc"
  16. #include "llvm/ProfileData/RawMemProfReader.h"
  17. namespace llvm {
  18. namespace memprof {
  19. namespace {
  20. struct Summary {
  21. uint64_t Version;
  22. uint64_t TotalSizeBytes;
  23. uint64_t NumSegments;
  24. uint64_t NumMIBInfo;
  25. uint64_t NumStackOffsets;
  26. };
  27. template <class T = uint64_t> inline T alignedRead(const char *Ptr) {
  28. static_assert(std::is_pod<T>::value, "Not a pod type.");
  29. assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read");
  30. return *reinterpret_cast<const T *>(Ptr);
  31. }
  32. Summary computeSummary(const char *Start) {
  33. auto *H = reinterpret_cast<const Header *>(Start);
  34. // Check alignment while reading the number of items in each section.
  35. return Summary{
  36. H->Version,
  37. H->TotalSize,
  38. alignedRead(Start + H->SegmentOffset),
  39. alignedRead(Start + H->MIBOffset),
  40. alignedRead(Start + H->StackOffset),
  41. };
  42. }
  43. } // namespace
  44. Expected<std::unique_ptr<RawMemProfReader>>
  45. RawMemProfReader::create(const Twine &Path) {
  46. auto BufferOr = MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
  47. if (std::error_code EC = BufferOr.getError())
  48. return errorCodeToError(EC);
  49. std::unique_ptr<MemoryBuffer> Buffer(BufferOr.get().release());
  50. if (Buffer->getBufferSize() == 0)
  51. return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
  52. if (!RawMemProfReader::hasFormat(*Buffer))
  53. return make_error<InstrProfError>(instrprof_error::bad_magic);
  54. if (Buffer->getBufferSize() < sizeof(Header)) {
  55. return make_error<InstrProfError>(instrprof_error::truncated);
  56. }
  57. // The size of the buffer can be > header total size since we allow repeated
  58. // serialization of memprof profiles to the same file.
  59. uint64_t TotalSize = 0;
  60. const char *Next = Buffer->getBufferStart();
  61. while (Next < Buffer->getBufferEnd()) {
  62. auto *H = reinterpret_cast<const Header *>(Next);
  63. if (H->Version != MEMPROF_RAW_VERSION) {
  64. return make_error<InstrProfError>(instrprof_error::unsupported_version);
  65. }
  66. TotalSize += H->TotalSize;
  67. Next += H->TotalSize;
  68. }
  69. if (Buffer->getBufferSize() != TotalSize) {
  70. return make_error<InstrProfError>(instrprof_error::malformed);
  71. }
  72. return std::make_unique<RawMemProfReader>(std::move(Buffer));
  73. }
  74. bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) {
  75. if (Buffer.getBufferSize() < sizeof(uint64_t))
  76. return false;
  77. // Aligned read to sanity check that the buffer was allocated with at least 8b
  78. // alignment.
  79. const uint64_t Magic = alignedRead(Buffer.getBufferStart());
  80. return Magic == MEMPROF_RAW_MAGIC_64;
  81. }
  82. void RawMemProfReader::printSummaries(raw_ostream &OS) const {
  83. int Count = 0;
  84. const char *Next = DataBuffer->getBufferStart();
  85. while (Next < DataBuffer->getBufferEnd()) {
  86. auto Summary = computeSummary(Next);
  87. OS << "MemProf Profile " << ++Count << "\n";
  88. OS << " Version: " << Summary.Version << "\n";
  89. OS << " TotalSizeBytes: " << Summary.TotalSizeBytes << "\n";
  90. OS << " NumSegments: " << Summary.NumSegments << "\n";
  91. OS << " NumMIBInfo: " << Summary.NumMIBInfo << "\n";
  92. OS << " NumStackOffsets: " << Summary.NumStackOffsets << "\n";
  93. // TODO: Print the build ids once we can record them using the
  94. // sanitizer_procmaps library for linux.
  95. auto *H = reinterpret_cast<const Header *>(Next);
  96. Next += H->TotalSize;
  97. }
  98. }
  99. } // namespace memprof
  100. } // namespace llvm