2 Test basics of Minidump debugging.
5 from six import iteritems
10 from lldbsuite.test.decorators import *
11 from lldbsuite.test.lldbtest import *
12 from lldbsuite.test import lldbutil
15 class MiniDumpUUIDTestCase(TestBase):
17 mydir = TestBase.compute_mydir(__file__)
19 NO_DEBUG_INFO_TESTCASE = True
22 super(MiniDumpUUIDTestCase, self).setUp()
23 self._initial_platform = lldb.DBG.GetSelectedPlatform()
26 lldb.DBG.SetSelectedPlatform(self._initial_platform)
27 super(MiniDumpUUIDTestCase, self).tearDown()
29 def verify_module(self, module, verify_path, verify_uuid):
30 uuid = module.GetUUIDString()
31 self.assertEqual(verify_path, module.GetFileSpec().fullpath)
32 self.assertEqual(verify_uuid, uuid)
34 def get_minidump_modules(self, yaml_file):
35 minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp")
36 self.yaml2obj(yaml_file, minidump_path)
37 self.target = self.dbg.CreateTarget(None)
38 self.process = self.target.LoadCore(minidump_path)
39 return self.target.modules
41 def test_zero_uuid_modules(self):
43 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
44 but contains a PDB70 value whose age is zero and whose UUID values are
45 all zero. Prior to a fix all such modules would be duplicated to the
46 first one since the UUIDs claimed to be valid and all zeroes. Now we
47 ensure that the UUID is not valid for each module and that we have
48 each of the modules in the target after loading the core
50 modules = self.get_minidump_modules("linux-arm-zero-uuids.yaml")
51 self.assertEqual(2, len(modules))
52 self.verify_module(modules[0], "/file/does/not/exist/a", None)
53 self.verify_module(modules[1], "/file/does/not/exist/b", None)
55 def test_uuid_modules_no_age(self):
57 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
58 and contains a PDB70 value whose age is zero and whose UUID values are
59 valid. Ensure we decode the UUID and don't include the age field in the UUID.
61 modules = self.get_minidump_modules("linux-arm-uuids-no-age.yaml")
62 modules = self.target.modules
63 self.assertEqual(2, len(modules))
64 self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10")
65 self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0")
67 def test_uuid_modules_no_age_apple(self):
69 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
70 and contains a PDB70 value whose age is zero and whose UUID values are
71 valid. Ensure we decode the UUID and don't include the age field in the UUID.
72 Also ensure that the first uint32_t is byte swapped, along with the next
73 two uint16_t values. Breakpad incorrectly byte swaps these values when it
74 saves Darwin minidump files.
76 modules = self.get_minidump_modules("macos-arm-uuids-no-age.yaml")
77 modules = self.target.modules
78 self.assertEqual(2, len(modules))
79 self.verify_module(modules[0], "/tmp/a", "04030201-0605-0807-090A-0B0C0D0E0F10")
80 self.verify_module(modules[1], "/tmp/b", "281E140A-3C32-5046-5A64-6E78828C96A0")
82 def test_uuid_modules_with_age(self):
84 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
85 and contains a PDB70 value whose age is valid and whose UUID values are
86 valid. Ensure we decode the UUID and include the age field in the UUID.
88 modules = self.get_minidump_modules("linux-arm-uuids-with-age.yaml")
89 self.assertEqual(2, len(modules))
90 self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-10101010")
91 self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-20202020")
93 def test_uuid_modules_elf_build_id_16(self):
95 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
96 and contains a ELF build ID whose value is valid and is 16 bytes long.
98 modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml")
99 self.assertEqual(2, len(modules))
100 self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10")
101 self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0")
103 def test_uuid_modules_elf_build_id_20(self):
105 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
106 and contains a ELF build ID whose value is valid and is 20 bytes long.
108 modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml")
109 self.assertEqual(2, len(modules))
110 self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314")
111 self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8")
113 def test_uuid_modules_elf_build_id_zero(self):
115 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid,
116 and contains a ELF build ID whose value is all zero.
118 modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-zero.yaml")
119 self.assertEqual(2, len(modules))
120 self.verify_module(modules[0], "/not/exist/a", None)
121 self.verify_module(modules[1], "/not/exist/b", None)
123 def test_uuid_modules_elf_build_id_same(self):
125 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is
126 valid, and contains a ELF build ID whose value is the same. There
127 is an assert in the PlaceholderObjectFile that was firing when we
128 encountered this which was crashing the process that was checking
129 if PlaceholderObjectFile.m_base was the same as the address this
130 fake module was being loaded at. We need to ensure we don't crash
131 in such cases and that we add both modules even though they have
134 modules = self.get_minidump_modules("linux-arm-same-uuids.yaml")
135 self.assertEqual(2, len(modules))
136 self.verify_module(modules[0], "/file/does/not/exist/a",
137 '11223344-1122-3344-1122-334411223344-11223344')
138 self.verify_module(modules[1], "/file/does/not/exist/b",
139 '11223344-1122-3344-1122-334411223344-11223344')
141 @expectedFailureAll(oslist=["windows"])
142 def test_partial_uuid_match(self):
144 Breakpad has been known to create minidump files using CvRecord in each
145 module whose signature is set to PDB70 where the UUID only contains the
146 first 16 bytes of a 20 byte ELF build ID. Code was added to
147 ProcessMinidump.cpp to deal with this and allows partial UUID matching.
149 This test verifies that if we have a minidump with a 16 byte UUID, that
150 we are able to associate a symbol file with a 20 byte UUID only if the
151 first 16 bytes match. In this case we will see the path from the file
152 we found in the test directory and the 20 byte UUID from the actual
153 file, not the 16 byte shortened UUID from the minidump.
155 so_path = self.getBuildArtifact("libuuidmatch.so")
156 self.yaml2obj("libuuidmatch.yaml", so_path)
157 cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path))
158 self.dbg.HandleCommand(cmd)
159 modules = self.get_minidump_modules("linux-arm-partial-uuids-match.yaml")
160 self.assertEqual(1, len(modules))
161 self.verify_module(modules[0], so_path,
162 "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116")
164 def test_partial_uuid_mismatch(self):
166 Breakpad has been known to create minidump files using CvRecord in each
167 module whose signature is set to PDB70 where the UUID only contains the
168 first 16 bytes of a 20 byte ELF build ID. Code was added to
169 ProcessMinidump.cpp to deal with this and allows partial UUID matching.
171 This test verifies that if we have a minidump with a 16 byte UUID, that
172 we are not able to associate a symbol file with a 20 byte UUID only if
173 any of the first 16 bytes do not match. In this case we will see the UUID
174 from the minidump file and the path from the minidump file.
176 so_path = self.getBuildArtifact("libuuidmismatch.so")
177 self.yaml2obj("libuuidmismatch.yaml", so_path)
178 cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path))
179 self.dbg.HandleCommand(cmd)
180 modules = self.get_minidump_modules("linux-arm-partial-uuids-mismatch.yaml")
181 self.assertEqual(1, len(modules))
182 self.verify_module(modules[0],
183 "/invalid/path/on/current/system/libuuidmismatch.so",
184 "7295E17C-6668-9E05-CBB5-DEE5003865D5")
186 def test_relative_module_name(self):
187 old_cwd = os.getcwd()
188 self.addTearDownHook(lambda: os.chdir(old_cwd))
189 os.chdir(self.getBuildDir())
190 name = "file-with-a-name-unlikely-to-exist-in-the-current-directory.so"
191 open(name, "a").close()
192 modules = self.get_minidump_modules(
193 self.getSourcePath("relative_module_name.yaml"))
194 self.assertEqual(1, len(modules))
195 self.verify_module(modules[0], name, None)