This revision was automatically updated to reflect the committed changes.
Closed by commit rL357897: Object/Minidump: Add support for reading the 
ModuleList stream (authored by labath, committed by ).

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60121/new/

https://reviews.llvm.org/D60121

Files:
  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

Index: llvm/trunk/include/llvm/BinaryFormat/Minidump.h
===================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Minidump.h
+++ llvm/trunk/include/llvm/BinaryFormat/Minidump.h
@@ -124,6 +124,37 @@
 };
 static_assert(sizeof(SystemInfo) == 56, "");
 
+struct VSFixedFileInfo {
+  support::ulittle32_t Signature;
+  support::ulittle32_t StructVersion;
+  support::ulittle32_t FileVersionHigh;
+  support::ulittle32_t FileVersionLow;
+  support::ulittle32_t ProductVersionHigh;
+  support::ulittle32_t ProductVersionLow;
+  support::ulittle32_t FileFlagsMask;
+  support::ulittle32_t FileFlags;
+  support::ulittle32_t FileOS;
+  support::ulittle32_t FileType;
+  support::ulittle32_t FileSubtype;
+  support::ulittle32_t FileDateHigh;
+  support::ulittle32_t FileDateLow;
+};
+static_assert(sizeof(VSFixedFileInfo) == 52, "");
+
+struct Module {
+  support::ulittle64_t BaseOfImage;
+  support::ulittle32_t SizeOfImage;
+  support::ulittle32_t Checksum;
+  support::ulittle32_t TimeDateStamp;
+  support::ulittle32_t ModuleNameRVA;
+  VSFixedFileInfo VersionInfo;
+  LocationDescriptor CvRecord;
+  LocationDescriptor MiscRecord;
+  support::ulittle64_t Reserved0;
+  support::ulittle64_t Reserved1;
+};
+static_assert(sizeof(Module) == 108, "");
+
 } // namespace minidump
 
 template <> struct DenseMapInfo<minidump::StreamType> {
Index: llvm/trunk/include/llvm/Object/Minidump.h
===================================================================
--- llvm/trunk/include/llvm/Object/Minidump.h
+++ llvm/trunk/include/llvm/Object/Minidump.h
@@ -55,14 +55,21 @@
     return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo);
   }
 
+  /// Returns the module list embedded in the ModuleList 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 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;
+
 private:
-  static Error createError(StringRef Str,
-                           object_error Err = object_error::parse_failed) {
-    return make_error<GenericBinaryError>(Str, Err);
+  static Error createError(StringRef Str) {
+    return make_error<GenericBinaryError>(Str, object_error::parse_failed);
   }
 
   static Error createEOFError() {
-    return createError("Unexpected EOF", object_error::unexpected_eof);
+    return make_error<GenericBinaryError>("Unexpected EOF",
+                                          object_error::unexpected_eof);
   }
 
   /// Return a slice of the given data array, with bounds checking.
@@ -101,9 +108,9 @@
   if (auto OptionalStream = getRawStream(Stream)) {
     if (OptionalStream->size() >= sizeof(T))
       return *reinterpret_cast<const T *>(OptionalStream->data());
-    return createError("Malformed stream", object_error::unexpected_eof);
+    return createEOFError();
   }
-  return createError("No such stream", object_error::invalid_section_index);
+  return createError("No such stream");
 }
 
 template <typename T>
Index: llvm/trunk/lib/Object/Minidump.cpp
===================================================================
--- llvm/trunk/lib/Object/Minidump.cpp
+++ llvm/trunk/lib/Object/Minidump.cpp
@@ -53,6 +53,27 @@
   return Result;
 }
 
+Expected<ArrayRef<Module>> MinidumpFile::getModuleList() const {
+  auto OptionalStream = getRawStream(StreamType::ModuleList);
+  if (!OptionalStream)
+    return createError("No such stream");
+  auto ExpectedSize =
+      getDataSliceAs<support::ulittle32_t>(*OptionalStream, 0, 1);
+  if (!ExpectedSize)
+    return ExpectedSize.takeError();
+
+  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())
+    ListOffset = 8;
+
+  return getDataSliceAs<Module>(*OptionalStream, ListOffset, ListSize);
+}
+
 Expected<ArrayRef<uint8_t>>
 MinidumpFile::getDataSlice(ArrayRef<uint8_t> Data, size_t Offset, size_t Size) {
   // Check for overflow.
Index: llvm/trunk/unittests/Object/MinidumpTest.cpp
===================================================================
--- llvm/trunk/unittests/Object/MinidumpTest.cpp
+++ llvm/trunk/unittests/Object/MinidumpTest.cpp
@@ -284,3 +284,115 @@
   EXPECT_THAT_EXPECTED(File.getString(ManyStrings.size() - 2),
                        Failed<BinaryError>());
 }
+
+TEST(MinidumpFile, getModuleList) {
+  std::vector<uint8_t> OneModule{
+      // 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
+      4, 0, 0, 0, 112, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // ModuleList
+      1, 0, 0, 0,             // NumberOfModules
+      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
+      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
+      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
+      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
+      0, 0, 0, 0,             // FileOS
+      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
+      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
+      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
+      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
+      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
+      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
+  };
+  // Same as before, but with a padded module list.
+  std::vector<uint8_t> PaddedModule{
+      // 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
+      4, 0, 0, 0, 116, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // ModuleList
+      1, 0, 0, 0,             // NumberOfModules
+      0, 0, 0, 0,             // Padding
+      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
+      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
+      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
+      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
+      0, 0, 0, 0,             // FileOS
+      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
+      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
+      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
+      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
+      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
+      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
+  };
+
+  for (const std::vector<uint8_t> &Data : {OneModule, PaddedModule}) {
+    auto ExpectedFile = create(Data);
+    ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+    const MinidumpFile &File = **ExpectedFile;
+    Expected<ArrayRef<Module>> ExpectedModule = File.getModuleList();
+    ASSERT_THAT_EXPECTED(ExpectedModule, Succeeded());
+    ASSERT_EQ(1u, ExpectedModule->size());
+    const Module &M = ExpectedModule.get()[0];
+    EXPECT_EQ(0x0807060504030201u, M.BaseOfImage);
+    EXPECT_EQ(0x02010009u, M.SizeOfImage);
+    EXPECT_EQ(0x06050403u, M.Checksum);
+    EXPECT_EQ(0x00090807u, M.TimeDateStamp);
+    EXPECT_EQ(0x04030201u, M.ModuleNameRVA);
+    EXPECT_EQ(0x04030201u, M.CvRecord.DataSize);
+    EXPECT_EQ(0x08070605u, M.CvRecord.RVA);
+    EXPECT_EQ(0x02010009u, M.MiscRecord.DataSize);
+    EXPECT_EQ(0x06050403u, M.MiscRecord.RVA);
+    EXPECT_EQ(0x0403020100090807u, M.Reserved0);
+    EXPECT_EQ(0x0201000908070605u, M.Reserved1);
+  }
+
+  std::vector<uint8_t> StreamTooShort{
+      // 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
+      4, 0, 0, 0, 111, 0, 0, 0,             // Type, DataSize,
+      44, 0, 0, 0,                          // RVA
+      // ModuleList
+      1, 0, 0, 0,             // NumberOfModules
+      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
+      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
+      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
+      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
+      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
+      0, 0, 0, 0,             // FileOS
+      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
+      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
+      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
+      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
+      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
+      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
+  };
+  auto ExpectedFile = create(StreamTooShort);
+  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
+  const MinidumpFile &File = **ExpectedFile;
+  EXPECT_THAT_EXPECTED(File.getModuleList(), Failed<BinaryError>());
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to