1""" 2Test basics of Minidump debugging. 3""" 4 5from six import iteritems 6 7 8import lldb 9import os 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12from lldbsuite.test import lldbutil 13 14 15class MiniDumpUUIDTestCase(TestBase): 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 NO_DEBUG_INFO_TESTCASE = True 20 21 def setUp(self): 22 super(MiniDumpUUIDTestCase, self).setUp() 23 self._initial_platform = lldb.DBG.GetSelectedPlatform() 24 25 def tearDown(self): 26 lldb.DBG.SetSelectedPlatform(self._initial_platform) 27 super(MiniDumpUUIDTestCase, self).tearDown() 28 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) 33 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 40 41 def test_zero_uuid_modules(self): 42 """ 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 49 """ 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) 54 55 def test_uuid_modules_no_age(self): 56 """ 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. 60 """ 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") 66 67 def test_uuid_modules_no_age_apple(self): 68 """ 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. 75 """ 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") 81 82 def test_uuid_modules_with_age(self): 83 """ 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. 87 """ 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") 92 93 def test_uuid_modules_elf_build_id_16(self): 94 """ 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. 97 """ 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") 102 103 def test_uuid_modules_elf_build_id_20(self): 104 """ 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. 107 """ 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") 112 113 def test_uuid_modules_elf_build_id_zero(self): 114 """ 115 Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 116 and contains a ELF build ID whose value is all zero. 117 """ 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) 122 123 def test_uuid_modules_elf_build_id_same(self): 124 """ 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 132 the same UUID. 133 """ 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') 140 141 @expectedFailureAll(oslist=["windows"]) 142 def test_partial_uuid_match(self): 143 """ 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. 148 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. 154 """ 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") 163 164 def test_partial_uuid_mismatch(self): 165 """ 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. 170 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. 175 """ 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") 185 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) 196