labath updated this revision to Diff 223811.
labath added a comment.
Address review comments
Repository:
rL LLVM
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D68210/new/
https://reviews.llvm.org/D68210
Files:
include/llvm/BinaryFormat/Minidump.h
include/llvm/BinaryFormat/MinidumpConstants.def
include/llvm/Object/Minidump.h
lib/Object/Minidump.cpp
unittests/Object/MinidumpTest.cpp
Index: unittests/Object/MinidumpTest.cpp
===================================================================
--- unittests/Object/MinidumpTest.cpp
+++ unittests/Object/MinidumpTest.cpp
@@ -511,3 +511,204 @@
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);
+ }
+
+ const auto &GetMemoryInfoList = [](ArrayRef<uint8_t> Data)
+ -> Expected<iterator_range<MinidumpFile::MemoryInfoIterator>> {
+ Expected<std::unique_ptr<MinidumpFile>> File = create(Data);
+ if (File)
+ return File.get()->getMemoryInfoList();
+ return File.takeError();
+ };
+ // 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, // ???
+ };
+ EXPECT_THAT_EXPECTED(GetMemoryInfoList(HeaderTooBig), 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, // ???
+ };
+ EXPECT_THAT_EXPECTED(GetMemoryInfoList(HeaderTooSmall),
+ 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
+ };
+ EXPECT_THAT_EXPECTED(GetMemoryInfoList(EntryTooBig), 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
+ };
+ auto ExpectedFile = create(ThreeEntries);
+ ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+ auto ExpectedInfo = ExpectedFile.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: lib/Object/Minidump.cpp
===================================================================
--- lib/Object/Minidump.cpp
+++ 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: include/llvm/Object/Minidump.h
===================================================================
--- include/llvm/Object/Minidump.h
+++ 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: include/llvm/BinaryFormat/MinidumpConstants.def
===================================================================
--- include/llvm/BinaryFormat/MinidumpConstants.def
+++ 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: include/llvm/BinaryFormat/Minidump.h
===================================================================
--- include/llvm/BinaryFormat/Minidump.h
+++ 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits