Some tests set settings and don't clean them up, this leads to side effects in other tests. The patch removes a global debugger instance with a per-test debugger to avoid such effects. From what I see, lldb.DBG was needed to determine the platform before a test is run, lldb.selected_platform is used for this purpose now. Though, this required adding a new function to the SBPlatform interface. Differential Revision: https://reviews.llvm.org/D74903
188 lines
9.3 KiB
Python
188 lines
9.3 KiB
Python
"""
|
|
Test basics of Minidump debugging.
|
|
"""
|
|
|
|
from six import iteritems
|
|
|
|
|
|
import lldb
|
|
import os
|
|
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 verify_module(self, module, verify_path, verify_uuid):
|
|
uuid = module.GetUUIDString()
|
|
self.assertEqual(verify_path, module.GetFileSpec().fullpath)
|
|
self.assertEqual(verify_uuid, uuid)
|
|
|
|
def get_minidump_modules(self, yaml_file):
|
|
minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp")
|
|
self.yaml2obj(yaml_file, minidump_path)
|
|
self.target = self.dbg.CreateTarget(None)
|
|
self.process = self.target.LoadCore(minidump_path)
|
|
return self.target.modules
|
|
|
|
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
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-zero-uuids.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-uuids-no-age.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("macos-arm-uuids-no-age.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-uuids-with-age.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml")
|
|
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.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-zero.yaml")
|
|
self.assertEqual(2, len(modules))
|
|
self.verify_module(modules[0], "/not/exist/a", None)
|
|
self.verify_module(modules[1], "/not/exist/b", None)
|
|
|
|
def test_uuid_modules_elf_build_id_same(self):
|
|
"""
|
|
Test multiple modules having a MINIDUMP_MODULE.CvRecord that is
|
|
valid, and contains a ELF build ID whose value is the same. There
|
|
is an assert in the PlaceholderObjectFile that was firing when we
|
|
encountered this which was crashing the process that was checking
|
|
if PlaceholderObjectFile.m_base was the same as the address this
|
|
fake module was being loaded at. We need to ensure we don't crash
|
|
in such cases and that we add both modules even though they have
|
|
the same UUID.
|
|
"""
|
|
modules = self.get_minidump_modules("linux-arm-same-uuids.yaml")
|
|
self.assertEqual(2, len(modules))
|
|
self.verify_module(modules[0], "/file/does/not/exist/a",
|
|
'11223344-1122-3344-1122-334411223344-11223344')
|
|
self.verify_module(modules[1], "/file/does/not/exist/b",
|
|
'11223344-1122-3344-1122-334411223344-11223344')
|
|
|
|
@expectedFailureAll(oslist=["windows"])
|
|
def test_partial_uuid_match(self):
|
|
"""
|
|
Breakpad has been known to create minidump files using CvRecord in each
|
|
module whose signature is set to PDB70 where the UUID only contains the
|
|
first 16 bytes of a 20 byte ELF build ID. Code was added to
|
|
ProcessMinidump.cpp to deal with this and allows partial UUID matching.
|
|
|
|
This test verifies that if we have a minidump with a 16 byte UUID, that
|
|
we are able to associate a symbol file with a 20 byte UUID only if the
|
|
first 16 bytes match. In this case we will see the path from the file
|
|
we found in the test directory and the 20 byte UUID from the actual
|
|
file, not the 16 byte shortened UUID from the minidump.
|
|
"""
|
|
so_path = self.getBuildArtifact("libuuidmatch.so")
|
|
self.yaml2obj("libuuidmatch.yaml", so_path)
|
|
cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path))
|
|
self.dbg.HandleCommand(cmd)
|
|
modules = self.get_minidump_modules("linux-arm-partial-uuids-match.yaml")
|
|
self.assertEqual(1, len(modules))
|
|
self.verify_module(modules[0], so_path,
|
|
"7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116")
|
|
|
|
def test_partial_uuid_mismatch(self):
|
|
"""
|
|
Breakpad has been known to create minidump files using CvRecord in each
|
|
module whose signature is set to PDB70 where the UUID only contains the
|
|
first 16 bytes of a 20 byte ELF build ID. Code was added to
|
|
ProcessMinidump.cpp to deal with this and allows partial UUID matching.
|
|
|
|
This test verifies that if we have a minidump with a 16 byte UUID, that
|
|
we are not able to associate a symbol file with a 20 byte UUID only if
|
|
any of the first 16 bytes do not match. In this case we will see the UUID
|
|
from the minidump file and the path from the minidump file.
|
|
"""
|
|
so_path = self.getBuildArtifact("libuuidmismatch.so")
|
|
self.yaml2obj("libuuidmismatch.yaml", so_path)
|
|
cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path))
|
|
self.dbg.HandleCommand(cmd)
|
|
modules = self.get_minidump_modules("linux-arm-partial-uuids-mismatch.yaml")
|
|
self.assertEqual(1, len(modules))
|
|
self.verify_module(modules[0],
|
|
"/invalid/path/on/current/system/libuuidmismatch.so",
|
|
"7295E17C-6668-9E05-CBB5-DEE5003865D5")
|
|
|
|
def test_relative_module_name(self):
|
|
old_cwd = os.getcwd()
|
|
self.addTearDownHook(lambda: os.chdir(old_cwd))
|
|
os.chdir(self.getBuildDir())
|
|
name = "file-with-a-name-unlikely-to-exist-in-the-current-directory.so"
|
|
open(name, "a").close()
|
|
modules = self.get_minidump_modules(
|
|
self.getSourcePath("relative_module_name.yaml"))
|
|
self.assertEqual(1, len(modules))
|
|
self.verify_module(modules[0], name, None)
|