summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2019-03-25 14:02:16 +0000
committerPavel Labath <pavel@labath.sk>2019-03-25 14:02:16 +0000
commit2ef15d82e9086b97a18d7acbcbca31a81450105c (patch)
treecf5661ca9d6225c337885b349bfade9befa75242
parentbc92c8c8636b78507123faa6e9ef71b3f8f48d08 (diff)
downloadbcm5719-llvm-2ef15d82e9086b97a18d7acbcbca31a81450105c.tar.gz
bcm5719-llvm-2ef15d82e9086b97a18d7acbcbca31a81450105c.zip
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. llvm-svn: 356896
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py134
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmpbin0 -> 460 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmpbin0 -> 468 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmpbin0 -> 492 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmpbin0 -> 470 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmpbin0 -> 470 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmpbin0 -> 534 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmpbin0 -> 470 bytes
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp49
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp26
10 files changed, 185 insertions, 24 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py
new file mode 100644
index 00000000000..1e4a98363e3
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py
@@ -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)
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp
new file mode 100644
index 00000000000..df24fef6d38
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp
new file mode 100644
index 00000000000..d1a39827b5e
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp
new file mode 100644
index 00000000000..238c0f97bf9
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp
new file mode 100644
index 00000000000..1ce4ce2cffc
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp
new file mode 100644
index 00000000000..ee82b9bd704
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp
new file mode 100644
index 00000000000..d8e1f4a70c9
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.dmp
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp
new file mode 100644
index 00000000000..1cc6e56987a
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.dmp
Binary files differ
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 0ec8ddcdcfb..d18244f7610 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -165,23 +165,46 @@ UUID MinidumpParser::GetModuleUUID(const MinidumpModule *module) {
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();
}
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
index 5c010cdd981..4abf36efe56 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
@@ -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);
OpenPOWER on IntegriCloud