This revision was automatically updated to reflect the committed changes.
labath marked an inline comment as done.
Closed by commit rG6e0b1ce48e3c: Object/minidump: Add support for the 
MemoryInfoList stream (authored by labath).
Herald added a subscriber: hiraditya.

Changed prior to commit:
  https://reviews.llvm.org/D68210?vs=223816&id=223850#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68210/new/

https://reviews.llvm.org/D68210

Files:
  llvm/include/llvm/BinaryFormat/Minidump.h
  llvm/include/llvm/BinaryFormat/MinidumpConstants.def
  llvm/include/llvm/Object/Minidump.h
  llvm/lib/Object/Minidump.cpp
  llvm/unittests/Object/MinidumpTest.cpp

Index: llvm/unittests/Object/MinidumpTest.cpp
===================================================================
--- llvm/unittests/Object/MinidumpTest.cpp
+++ llvm/unittests/Object/MinidumpTest.cpp
@@ -511,3 +511,202 @@
     EXPECT_EQ(0x00090807u, MD.Memory.RVA);
   }
 }
+
+TEST(MinidumpFile, getMemoryInfoList) {
+  std::vector<uint8_t> OneEntry{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 64, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
+      // MemoryInfo
+      0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
+      8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
+      16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
+      0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
+      0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
+      0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
+  };
+
+  // Same as before, but the list header is larger.
+  std::vector<uint8_t> BiggerHeader{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 68, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      20, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
+      0, 0, 0, 0,               // ???
+      // MemoryInfo
+      0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
+      8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
+      16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
+      0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
+      0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
+      0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
+  };
+
+  // Same as before, but the entry is larger.
+  std::vector<uint8_t> BiggerEntry{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 68, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      16, 0, 0, 0, 52, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
+      // MemoryInfo
+      0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
+      8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
+      16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
+      0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
+      0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
+      0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
+      0, 0, 0, 0,               // ???
+  };
+
+  for (ArrayRef<uint8_t> Data : {OneEntry, BiggerHeader, BiggerEntry}) {
+    auto ExpectedFile = create(Data);
+    ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+    const MinidumpFile &File = **ExpectedFile;
+    auto ExpectedInfo = File.getMemoryInfoList();
+    ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
+    ASSERT_EQ(1u, std::distance(ExpectedInfo->begin(), ExpectedInfo->end()));
+    const MemoryInfo &Info = *ExpectedInfo.get().begin();
+    EXPECT_EQ(0x0706050403020100u, Info.BaseAddress);
+    EXPECT_EQ(0x0504030201000908u, Info.AllocationBase);
+    EXPECT_EQ(MemoryProtection::Execute, Info.AllocationProtect);
+    EXPECT_EQ(0x09080706u, Info.Reserved0);
+    EXPECT_EQ(0x0706050403020100u, Info.RegionSize);
+    EXPECT_EQ(MemoryState::Commit, Info.State);
+    EXPECT_EQ(MemoryProtection::ExecuteRead, Info.Protect);
+    EXPECT_EQ(MemoryType::Private, Info.Type);
+    EXPECT_EQ(0x01000908u, Info.Reserved1);
+  }
+
+  // Header does not fit into the stream.
+  std::vector<uint8_t> HeaderTooBig{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 15, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0,      // ???
+  };
+  Expected<std::unique_ptr<MinidumpFile>> File = create(HeaderTooBig);
+  ASSERT_THAT_EXPECTED(File, Succeeded());
+  EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
+
+  // Header fits into the stream, but it is too small to contain the required
+  // entries.
+  std::vector<uint8_t> HeaderTooSmall{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 15, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      15, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0,      // ???
+  };
+  File = create(HeaderTooSmall);
+  ASSERT_THAT_EXPECTED(File, Succeeded());
+  EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
+
+  std::vector<uint8_t> EntryTooBig{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 64, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      16, 0, 0, 0, 49, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
+      // MemoryInfo
+      0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
+      8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
+      16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
+      0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
+      0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
+      0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
+  };
+  File = create(EntryTooBig);
+  ASSERT_THAT_EXPECTED(File, Succeeded());
+  EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
+
+  std::vector<uint8_t> ThreeEntries{
+      // Header
+      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
+      1, 0, 0, 0,                           // NumberOfStreams,
+      32, 0, 0, 0,                          // StreamDirectoryRVA
+      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
+      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
+                                            // Stream Directory
+      16, 0, 0, 0, 160, 0, 0, 0,            // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // MemoryInfoListHeader
+      16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
+      3, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
+      // MemoryInfo
+      0, 1, 2, 3, 0, 0, 0, 0, // BaseAddress
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
+      0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
+      0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
+      0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
+      0, 0, 4, 5, 6, 7, 0, 0, // BaseAddress
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
+      0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
+      0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
+      0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
+      0, 0, 0, 8, 9, 0, 1, 0, // BaseAddress
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
+      0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
+      0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
+      0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
+      0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
+  };
+  File = create(ThreeEntries);
+  ASSERT_THAT_EXPECTED(File, Succeeded());
+  auto ExpectedInfo = File.get()->getMemoryInfoList();
+  ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
+  EXPECT_THAT(to_vector<3>(map_range(*ExpectedInfo,
+                                     [](const MemoryInfo &Info) -> uint64_t {
+                                       return Info.BaseAddress;
+                                     })),
+              testing::ElementsAre(0x0000000003020100u, 0x0000070605040000u,
+                                   0x0001000908000000u));
+}
Index: llvm/lib/Object/Minidump.cpp
===================================================================
--- llvm/lib/Object/Minidump.cpp
+++ llvm/lib/Object/Minidump.cpp
@@ -53,13 +53,30 @@
   return Result;
 }
 
+Expected<iterator_range<MinidumpFile::MemoryInfoIterator>>
+MinidumpFile::getMemoryInfoList() const {
+  Optional<ArrayRef<uint8_t>> Stream = getRawStream(StreamType::MemoryInfoList);
+  if (!Stream)
+    return createError("No such stream");
+  auto ExpectedHeader =
+      getDataSliceAs<minidump::MemoryInfoListHeader>(*Stream, 0, 1);
+  if (!ExpectedHeader)
+    return ExpectedHeader.takeError();
+  const minidump::MemoryInfoListHeader &H = ExpectedHeader.get()[0];
+  Expected<ArrayRef<uint8_t>> Data =
+      getDataSlice(*Stream, H.SizeOfHeader, H.SizeOfEntry * H.NumberOfEntries);
+  if (!Data)
+    return Data.takeError();
+  return make_range(MemoryInfoIterator(*Data, H.SizeOfEntry),
+                    MemoryInfoIterator({}, H.SizeOfEntry));
+}
+
 template <typename T>
-Expected<ArrayRef<T>> MinidumpFile::getListStream(StreamType Stream) const {
-  auto OptionalStream = getRawStream(Stream);
-  if (!OptionalStream)
+Expected<ArrayRef<T>> MinidumpFile::getListStream(StreamType Type) const {
+  Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type);
+  if (!Stream)
     return createError("No such stream");
-  auto ExpectedSize =
-      getDataSliceAs<support::ulittle32_t>(*OptionalStream, 0, 1);
+  auto ExpectedSize = getDataSliceAs<support::ulittle32_t>(*Stream, 0, 1);
   if (!ExpectedSize)
     return ExpectedSize.takeError();
 
@@ -69,10 +86,10 @@
   // Some producers insert additional padding bytes to align the list to an
   // 8-byte boundary. Check for that by comparing the list size with the overall
   // stream size.
-  if (ListOffset + sizeof(T) * ListSize < OptionalStream->size())
+  if (ListOffset + sizeof(T) * ListSize < Stream->size())
     ListOffset = 8;
 
-  return getDataSliceAs<T>(*OptionalStream, ListOffset, ListSize);
+  return getDataSliceAs<T>(*Stream, ListOffset, ListSize);
 }
 template Expected<ArrayRef<Module>>
     MinidumpFile::getListStream(StreamType) const;
@@ -109,13 +126,14 @@
     return ExpectedStreams.takeError();
 
   DenseMap<StreamType, std::size_t> StreamMap;
-  for (const auto &Stream : llvm::enumerate(*ExpectedStreams)) {
-    StreamType Type = Stream.value().Type;
-    const LocationDescriptor &Loc = Stream.value().Location;
+  for (const auto &StreamDescriptor : llvm::enumerate(*ExpectedStreams)) {
+    StreamType Type = StreamDescriptor.value().Type;
+    const LocationDescriptor &Loc = StreamDescriptor.value().Location;
 
-    auto ExpectedStream = getDataSlice(Data, Loc.RVA, Loc.DataSize);
-    if (!ExpectedStream)
-      return ExpectedStream.takeError();
+    Expected<ArrayRef<uint8_t>> Stream =
+        getDataSlice(Data, Loc.RVA, Loc.DataSize);
+    if (!Stream)
+      return Stream.takeError();
 
     if (Type == StreamType::Unused && Loc.DataSize == 0) {
       // Ignore dummy streams. This is technically ill-formed, but a number of
@@ -128,7 +146,7 @@
       return createError("Cannot handle one of the minidump streams");
 
     // Update the directory map, checking for duplicate stream types.
-    if (!StreamMap.try_emplace(Type, Stream.index()).second)
+    if (!StreamMap.try_emplace(Type, StreamDescriptor.index()).second)
       return createError("Duplicate stream type");
   }
 
Index: llvm/include/llvm/Object/Minidump.h
===================================================================
--- llvm/include/llvm/Object/Minidump.h
+++ llvm/include/llvm/Object/Minidump.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/iterator.h"
 #include "llvm/BinaryFormat/Minidump.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Support/Error.h"
@@ -80,16 +81,56 @@
     return getListStream<minidump::Thread>(minidump::StreamType::ThreadList);
   }
 
-  /// Returns the list of memory ranges embedded in the MemoryList stream. An
-  /// error is returned if the file does not contain this stream, or if the
-  /// stream is not large enough to contain the number of memory descriptors
-  /// declared in the stream header. The consistency of the MemoryDescriptor
-  /// entries themselves is not checked in any way.
+  /// Returns the list of descriptors embedded in the MemoryList stream. The
+  /// descriptors provide the content of interesting regions of memory at the
+  /// time the minidump was taken. An error is returned if the file does not
+  /// contain this stream, or if the stream is not large enough to contain the
+  /// number of memory descriptors declared in the stream header. The
+  /// consistency of the MemoryDescriptor entries themselves is not checked in
+  /// any way.
   Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const {
     return getListStream<minidump::MemoryDescriptor>(
         minidump::StreamType::MemoryList);
   }
 
+  class MemoryInfoIterator
+      : public iterator_facade_base<MemoryInfoIterator,
+                                    std::forward_iterator_tag,
+                                    minidump::MemoryInfo> {
+  public:
+    MemoryInfoIterator(ArrayRef<uint8_t> Storage, size_t Stride)
+        : Storage(Storage), Stride(Stride) {
+      assert(Storage.size() % Stride == 0);
+    }
+
+    bool operator==(const MemoryInfoIterator &R) const {
+      return Storage.size() == R.Storage.size();
+    }
+
+    const minidump::MemoryInfo &operator*() const {
+      assert(Storage.size() >= sizeof(minidump::MemoryInfo));
+      return *reinterpret_cast<const minidump::MemoryInfo *>(Storage.data());
+    }
+
+    MemoryInfoIterator &operator++() {
+      Storage = Storage.drop_front(Stride);
+      return *this;
+    }
+
+  private:
+    ArrayRef<uint8_t> Storage;
+    size_t Stride;
+  };
+
+  /// Returns the list of descriptors embedded in the MemoryInfoList stream. The
+  /// descriptors provide properties (e.g. permissions) of interesting regions
+  /// of memory at the time the minidump was taken. An error is returned if the
+  /// file does not contain this stream, or if the stream is not large enough to
+  /// contain the number of memory descriptors declared in the stream header.
+  /// The consistency of the MemoryInfoList entries themselves is not checked
+  /// in any way.
+  Expected<iterator_range<MemoryInfoIterator>> getMemoryInfoList() const;
+
 private:
   static Error createError(StringRef Str) {
     return make_error<GenericBinaryError>(Str, object_error::parse_failed);
@@ -137,10 +178,10 @@
 };
 
 template <typename T>
-Expected<const T &> MinidumpFile::getStream(minidump::StreamType Stream) const {
-  if (auto OptionalStream = getRawStream(Stream)) {
-    if (OptionalStream->size() >= sizeof(T))
-      return *reinterpret_cast<const T *>(OptionalStream->data());
+Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const {
+  if (Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type)) {
+    if (Stream->size() >= sizeof(T))
+      return *reinterpret_cast<const T *>(Stream->data());
     return createEOFError();
   }
   return createError("No such stream");
@@ -153,10 +194,11 @@
   // Check for overflow.
   if (Count > std::numeric_limits<size_t>::max() / sizeof(T))
     return createEOFError();
-  auto ExpectedArray = getDataSlice(Data, Offset, sizeof(T) * Count);
-  if (!ExpectedArray)
-    return ExpectedArray.takeError();
-  return ArrayRef<T>(reinterpret_cast<const T *>(ExpectedArray->data()), Count);
+  Expected<ArrayRef<uint8_t>> Slice =
+      getDataSlice(Data, Offset, sizeof(T) * Count);
+  if (!Slice)
+    return Slice.takeError();
+  return ArrayRef<T>(reinterpret_cast<const T *>(Slice->data()), Count);
 }
 
 } // end namespace object
Index: llvm/include/llvm/BinaryFormat/MinidumpConstants.def
===================================================================
--- llvm/include/llvm/BinaryFormat/MinidumpConstants.def
+++ llvm/include/llvm/BinaryFormat/MinidumpConstants.def
@@ -6,8 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#if !(defined HANDLE_MDMP_STREAM_TYPE || defined HANDLE_MDMP_ARCH ||           \
-      defined HANDLE_MDMP_PLATFORM)
+#if !(defined(HANDLE_MDMP_STREAM_TYPE) || defined(HANDLE_MDMP_ARCH) ||         \
+      defined(HANDLE_MDMP_PLATFORM) || defined(HANDLE_MDMP_PROTECT) ||         \
+      defined(HANDLE_MDMP_MEMSTATE) || defined(HANDLE_MDMP_MEMTYPE))
 #error "Missing HANDLE_MDMP definition"
 #endif
 
@@ -23,6 +24,18 @@
 #define HANDLE_MDMP_PLATFORM(CODE, NAME)
 #endif
 
+#ifndef HANDLE_MDMP_PROTECT
+#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME)
+#endif
+
+#ifndef HANDLE_MDMP_MEMSTATE
+#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME)
+#endif
+
+#ifndef HANDLE_MDMP_MEMTYPE
+#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME)
+#endif
+
 HANDLE_MDMP_STREAM_TYPE(0x0003, ThreadList)
 HANDLE_MDMP_STREAM_TYPE(0x0004, ModuleList)
 HANDLE_MDMP_STREAM_TYPE(0x0005, MemoryList)
@@ -102,6 +115,30 @@
 HANDLE_MDMP_PLATFORM(0x8204, PS3) // PS3
 HANDLE_MDMP_PLATFORM(0x8205, NaCl) // Native Client (NaCl)
 
+HANDLE_MDMP_PROTECT(0x01, NoAccess, PAGE_NO_ACCESS)
+HANDLE_MDMP_PROTECT(0x02, ReadOnly, PAGE_READ_ONLY)
+HANDLE_MDMP_PROTECT(0x04, ReadWrite, PAGE_READ_WRITE)
+HANDLE_MDMP_PROTECT(0x08, WriteCopy, PAGE_WRITE_COPY)
+HANDLE_MDMP_PROTECT(0x10, Execute, PAGE_EXECUTE)
+HANDLE_MDMP_PROTECT(0x20, ExecuteRead, PAGE_EXECUTE_READ)
+HANDLE_MDMP_PROTECT(0x40, ExecuteReadWrite, PAGE_EXECUTE_READ_WRITE)
+HANDLE_MDMP_PROTECT(0x80, ExeciteWriteCopy, PAGE_EXECUTE_WRITE_COPY)
+HANDLE_MDMP_PROTECT(0x100, Guard, PAGE_GUARD)
+HANDLE_MDMP_PROTECT(0x200, NoCache, PAGE_NOCACHE)
+HANDLE_MDMP_PROTECT(0x400, WriteCombine, PAGE_WRITECOMBINE)
+HANDLE_MDMP_PROTECT(0x40000000, TargetsInvalid, PAGE_TARGETS_INVALID)
+
+HANDLE_MDMP_MEMSTATE(0x01000, Commit, MEM_COMMIT)
+HANDLE_MDMP_MEMSTATE(0x02000, Reserve, MEM_RESERVE)
+HANDLE_MDMP_MEMSTATE(0x10000, Free, MEM_FREE)
+
+HANDLE_MDMP_MEMTYPE(0x0020000, Private, MEM_PRIVATE)
+HANDLE_MDMP_MEMTYPE(0x0040000, Mapped, MEM_MAPPED)
+HANDLE_MDMP_MEMTYPE(0x1000000, Image, MEM_IMAGE)
+
 #undef HANDLE_MDMP_STREAM_TYPE
 #undef HANDLE_MDMP_ARCH
 #undef HANDLE_MDMP_PLATFORM
+#undef HANDLE_MDMP_PROTECT
+#undef HANDLE_MDMP_MEMSTATE
+#undef HANDLE_MDMP_MEMTYPE
Index: llvm/include/llvm/BinaryFormat/Minidump.h
===================================================================
--- llvm/include/llvm/BinaryFormat/Minidump.h
+++ llvm/include/llvm/BinaryFormat/Minidump.h
@@ -18,6 +18,7 @@
 #ifndef LLVM_BINARYFORMAT_MINIDUMP_H
 #define LLVM_BINARYFORMAT_MINIDUMP_H
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/Endian.h"
 
@@ -67,6 +68,42 @@
 };
 static_assert(sizeof(MemoryDescriptor) == 16, "");
 
+struct MemoryInfoListHeader {
+  support::ulittle32_t SizeOfHeader;
+  support::ulittle32_t SizeOfEntry;
+  support::ulittle64_t NumberOfEntries;
+};
+static_assert(sizeof(MemoryInfoListHeader) == 16, "");
+
+enum class MemoryProtection : uint32_t {
+#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
+};
+
+enum class MemoryState : uint32_t {
+#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+enum class MemoryType : uint32_t {
+#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) NAME = CODE,
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+};
+
+struct MemoryInfo {
+  support::ulittle64_t BaseAddress;
+  support::ulittle64_t AllocationBase;
+  support::little_t<MemoryProtection> AllocationProtect;
+  support::ulittle32_t Reserved0;
+  support::ulittle64_t RegionSize;
+  support::little_t<MemoryState> State;
+  support::little_t<MemoryProtection> Protect;
+  support::little_t<MemoryType> Type;
+  support::ulittle32_t Reserved1;
+};
+static_assert(sizeof(MemoryInfo) == 48, "");
+
 /// Specifies the location and type of a single stream in the minidump file. The
 /// minidump stream directory is an array of entries of this type, with its size
 /// given by Header.NumberOfStreams.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to