[Lldb-commits] [lldb] r356896 - Reapply minidump changes reverted in r356806

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Mar 25 07:02:17 PDT 2019


Author: labath
Date: Mon Mar 25 07:02:16 2019
New Revision: 356896

URL: http://llvm.org/viewvc/llvm-project?rev=356896&view=rev
Log:
Reapply minidump changes reverted in r356806

The changes were reverted due to ubsan errors (unaligned accesses). Here
I fix those errors by first copying the data into aligned storage.
Besides fixing alignment issues, this also fixes reading of minidump
strings on big-endian systems.

Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp
Modified:
    lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
    lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py?rev=356896&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py Mon Mar 25 07:02:16 2019
@@ -0,0 +1,134 @@
+"""
+Test basics of Minidump debugging.
+"""
+
+from __future__ import print_function
+from six import iteritems
+
+import shutil
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class MiniDumpUUIDTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def setUp(self):
+        super(MiniDumpUUIDTestCase, self).setUp()
+        self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+    def tearDown(self):
+        lldb.DBG.SetSelectedPlatform(self._initial_platform)
+        super(MiniDumpUUIDTestCase, self).tearDown()
+
+    def verify_module(self, module, verify_path, verify_uuid):
+        uuid = module.GetUUIDString()
+        self.assertEqual(verify_path, module.GetFileSpec().fullpath)
+        self.assertEqual(verify_uuid, uuid)
+
+    def test_zero_uuid_modules(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            but contains a PDB70 value whose age is zero and whose UUID values are 
+            all zero. Prior to a fix all such modules would be duplicated to the
+            first one since the UUIDs claimed to be valid and all zeroes. Now we
+            ensure that the UUID is not valid for each module and that we have
+            each of the modules in the target after loading the core
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-zero-uuids.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/file/does/not/exist/a", None)
+        self.verify_module(modules[1], "/file/does/not/exist/b", None)
+
+    def test_uuid_modules_no_age(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a PDB70 value whose age is zero and whose UUID values are 
+            valid. Ensure we decode the UUID and don't include the age field in the UUID.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-uuids-no-age.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10")
+        self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0")
+
+    def test_uuid_modules_no_age_apple(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a PDB70 value whose age is zero and whose UUID values are 
+            valid. Ensure we decode the UUID and don't include the age field in the UUID.
+            Also ensure that the first uint32_t is byte swapped, along with the next
+            two uint16_t values. Breakpad incorrectly byte swaps these values when it
+            saves Darwin minidump files.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("macos-arm-uuids-no-age.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/tmp/a", "04030201-0605-0807-090A-0B0C0D0E0F10")
+        self.verify_module(modules[1], "/tmp/b", "281E140A-3C32-5046-5A64-6E78828C96A0")
+
+    def test_uuid_modules_with_age(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a PDB70 value whose age is valid and whose UUID values are 
+            valid. Ensure we decode the UUID and include the age field in the UUID.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-uuids-with-age.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-10101010")
+        self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-20202020")
+
+    def test_uuid_modules_elf_build_id_16(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a ELF build ID whose value is valid and is 16 bytes long.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-uuids-elf-build-id-16.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10")
+        self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0")
+
+    def test_uuid_modules_elf_build_id_20(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a ELF build ID whose value is valid and is 20 bytes long.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-uuids-elf-build-id-20.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314")
+        self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8")
+
+    def test_uuid_modules_elf_build_id_zero(self):
+        """
+            Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
+            and contains a ELF build ID whose value is all zero.
+        """
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-arm-uuids-elf-build-id-zero.dmp")
+        modules = self.target.modules
+        self.assertEqual(2, len(modules))
+        self.verify_module(modules[0], "/not/exist/a", None)
+        self.verify_module(modules[1], "/not/exist/b", None)

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp Mon Mar 25 07:02:16 2019 differ

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp?rev=356896&view=auto
==============================================================================
Binary files lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp (added) and lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp Mon Mar 25 07:02:16 2019 differ

Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp?rev=356896&r1=356895&r2=356896&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp Mon Mar 25 07:02:16 2019
@@ -165,23 +165,46 @@ UUID MinidumpParser::GetModuleUUID(const
       static_cast<CvSignature>(static_cast<uint32_t>(*signature));
 
   if (cv_signature == CvSignature::Pdb70) {
-    // PDB70 record
     const CvRecordPdb70 *pdb70_uuid = nullptr;
     Status error = consumeObject(cv_record, pdb70_uuid);
-    if (!error.Fail()) {
-      auto arch = GetArchitecture();
-      // For Apple targets we only need a 16 byte UUID so that we can match
-      // the UUID in the Module to actual UUIDs from the built binaries. The
-      // "Age" field is zero in breakpad minidump files for Apple targets, so
-      // we restrict the UUID to the "Uuid" field so we have a UUID we can use
-      // to match.
-      if (arch.GetTriple().getVendor() == llvm::Triple::Apple)
-        return UUID::fromData(pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid));
-      else
-        return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+    if (error.Fail())
+      return UUID();
+    // If the age field is not zero, then include the entire pdb70_uuid struct
+    if (pdb70_uuid->Age != 0)
+      return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+
+    // Many times UUIDs are all zeroes. This can cause more than one module
+    // to claim it has a valid UUID of all zeroes and causes the files to all
+    // merge into the first module that claims this valid zero UUID.
+    bool all_zeroes = true;
+    for (size_t i = 0; all_zeroes && i < sizeof(pdb70_uuid->Uuid); ++i)
+      all_zeroes = pdb70_uuid->Uuid[i] == 0;
+    if (all_zeroes)
+      return UUID();
+    
+    if (GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
+      // Breakpad incorrectly byte swaps the first 32 bit and next 2 16 bit
+      // values in the UUID field. Undo this so we can match things up
+      // with our symbol files
+      uint8_t apple_uuid[16];
+      // Byte swap the first 32 bits
+      apple_uuid[0] = pdb70_uuid->Uuid[3];
+      apple_uuid[1] = pdb70_uuid->Uuid[2];
+      apple_uuid[2] = pdb70_uuid->Uuid[1];
+      apple_uuid[3] = pdb70_uuid->Uuid[0];
+      // Byte swap the next 16 bit value
+      apple_uuid[4] = pdb70_uuid->Uuid[5];
+      apple_uuid[5] = pdb70_uuid->Uuid[4];
+      // Byte swap the next 16 bit value
+      apple_uuid[6] = pdb70_uuid->Uuid[7];
+      apple_uuid[7] = pdb70_uuid->Uuid[6];
+      for (size_t i = 8; i < sizeof(pdb70_uuid->Uuid); ++i)
+        apple_uuid[i] = pdb70_uuid->Uuid[i];
+      return UUID::fromData(apple_uuid, sizeof(apple_uuid));
     }
+    return UUID::fromData(pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid));
   } else if (cv_signature == CvSignature::ElfBuildId)
-    return UUID::fromData(cv_record);
+    return UUID::fromOptionalData(cv_record);
 
   return UUID();
 }

Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp?rev=356896&r1=356895&r2=356896&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp Mon Mar 25 07:02:16 2019
@@ -37,26 +37,30 @@ llvm::Optional<std::string>
 lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
   std::string result;
 
-  const uint32_t *source_length_ptr;
-  Status error = consumeObject(data, source_length_ptr);
+  const llvm::support::ulittle32_t *source_length;
+  Status error = consumeObject(data, source_length);
 
-  // Copy non-aligned source_length data into aligned memory.
-  uint32_t source_length;
-  std::memcpy(&source_length, source_length_ptr, sizeof(source_length));
-
-  if (error.Fail() || source_length > data.size() || source_length % 2 != 0)
+  if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0)
     return llvm::None;
 
-  auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data());
+  auto *source_start =
+      reinterpret_cast<const llvm::support::ulittle16_t *>(data.data());
   // source_length is the length of the string in bytes we need the length of
   // the string in UTF-16 characters/code points (16 bits per char) that's why
   // it's divided by 2
-  const auto source_end = source_start + source_length / 2;
+  uint32_t utf16_length = *source_length / 2;
+
+  // Correct the endianness and alignment of the string.
+  llvm::SmallVector<llvm::UTF16, 64> utf16(utf16_length, 0);
+  std::copy_n(source_start, utf16_length, utf16.begin());
+
+  const llvm::UTF16 *utf16_start = utf16.begin();
+
   // resize to worst case length
-  result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length / 2);
+  result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * utf16_length);
   auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]);
   const auto result_end = result_start + result.size();
-  llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
+  llvm::ConvertUTF16toUTF8(&utf16_start, utf16.end(), &result_start, result_end,
                            llvm::strictConversion);
   const auto result_size =
       std::distance(reinterpret_cast<llvm::UTF8 *>(&result[0]), result_start);




More information about the lldb-commits mailing list