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
llvm-svn: 359762
diff --git a/llvm/unittests/Object/MinidumpTest.cpp b/llvm/unittests/Object/MinidumpTest.cpp
index fdb9d22..98e3132 100644
--- a/llvm/unittests/Object/MinidumpTest.cpp
+++ b/llvm/unittests/Object/MinidumpTest.cpp
@@ -343,7 +343,7 @@
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 @@
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);
+ }
+}