[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