[llvm] r359762 - Object/Minidump: Add support for the ThreadList stream
Pavel Labath via llvm-commits
llvm-commits at lists.llvm.org
Thu May 2 00:45:42 PDT 2019
Author: labath
Date: Thu May 2 00:45:42 2019
New Revision: 359762
URL: http://llvm.org/viewvc/llvm-project?rev=359762&view=rev
Log:
Object/Minidump: Add support for the ThreadList stream
Summary:
The stream contains the list of threads belonging to the process
described by the minidump. Its structure is the same as the ModuleList
stream, and in fact, I have generalized the ModuleList reading code to
handle this stream too.
Reviewers: amccarth, jhenderson, clayborg
Subscribers: llvm-commits, lldb-commits, markmentovai, zturner
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D61064
Modified:
llvm/trunk/include/llvm/BinaryFormat/Minidump.h
llvm/trunk/include/llvm/Object/Minidump.h
llvm/trunk/lib/Object/Minidump.cpp
llvm/trunk/unittests/Object/MinidumpTest.cpp
Modified: llvm/trunk/include/llvm/BinaryFormat/Minidump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Minidump.h?rev=359762&r1=359761&r2=359762&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Minidump.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Minidump.h Thu May 2 00:45:42 2019
@@ -59,6 +59,14 @@ struct LocationDescriptor {
};
static_assert(sizeof(LocationDescriptor) == 8, "");
+/// Describes a single memory range (both its VM address and where to find it in
+/// the file) of the process from which this minidump file was generated.
+struct MemoryDescriptor {
+ support::ulittle64_t StartOfMemoryRange;
+ LocationDescriptor Memory;
+};
+static_assert(sizeof(MemoryDescriptor) == 16, "");
+
/// 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.
@@ -159,6 +167,19 @@ struct Module {
};
static_assert(sizeof(Module) == 108, "");
+/// Describes a single thread in the minidump file. Part of the ThreadList
+/// stream.
+struct Thread {
+ support::ulittle32_t ThreadId;
+ support::ulittle32_t SuspendCount;
+ support::ulittle32_t PriorityClass;
+ support::ulittle32_t Priority;
+ support::ulittle64_t EnvironmentBlock;
+ MemoryDescriptor Stack;
+ LocationDescriptor Context;
+};
+static_assert(sizeof(Thread) == 48, "");
+
} // namespace minidump
template <> struct DenseMapInfo<minidump::StreamType> {
Modified: llvm/trunk/include/llvm/Object/Minidump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Minidump.h?rev=359762&r1=359761&r2=359762&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Minidump.h (original)
+++ llvm/trunk/include/llvm/Object/Minidump.h Thu May 2 00:45:42 2019
@@ -67,7 +67,18 @@ public:
/// not large enough to contain the number of modules declared in the stream
/// header. The consistency of the Module entries themselves is not checked in
/// any way.
- Expected<ArrayRef<minidump::Module>> getModuleList() const;
+ Expected<ArrayRef<minidump::Module>> getModuleList() const {
+ return getListStream<minidump::Module>(minidump::StreamType::ModuleList);
+ }
+
+ /// Returns the thread list embedded in the ThreadList 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 threads declared in the stream
+ /// header. The consistency of the Thread entries themselves is not checked in
+ /// any way.
+ Expected<ArrayRef<minidump::Thread>> getThreadList() const {
+ return getListStream<minidump::Thread>(minidump::StreamType::ThreadList);
+ }
private:
static Error createError(StringRef Str) {
@@ -105,6 +116,11 @@ private:
template <typename T>
Expected<const T &> getStream(minidump::StreamType Stream) const;
+ /// Return the contents of a stream which contains a list of fixed-size items,
+ /// prefixed by the list size.
+ template <typename T>
+ Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const;
+
const minidump::Header &Header;
ArrayRef<minidump::Directory> Streams;
DenseMap<minidump::StreamType, std::size_t> StreamMap;
Modified: llvm/trunk/lib/Object/Minidump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Minidump.cpp?rev=359762&r1=359761&r2=359762&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Minidump.cpp (original)
+++ llvm/trunk/lib/Object/Minidump.cpp Thu May 2 00:45:42 2019
@@ -53,8 +53,9 @@ Expected<std::string> MinidumpFile::getS
return Result;
}
-Expected<ArrayRef<Module>> MinidumpFile::getModuleList() const {
- auto OptionalStream = getRawStream(StreamType::ModuleList);
+template <typename T>
+Expected<ArrayRef<T>> MinidumpFile::getListStream(StreamType Stream) const {
+ auto OptionalStream = getRawStream(Stream);
if (!OptionalStream)
return createError("No such stream");
auto ExpectedSize =
@@ -65,14 +66,18 @@ Expected<ArrayRef<Module>> MinidumpFile:
size_t ListSize = ExpectedSize.get()[0];
size_t ListOffset = 4;
- // Some producers insert additional padding bytes to align the module list to
- // 8-byte boundary. Check for that by comparing the module list size with the
- // overall stream size.
- if (ListOffset + sizeof(Module) * ListSize < OptionalStream->size())
+ // 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())
ListOffset = 8;
- return getDataSliceAs<Module>(*OptionalStream, ListOffset, ListSize);
+ return getDataSliceAs<T>(*OptionalStream, ListOffset, ListSize);
}
+template Expected<ArrayRef<Module>>
+ MinidumpFile::getListStream(StreamType) const;
+template Expected<ArrayRef<Thread>>
+ MinidumpFile::getListStream(StreamType) const;
Expected<ArrayRef<uint8_t>>
MinidumpFile::getDataSlice(ArrayRef<uint8_t> Data, size_t Offset, size_t Size) {
Modified: llvm/trunk/unittests/Object/MinidumpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Object/MinidumpTest.cpp?rev=359762&r1=359761&r2=359762&view=diff
==============================================================================
--- llvm/trunk/unittests/Object/MinidumpTest.cpp (original)
+++ llvm/trunk/unittests/Object/MinidumpTest.cpp Thu May 2 00:45:42 2019
@@ -343,7 +343,7 @@ TEST(MinidumpFile, getModuleList) {
5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
};
- for (const std::vector<uint8_t> &Data : {OneModule, PaddedModule}) {
+ for (ArrayRef<uint8_t> Data : {OneModule, PaddedModule}) {
auto ExpectedFile = create(Data);
ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
const MinidumpFile &File = **ExpectedFile;
@@ -396,3 +396,70 @@ TEST(MinidumpFile, getModuleList) {
const MinidumpFile &File = **ExpectedFile;
EXPECT_THAT_EXPECTED(File.getModuleList(), Failed<BinaryError>());
}
+
+TEST(MinidumpFile, getThreadList) {
+ std::vector<uint8_t> OneThread{
+ // 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
+ 3, 0, 0, 0, 52, 0, 0, 0, // Type, DataSize,
+ 44, 0, 0, 0, // RVA
+ // ThreadList
+ 1, 0, 0, 0, // NumberOfThreads
+ 1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount
+ 9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority
+ 7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock
+ // Stack
+ 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
+ 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
+ // Context
+ 1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA
+ };
+ // Same as before, but with a padded thread list.
+ std::vector<uint8_t> PaddedThread{
+ // 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
+ 3, 0, 0, 0, 56, 0, 0, 0, // Type, DataSize,
+ 44, 0, 0, 0, // RVA
+ // ThreadList
+ 1, 0, 0, 0, // NumberOfThreads
+ 0, 0, 0, 0, // Padding
+ 1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount
+ 9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority
+ 7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock
+ // Stack
+ 5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
+ 3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
+ // Context
+ 1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA
+ };
+
+ for (ArrayRef<uint8_t> Data : {OneThread, PaddedThread}) {
+ auto ExpectedFile = create(Data);
+ ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+ const MinidumpFile &File = **ExpectedFile;
+ Expected<ArrayRef<Thread>> ExpectedThread = File.getThreadList();
+ ASSERT_THAT_EXPECTED(ExpectedThread, Succeeded());
+ ASSERT_EQ(1u, ExpectedThread->size());
+ const Thread &T = ExpectedThread.get()[0];
+ EXPECT_EQ(0x04030201u, T.ThreadId);
+ EXPECT_EQ(0x08070605u, T.SuspendCount);
+ EXPECT_EQ(0x02010009u, T.PriorityClass);
+ EXPECT_EQ(0x06050403u, T.Priority);
+ EXPECT_EQ(0x0403020100090807u, T.EnvironmentBlock);
+ EXPECT_EQ(0x0201000908070605u, T.Stack.StartOfMemoryRange);
+ EXPECT_EQ(0x06050403u, T.Stack.Memory.DataSize);
+ EXPECT_EQ(0x00090807u, T.Stack.Memory.RVA);
+ EXPECT_EQ(0x04030201u, T.Context.DataSize);
+ EXPECT_EQ(0x08070605u, T.Context.RVA);
+ }
+}
More information about the llvm-commits
mailing list