[llvm] r360908 - Minidump: Add support for the MemoryList stream
Pavel Labath via llvm-commits
llvm-commits at lists.llvm.org
Thu May 16 08:17:31 PDT 2019
Author: labath
Date: Thu May 16 08:17:30 2019
New Revision: 360908
URL: http://llvm.org/viewvc/llvm-project?rev=360908&view=rev
Log:
Minidump: Add support for the MemoryList stream
Summary:
the stream format is exactly the same as for ThreadList and ModuleList
streams, only the entry types are slightly different, so the changes in
this patch are just straight-forward applications of established
patterns.
Reviewers: amccarth, jhenderson, clayborg
Subscribers: markmentovai, lldb-commits, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D61885
Modified:
llvm/trunk/include/llvm/Object/Minidump.h
llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h
llvm/trunk/lib/Object/Minidump.cpp
llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp
llvm/trunk/test/tools/obj2yaml/basic-minidump.yaml
llvm/trunk/unittests/Object/MinidumpTest.cpp
Modified: llvm/trunk/include/llvm/Object/Minidump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Minidump.h?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Minidump.h (original)
+++ llvm/trunk/include/llvm/Object/Minidump.h Thu May 16 08:17:30 2019
@@ -80,6 +80,16 @@ public:
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.
+ Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const {
+ return getListStream<minidump::MemoryDescriptor>(
+ minidump::StreamType::MemoryList);
+ }
+
private:
static Error createError(StringRef Str) {
return make_error<GenericBinaryError>(Str, object_error::parse_failed);
Modified: llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/MinidumpYAML.h Thu May 16 08:17:30 2019
@@ -26,6 +26,7 @@ namespace MinidumpYAML {
/// from Types to Kinds is fixed and given by the static getKind function.
struct Stream {
enum class StreamKind {
+ MemoryList,
ModuleList,
RawContent,
SystemInfo,
@@ -86,10 +87,20 @@ struct ParsedThread {
yaml::BinaryRef Stack;
yaml::BinaryRef Context;
};
+
+/// A structure containing all data describing a single memory region.
+struct ParsedMemoryDescriptor {
+ static constexpr Stream::StreamKind Kind = Stream::StreamKind::MemoryList;
+ static constexpr minidump::StreamType Type = minidump::StreamType::MemoryList;
+
+ minidump::MemoryDescriptor Entry;
+ yaml::BinaryRef Content;
+};
} // namespace detail
using ModuleListStream = detail::ListStream<detail::ParsedModule>;
using ThreadListStream = detail::ListStream<detail::ParsedThread>;
+using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
/// A minidump stream represented as a sequence of hex bytes. This is used as a
/// fallback when no other stream kind is suitable.
@@ -212,11 +223,14 @@ LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::m
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
LLVM_YAML_DECLARE_MAPPING_TRAITS(
+ llvm::MinidumpYAML::MemoryListStream::entry_type)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(
llvm::MinidumpYAML::ModuleListStream::entry_type)
LLVM_YAML_DECLARE_MAPPING_TRAITS(
llvm::MinidumpYAML::ThreadListStream::entry_type)
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)
Modified: llvm/trunk/lib/Object/Minidump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Minidump.cpp?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Minidump.cpp (original)
+++ llvm/trunk/lib/Object/Minidump.cpp Thu May 16 08:17:30 2019
@@ -78,6 +78,8 @@ template Expected<ArrayRef<Module>>
MinidumpFile::getListStream(StreamType) const;
template Expected<ArrayRef<Thread>>
MinidumpFile::getListStream(StreamType) const;
+template Expected<ArrayRef<MemoryDescriptor>>
+ MinidumpFile::getListStream(StreamType) const;
Expected<ArrayRef<uint8_t>>
MinidumpFile::getDataSlice(ArrayRef<uint8_t> Data, size_t Offset, size_t Size) {
Modified: llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/MinidumpYAML.cpp Thu May 16 08:17:30 2019
@@ -168,6 +168,8 @@ Stream::~Stream() = default;
Stream::StreamKind Stream::getKind(StreamType Type) {
switch (Type) {
+ case StreamType::MemoryList:
+ return StreamKind::MemoryList;
case StreamType::ModuleList:
return StreamKind::ModuleList;
case StreamType::SystemInfo:
@@ -190,6 +192,8 @@ Stream::StreamKind Stream::getKind(Strea
std::unique_ptr<Stream> Stream::create(StreamType Type) {
StreamKind Kind = getKind(Type);
switch (Kind) {
+ case StreamKind::MemoryList:
+ return llvm::make_unique<MemoryListStream>();
case StreamKind::ModuleList:
return llvm::make_unique<ModuleListStream>();
case StreamKind::RawContent:
@@ -353,6 +357,16 @@ static StringRef streamValidate(RawConte
return "";
}
+void yaml::MappingTraits<MemoryListStream::entry_type>::mapping(
+ IO &IO, MemoryListStream::entry_type &Range) {
+ MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping(
+ IO, Range.Entry, Range.Content);
+}
+
+static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {
+ IO.mapRequired("Memory Ranges", Stream.Entries);
+}
+
static void streamMapping(yaml::IO &IO, ModuleListStream &Stream) {
IO.mapRequired("Modules", Stream.Entries);
}
@@ -421,6 +435,9 @@ void yaml::MappingTraits<std::unique_ptr
if (!IO.outputting())
S = MinidumpYAML::Stream::create(Type);
switch (S->Kind) {
+ case MinidumpYAML::Stream::StreamKind::MemoryList:
+ streamMapping(IO, llvm::cast<MemoryListStream>(*S));
+ break;
case MinidumpYAML::Stream::StreamKind::ModuleList:
streamMapping(IO, llvm::cast<ModuleListStream>(*S));
break;
@@ -444,6 +461,7 @@ StringRef yaml::MappingTraits<std::uniqu
switch (S->Kind) {
case MinidumpYAML::Stream::StreamKind::RawContent:
return streamValidate(cast<RawContentStream>(*S));
+ case MinidumpYAML::Stream::StreamKind::MemoryList:
case MinidumpYAML::Stream::StreamKind::ModuleList:
case MinidumpYAML::Stream::StreamKind::SystemInfo:
case MinidumpYAML::Stream::StreamKind::TextContent:
@@ -466,6 +484,10 @@ static LocationDescriptor layout(BlobAll
support::ulittle32_t(File.allocateBytes(Data))};
}
+static void layout(BlobAllocator &File, MemoryListStream::entry_type &Range) {
+ Range.Entry.Memory = layout(File, Range.Content);
+}
+
static void layout(BlobAllocator &File, ModuleListStream::entry_type &M) {
M.Entry.ModuleNameRVA = File.allocateString(M.Name);
@@ -502,6 +524,9 @@ static Directory layout(BlobAllocator &F
Result.Location.RVA = File.tell();
Optional<size_t> DataEnd;
switch (S.Kind) {
+ case Stream::StreamKind::MemoryList:
+ DataEnd = layout(File, cast<MemoryListStream>(S));
+ break;
case Stream::StreamKind::ModuleList:
DataEnd = layout(File, cast<ModuleListStream>(S));
break;
@@ -566,6 +591,19 @@ Expected<std::unique_ptr<Stream>>
Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
StreamKind Kind = getKind(StreamDesc.Type);
switch (Kind) {
+ case StreamKind::MemoryList: {
+ auto ExpectedList = File.getMemoryList();
+ if (!ExpectedList)
+ return ExpectedList.takeError();
+ std::vector<MemoryListStream::entry_type> Ranges;
+ for (const MemoryDescriptor &MD : *ExpectedList) {
+ auto ExpectedContent = File.getRawData(MD.Memory);
+ if (!ExpectedContent)
+ return ExpectedContent.takeError();
+ Ranges.push_back({MD, *ExpectedContent});
+ }
+ return llvm::make_unique<MemoryListStream>(std::move(Ranges));
+ }
case StreamKind::ModuleList: {
auto ExpectedList = File.getModuleList();
if (!ExpectedList)
Modified: llvm/trunk/test/tools/obj2yaml/basic-minidump.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/basic-minidump.yaml?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/test/tools/obj2yaml/basic-minidump.yaml (original)
+++ llvm/trunk/test/tools/obj2yaml/basic-minidump.yaml Thu May 16 08:17:30 2019
@@ -37,20 +37,24 @@ Streams:
File Date High: 0x3C3D3E3F
File Date Low: 0x40414243
CodeView Record: '44454647'
- Misc Record: 48494A4B
+ Misc Record: '48494A4B'
- Base of Image: 0x4C4D4E4F50515253
Size of Image: 0x54555657
Module Name: libb.so
- CodeView Record: 58595A5B
+ CodeView Record: '58595A5B'
- Type: ThreadList
Threads:
- Thread Id: 0x5C5D5E5F
Priority Class: 0x60616263
Environment Block: 0x6465666768696A6B
- Context: 7C7D7E7F80818283
+ Context: '7C7D7E7F80818283'
Stack:
Start of Memory Range: 0x6C6D6E6F70717273
- Content: 7475767778797A7B
+ Content: '7475767778797A7B'
+ - Type: MemoryList
+ Memory Ranges:
+ - Start of Memory Range: 0x7C7D7E7F80818283
+ Content: '8485868788'
...
# CHECK: --- !minidump
@@ -97,11 +101,15 @@ Streams:
# CHECK-NEXT: CodeView Record: 58595A5B
# CHECK-NEXT: - Type: ThreadList
# CHECK-NEXT: Threads:
-# CHECK-NEXT: - Thread Id: 0x5C5D5E5F
-# CHECK-NEXT: Priority Class: 0x60616263
+# CHECK-NEXT: - Thread Id: 0x5C5D5E5F
+# CHECK-NEXT: Priority Class: 0x60616263
# CHECK-NEXT: Environment Block: 0x6465666768696A6B
-# CHECK-NEXT: Context: 7C7D7E7F80818283
+# CHECK-NEXT: Context: 7C7D7E7F80818283
# CHECK-NEXT: Stack:
# CHECK-NEXT: Start of Memory Range: 0x6C6D6E6F70717273
-# CHECK-NEXT: Content: 7475767778797A7B
+# CHECK-NEXT: Content: 7475767778797A7B
+# CHECK-NEXT: - Type: MemoryList
+# CHECK-NEXT: Memory Ranges:
+# CHECK-NEXT: - Start of Memory Range: 0x7C7D7E7F80818283
+# CHECK-NEXT: Content: '8485868788'
# CHECK-NEXT: ...
Modified: llvm/trunk/unittests/Object/MinidumpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Object/MinidumpTest.cpp?rev=360908&r1=360907&r2=360908&view=diff
==============================================================================
--- llvm/trunk/unittests/Object/MinidumpTest.cpp (original)
+++ llvm/trunk/unittests/Object/MinidumpTest.cpp Thu May 16 08:17:30 2019
@@ -463,3 +463,51 @@ TEST(MinidumpFile, getThreadList) {
EXPECT_EQ(0x08070605u, T.Context.RVA);
}
}
+
+TEST(MinidumpFile, getMemoryList) {
+ std::vector<uint8_t> OneRange{
+ // 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
+ 5, 0, 0, 0, 20, 0, 0, 0, // Type, DataSize,
+ 44, 0, 0, 0, // RVA
+ // MemoryDescriptor
+ 1, 0, 0, 0, // NumberOfMemoryRanges
+ 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
+ 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
+ };
+ // Same as before, but with a padded memory list.
+ std::vector<uint8_t> PaddedRange{
+ // 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
+ 5, 0, 0, 0, 24, 0, 0, 0, // Type, DataSize,
+ 44, 0, 0, 0, // RVA
+ // MemoryDescriptor
+ 1, 0, 0, 0, // NumberOfMemoryRanges
+ 0, 0, 0, 0, // Padding
+ 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
+ 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
+ };
+
+ for (ArrayRef<uint8_t> Data : {OneRange, PaddedRange}) {
+ auto ExpectedFile = create(Data);
+ ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+ const MinidumpFile &File = **ExpectedFile;
+ Expected<ArrayRef<MemoryDescriptor>> ExpectedRanges = File.getMemoryList();
+ ASSERT_THAT_EXPECTED(ExpectedRanges, Succeeded());
+ ASSERT_EQ(1u, ExpectedRanges->size());
+ const MemoryDescriptor &MD = ExpectedRanges.get()[0];
+ EXPECT_EQ(0x0201000908070605u, MD.StartOfMemoryRange);
+ EXPECT_EQ(0x06050403u, MD.Memory.DataSize);
+ EXPECT_EQ(0x00090807u, MD.Memory.RVA);
+ }
+}
More information about the llvm-commits
mailing list