]> granicus.if.org Git - llvm/commitdiff
MinidumpYAML: Add support for the memory info list stream
authorPavel Labath <pavel@labath.sk>
Thu, 10 Oct 2019 13:05:46 +0000 (13:05 +0000)
committerPavel Labath <pavel@labath.sk>
Thu, 10 Oct 2019 13:05:46 +0000 (13:05 +0000)
Summary:
The implementation is fairly straight-forward and uses the same patterns
as the existing streams. The yaml form does not attempt to preserve the
data in the "gaps" that can be created by setting a larger-than-required
header or entry size in the stream header, because the existing consumer
(lldb) does not make use of the information in the gap in any way, and
attempting to preserve that would make the implementation more
complicated.

Reviewers: amccarth, jhenderson, clayborg

Subscribers: llvm-commits, lldb-commits, markmentovai, zturner, JosephTremoulet

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D68645

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374337 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/BinaryFormat/Minidump.h
include/llvm/ObjectYAML/MinidumpYAML.h
lib/ObjectYAML/MinidumpEmitter.cpp
lib/ObjectYAML/MinidumpYAML.cpp
test/tools/obj2yaml/basic-minidump.yaml

index 93df467cd823f3fe09e491193316f924635b154a..0ecd341da8c4efc6ee9ad4ed373bee5ef84e009b 100644 (file)
@@ -72,6 +72,12 @@ struct MemoryInfoListHeader {
   support::ulittle32_t SizeOfHeader;
   support::ulittle32_t SizeOfEntry;
   support::ulittle64_t NumberOfEntries;
+
+  MemoryInfoListHeader() = default;
+  MemoryInfoListHeader(uint32_t SizeOfHeader, uint32_t SizeOfEntry,
+                       uint64_t NumberOfEntries)
+      : SizeOfHeader(SizeOfHeader), SizeOfEntry(SizeOfEntry),
+        NumberOfEntries(NumberOfEntries) {}
 };
 static_assert(sizeof(MemoryInfoListHeader) == 16, "");
 
@@ -84,11 +90,13 @@ enum class MemoryProtection : uint32_t {
 enum class MemoryState : uint32_t {
 #define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) NAME = CODE,
 #include "llvm/BinaryFormat/MinidumpConstants.def"
+  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
 };
 
 enum class MemoryType : uint32_t {
 #define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) NAME = CODE,
 #include "llvm/BinaryFormat/MinidumpConstants.def"
+  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
 };
 
 struct MemoryInfo {
index b4163e483e856f8209e768d2f15e46d18bd676ca..54be8886c64957557f0ed33b1194792bae806b95 100644 (file)
@@ -26,6 +26,7 @@ namespace MinidumpYAML {
 /// from Types to Kinds is fixed and given by the static getKind function.
 struct Stream {
   enum class StreamKind {
+    MemoryInfoList,
     MemoryList,
     ModuleList,
     RawContent,
@@ -102,6 +103,26 @@ using ModuleListStream = detail::ListStream<detail::ParsedModule>;
 using ThreadListStream = detail::ListStream<detail::ParsedThread>;
 using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
 
+/// A structure containing the list of MemoryInfo entries comprising a
+/// MemoryInfoList stream.
+struct MemoryInfoListStream : public Stream {
+  std::vector<minidump::MemoryInfo> Infos;
+
+  MemoryInfoListStream()
+      : Stream(StreamKind::MemoryInfoList,
+               minidump::StreamType::MemoryInfoList) {}
+
+  explicit MemoryInfoListStream(
+      iterator_range<object::MinidumpFile::MemoryInfoIterator> Range)
+      : Stream(StreamKind::MemoryInfoList,
+               minidump::StreamType::MemoryInfoList),
+        Infos(Range.begin(), Range.end()) {}
+
+  static bool classof(const Stream *S) {
+    return S->Kind == StreamKind::MemoryInfoList;
+  }
+};
+
 /// A minidump stream represented as a sequence of hex bytes. This is used as a
 /// fallback when no other stream kind is suitable.
 struct RawContentStream : public Stream {
@@ -122,16 +143,16 @@ struct SystemInfoStream : public Stream {
   minidump::SystemInfo Info;
   std::string CSDVersion;
 
-  explicit SystemInfoStream(const minidump::SystemInfo &Info,
-                            std::string CSDVersion)
-      : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
-        Info(Info), CSDVersion(std::move(CSDVersion)) {}
-
   SystemInfoStream()
       : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) {
     memset(&Info, 0, sizeof(Info));
   }
 
+  explicit SystemInfoStream(const minidump::SystemInfo &Info,
+                            std::string CSDVersion)
+      : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
+        Info(Info), CSDVersion(std::move(CSDVersion)) {}
+
   static bool classof(const Stream *S) {
     return S->Kind == StreamKind::SystemInfo;
   }
@@ -207,6 +228,10 @@ template <> struct MappingContextTraits<minidump::MemoryDescriptor, BinaryRef> {
 
 } // namespace llvm
 
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryProtection)
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryState)
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryType)
+
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
@@ -214,6 +239,7 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::MemoryInfo)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
 
 LLVM_YAML_DECLARE_MAPPING_TRAITS(
@@ -227,6 +253,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::minidump::MemoryInfo)
 
 LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
 
index 31a839e524c305cf7b156956872c0f48ef7b395c..9029be80ad7154c8161369c508636ae3724104c5 100644 (file)
@@ -158,6 +158,14 @@ static Directory layout(BlobAllocator &File, Stream &S) {
   Result.Location.RVA = File.tell();
   Optional<size_t> DataEnd;
   switch (S.Kind) {
+  case Stream::StreamKind::MemoryInfoList: {
+    MemoryInfoListStream &InfoList = cast<MemoryInfoListStream>(S);
+    File.allocateNewObject<minidump::MemoryInfoListHeader>(
+        sizeof(minidump::MemoryInfoListHeader), sizeof(minidump::MemoryInfo),
+        InfoList.Infos.size());
+    File.allocateArray(makeArrayRef(InfoList.Infos));
+    break;
+  }
   case Stream::StreamKind::MemoryList:
     DataEnd = layout(File, cast<MemoryListStream>(S));
     break;
index acc36a95a293c980fb3af1a85918d1dfc3938083..b9d1ded1816616fd3391324a8a341b15c0e5348c 100644 (file)
@@ -69,6 +69,8 @@ Stream::~Stream() = default;
 
 Stream::StreamKind Stream::getKind(StreamType Type) {
   switch (Type) {
+  case StreamType::MemoryInfoList:
+    return StreamKind::MemoryInfoList;
   case StreamType::MemoryList:
     return StreamKind::MemoryList;
   case StreamType::ModuleList:
@@ -93,6 +95,8 @@ Stream::StreamKind Stream::getKind(StreamType Type) {
 std::unique_ptr<Stream> Stream::create(StreamType Type) {
   StreamKind Kind = getKind(Type);
   switch (Kind) {
+  case StreamKind::MemoryInfoList:
+    return std::make_unique<MemoryInfoListStream>();
   case StreamKind::MemoryList:
     return std::make_unique<MemoryListStream>();
   case StreamKind::ModuleList:
@@ -109,6 +113,25 @@ std::unique_ptr<Stream> Stream::create(StreamType Type) {
   llvm_unreachable("Unhandled stream kind!");
 }
 
+void yaml::ScalarBitSetTraits<MemoryProtection>::bitset(
+    IO &IO, MemoryProtection &Protect) {
+#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME)                            \
+  IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
+void yaml::ScalarBitSetTraits<MemoryState>::bitset(IO &IO, MemoryState &State) {
+#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME)                           \
+  IO.bitSetCase(State, #NATIVENAME, MemoryState::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
+void yaml::ScalarBitSetTraits<MemoryType>::bitset(IO &IO, MemoryType &Type) {
+#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME)                            \
+  IO.bitSetCase(Type, #NATIVENAME, MemoryType::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
 void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
     IO &IO, ProcessorArchitecture &Arch) {
 #define HANDLE_MDMP_ARCH(CODE, NAME)                                           \
@@ -215,6 +238,20 @@ void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO,
   mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);
 }
 
+void yaml::MappingTraits<MemoryInfo>::mapping(IO &IO, MemoryInfo &Info) {
+  mapRequiredHex(IO, "Base Address", Info.BaseAddress);
+  mapOptionalHex(IO, "Allocation Base", Info.AllocationBase, Info.BaseAddress);
+  mapRequiredAs<MemoryProtection>(IO, "Allocation Protect",
+                                  Info.AllocationProtect);
+  mapOptionalHex(IO, "Reserved0", Info.Reserved0, 0);
+  mapRequiredHex(IO, "Region Size", Info.RegionSize);
+  mapRequiredAs<MemoryState>(IO, "State", Info.State);
+  mapOptionalAs<MemoryProtection>(IO, "Protect", Info.Protect,
+                                  Info.AllocationProtect);
+  mapRequiredAs<MemoryType>(IO, "Type", Info.Type);
+  mapOptionalHex(IO, "Reserved1", Info.Reserved1, 0);
+}
+
 void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO,
                                                    VSFixedFileInfo &Info) {
   mapOptionalHex(IO, "Signature", Info.Signature, 0);
@@ -264,6 +301,10 @@ void yaml::MappingTraits<MemoryListStream::entry_type>::mapping(
       IO, Range.Entry, Range.Content);
 }
 
+static void streamMapping(yaml::IO &IO, MemoryInfoListStream &Stream) {
+  IO.mapRequired("Memory Ranges", Stream.Infos);
+}
+
 static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {
   IO.mapRequired("Memory Ranges", Stream.Entries);
 }
@@ -336,6 +377,9 @@ void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
   if (!IO.outputting())
     S = MinidumpYAML::Stream::create(Type);
   switch (S->Kind) {
+  case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
+    streamMapping(IO, llvm::cast<MemoryInfoListStream>(*S));
+    break;
   case MinidumpYAML::Stream::StreamKind::MemoryList:
     streamMapping(IO, llvm::cast<MemoryListStream>(*S));
     break;
@@ -362,6 +406,7 @@ StringRef yaml::MappingTraits<std::unique_ptr<Stream>>::validate(
   switch (S->Kind) {
   case MinidumpYAML::Stream::StreamKind::RawContent:
     return streamValidate(cast<RawContentStream>(*S));
+  case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
   case MinidumpYAML::Stream::StreamKind::MemoryList:
   case MinidumpYAML::Stream::StreamKind::ModuleList:
   case MinidumpYAML::Stream::StreamKind::SystemInfo:
@@ -384,6 +429,12 @@ Expected<std::unique_ptr<Stream>>
 Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
   StreamKind Kind = getKind(StreamDesc.Type);
   switch (Kind) {
+  case StreamKind::MemoryInfoList: {
+    if (auto ExpectedList = File.getMemoryInfoList())
+      return std::make_unique<MemoryInfoListStream>(*ExpectedList);
+    else
+      return ExpectedList.takeError();
+  }
   case StreamKind::MemoryList: {
     auto ExpectedList = File.getMemoryList();
     if (!ExpectedList)
index af08fe19bb7f8f5befd655fc86801a5271d2ccf4..e4955dbbf35fa4f80c4aef071eab8f5f52a89251 100644 (file)
@@ -55,6 +55,27 @@ Streams:
     Memory Ranges:   
       - Start of Memory Range: 0x7C7D7E7F80818283
         Content:               '8485868788'
+  - Type:            MemoryInfoList
+    Memory Ranges:
+      - Base Address:    0x0000000000000000
+        Allocation Protect: [  ]
+        Region Size:     0x0000000000010000
+        State:           [ MEM_FREE ]
+        Protect:         [ PAGE_NO_ACCESS ]
+        Type:            [  ]
+      - Base Address:    0x0000000000010000
+        Allocation Protect: [ PAGE_READ_WRITE ]
+        Region Size:     0x0000000000010000
+        State:           [ MEM_COMMIT ]
+        Type:            [ MEM_MAPPED ]
+      - Base Address:    0x0000000000020000
+        Allocation Base: 0x0000000000000000
+        Allocation Protect: [ PAGE_READ_WRITE, PAGE_WRITECOMBINE ]
+        Reserved0:       0xDEADBEEF
+        Region Size:     0x0000000000010000
+        State:           [ MEM_COMMIT, MEM_FREE ]
+        Type:            [ MEM_PRIVATE, MEM_MAPPED ]
+        Reserved1:       0xBAADF00D
 ...
 
 # CHECK:      --- !minidump
@@ -112,4 +133,25 @@ Streams:
 # CHECK-NEXT:     Memory Ranges:   
 # CHECK-NEXT:       - Start of Memory Range: 0x7C7D7E7F80818283
 # CHECK-NEXT:         Content:               '8485868788'
+# CHECK-NEXT:   - Type:            MemoryInfoList
+# CHECK-NEXT:     Memory Ranges:
+# CHECK-NEXT:       - Base Address:       0x0000000000000000
+# CHECK-NEXT:         Allocation Protect: [  ]
+# CHECK-NEXT:         Region Size:        0x0000000000010000
+# CHECK-NEXT:         State:              [ MEM_FREE ]
+# CHECK-NEXT:         Protect:            [ PAGE_NO_ACCESS ]
+# CHECK-NEXT:         Type:               [  ]
+# CHECK-NEXT:       - Base Address:       0x0000000000010000
+# CHECK-NEXT:         Allocation Protect: [ PAGE_READ_WRITE ]
+# CHECK-NEXT:         Region Size:        0x0000000000010000
+# CHECK-NEXT:         State:              [ MEM_COMMIT ]
+# CHECK-NEXT:         Type:               [ MEM_MAPPED ]
+# CHECK-NEXT:       - Base Address:       0x0000000000020000
+# CHECK-NEXT:         Allocation Base:    0x0000000000000000
+# CHECK-NEXT:         Allocation Protect: [ PAGE_READ_WRITE, PAGE_WRITECOMBINE ]
+# CHECK-NEXT:         Reserved0:          0xDEADBEEF
+# CHECK-NEXT:         Region Size:        0x0000000000010000
+# CHECK-NEXT:         State:              [ MEM_COMMIT, MEM_FREE ]
+# CHECK-NEXT:         Type:               [ MEM_PRIVATE, MEM_MAPPED ]
+# CHECK-NEXT:         Reserved1:          0xBAADF00D
 # CHECK-NEXT: ...