199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest basics of Minidump debugging. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtimport lldb 699451b44SJordan Rupprechtimport os 799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 999451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1099451b44SJordan Rupprecht 1199451b44SJordan Rupprecht 1299451b44SJordan Rupprechtclass MiniDumpUUIDTestCase(TestBase): 1399451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1499451b44SJordan Rupprecht 1599451b44SJordan Rupprecht def verify_module(self, module, verify_path, verify_uuid): 16fac5d05eSJaroslav Sevcik # Compare the filename and the directory separately. We are avoiding 17fac5d05eSJaroslav Sevcik # SBFileSpec.fullpath because it causes a slash/backslash confusion 18d30797b4SJoseph Tremoulet # on Windows. Similarly, we compare the directories using normcase 19d30797b4SJoseph Tremoulet # because they may contain a Linux-style relative path from the 20d30797b4SJoseph Tremoulet # minidump appended to a Windows-style root path from the host. 212238dcc3SJonas Devlieghere self.assertEqual(os.path.basename(verify_path), module.GetFileSpec().basename) 22fac5d05eSJaroslav Sevcik self.assertEqual( 23d30797b4SJoseph Tremoulet os.path.normcase(os.path.dirname(verify_path)), 242238dcc3SJonas Devlieghere os.path.normcase(module.GetFileSpec().dirname or ""), 252238dcc3SJonas Devlieghere ) 26fac5d05eSJaroslav Sevcik self.assertEqual(verify_uuid, module.GetUUIDString()) 2799451b44SJordan Rupprecht 28d20aa7caSJoseph Tremoulet def get_minidump_modules(self, yaml_file, exe=None): 2999451b44SJordan Rupprecht minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp") 3099451b44SJordan Rupprecht self.yaml2obj(yaml_file, minidump_path) 31d20aa7caSJoseph Tremoulet self.target = self.dbg.CreateTarget(exe) 3299451b44SJordan Rupprecht self.process = self.target.LoadCore(minidump_path) 3399451b44SJordan Rupprecht return self.target.modules 3499451b44SJordan Rupprecht 3599451b44SJordan Rupprecht def test_zero_uuid_modules(self): 3699451b44SJordan Rupprecht """ 3799451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 3899451b44SJordan Rupprecht but contains a PDB70 value whose age is zero and whose UUID values are 3999451b44SJordan Rupprecht all zero. Prior to a fix all such modules would be duplicated to the 4099451b44SJordan Rupprecht first one since the UUIDs claimed to be valid and all zeroes. Now we 4199451b44SJordan Rupprecht ensure that the UUID is not valid for each module and that we have 4299451b44SJordan Rupprecht each of the modules in the target after loading the core 4399451b44SJordan Rupprecht """ 4499451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-zero-uuids.yaml") 4599451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 4699451b44SJordan Rupprecht self.verify_module(modules[0], "/file/does/not/exist/a", None) 4799451b44SJordan Rupprecht self.verify_module(modules[1], "/file/does/not/exist/b", None) 4899451b44SJordan Rupprecht 4999451b44SJordan Rupprecht def test_uuid_modules_no_age(self): 5099451b44SJordan Rupprecht """ 5199451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 5299451b44SJordan Rupprecht and contains a PDB70 value whose age is zero and whose UUID values are 5399451b44SJordan Rupprecht valid. Ensure we decode the UUID and don't include the age field in the UUID. 5499451b44SJordan Rupprecht """ 5599451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-no-age.yaml") 5699451b44SJordan Rupprecht modules = self.target.modules 5799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 5899451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10") 5999451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0") 6099451b44SJordan Rupprecht 6199451b44SJordan Rupprecht def test_uuid_modules_no_age_apple(self): 6299451b44SJordan Rupprecht """ 6399451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 6499451b44SJordan Rupprecht and contains a PDB70 value whose age is zero and whose UUID values are 6599451b44SJordan Rupprecht valid. Ensure we decode the UUID and don't include the age field in the UUID. 6699451b44SJordan Rupprecht Also ensure that the first uint32_t is byte swapped, along with the next 6799451b44SJordan Rupprecht two uint16_t values. Breakpad incorrectly byte swaps these values when it 6899451b44SJordan Rupprecht saves Darwin minidump files. 6999451b44SJordan Rupprecht """ 7099451b44SJordan Rupprecht modules = self.get_minidump_modules("macos-arm-uuids-no-age.yaml") 7199451b44SJordan Rupprecht modules = self.target.modules 7299451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 7399451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "04030201-0605-0807-090A-0B0C0D0E0F10") 7499451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "281E140A-3C32-5046-5A64-6E78828C96A0") 7599451b44SJordan Rupprecht 7699451b44SJordan Rupprecht def test_uuid_modules_with_age(self): 7799451b44SJordan Rupprecht """ 7899451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 7999451b44SJordan Rupprecht and contains a PDB70 value whose age is valid and whose UUID values are 8099451b44SJordan Rupprecht valid. Ensure we decode the UUID and include the age field in the UUID. 8199451b44SJordan Rupprecht """ 8299451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-with-age.yaml") 8399451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 842238dcc3SJonas Devlieghere self.verify_module( 852238dcc3SJonas Devlieghere modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-10101010" 862238dcc3SJonas Devlieghere ) 872238dcc3SJonas Devlieghere self.verify_module( 882238dcc3SJonas Devlieghere modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-20202020" 892238dcc3SJonas Devlieghere ) 9099451b44SJordan Rupprecht 9199451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_16(self): 9299451b44SJordan Rupprecht """ 9399451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 94*aa278487SEymen Ünay and contains an ELF build ID whose value is valid and is 16 bytes long. 9599451b44SJordan Rupprecht """ 9699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml") 9799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 9899451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10") 9999451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0") 10099451b44SJordan Rupprecht 10199451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_20(self): 10299451b44SJordan Rupprecht """ 10399451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 104*aa278487SEymen Ünay and contains an ELF build ID whose value is valid and is 20 bytes long. 10599451b44SJordan Rupprecht """ 10699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml") 10799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 1082238dcc3SJonas Devlieghere self.verify_module( 1092238dcc3SJonas Devlieghere modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314" 1102238dcc3SJonas Devlieghere ) 1112238dcc3SJonas Devlieghere self.verify_module( 1122238dcc3SJonas Devlieghere modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8" 1132238dcc3SJonas Devlieghere ) 11499451b44SJordan Rupprecht 11599451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_zero(self): 11699451b44SJordan Rupprecht """ 11799451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 118*aa278487SEymen Ünay and contains an ELF build ID whose value is all zero. 11999451b44SJordan Rupprecht """ 12099451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-zero.yaml") 12199451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 12299451b44SJordan Rupprecht self.verify_module(modules[0], "/not/exist/a", None) 12399451b44SJordan Rupprecht self.verify_module(modules[1], "/not/exist/b", None) 12499451b44SJordan Rupprecht 12599451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_same(self): 12699451b44SJordan Rupprecht """ 12799451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is 128*aa278487SEymen Ünay valid, and contains an ELF build ID whose value is the same. There 12999451b44SJordan Rupprecht is an assert in the PlaceholderObjectFile that was firing when we 13099451b44SJordan Rupprecht encountered this which was crashing the process that was checking 13199451b44SJordan Rupprecht if PlaceholderObjectFile.m_base was the same as the address this 13299451b44SJordan Rupprecht fake module was being loaded at. We need to ensure we don't crash 13399451b44SJordan Rupprecht in such cases and that we add both modules even though they have 13499451b44SJordan Rupprecht the same UUID. 13599451b44SJordan Rupprecht """ 13699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-same-uuids.yaml") 13799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 1382238dcc3SJonas Devlieghere self.verify_module( 1392238dcc3SJonas Devlieghere modules[0], 1402238dcc3SJonas Devlieghere "/file/does/not/exist/a", 1412238dcc3SJonas Devlieghere "11223344-1122-3344-1122-334411223344-11223344", 1422238dcc3SJonas Devlieghere ) 1432238dcc3SJonas Devlieghere self.verify_module( 1442238dcc3SJonas Devlieghere modules[1], 1452238dcc3SJonas Devlieghere "/file/does/not/exist/b", 1462238dcc3SJonas Devlieghere "11223344-1122-3344-1122-334411223344-11223344", 1472238dcc3SJonas Devlieghere ) 14899451b44SJordan Rupprecht 14999451b44SJordan Rupprecht def test_partial_uuid_match(self): 15099451b44SJordan Rupprecht """ 15199451b44SJordan Rupprecht Breakpad has been known to create minidump files using CvRecord in each 15299451b44SJordan Rupprecht module whose signature is set to PDB70 where the UUID only contains the 15399451b44SJordan Rupprecht first 16 bytes of a 20 byte ELF build ID. Code was added to 15499451b44SJordan Rupprecht ProcessMinidump.cpp to deal with this and allows partial UUID matching. 15599451b44SJordan Rupprecht 15699451b44SJordan Rupprecht This test verifies that if we have a minidump with a 16 byte UUID, that 15799451b44SJordan Rupprecht we are able to associate a symbol file with a 20 byte UUID only if the 15899451b44SJordan Rupprecht first 16 bytes match. In this case we will see the path from the file 15999451b44SJordan Rupprecht we found in the test directory and the 20 byte UUID from the actual 16099451b44SJordan Rupprecht file, not the 16 byte shortened UUID from the minidump. 16199451b44SJordan Rupprecht """ 16299451b44SJordan Rupprecht so_path = self.getBuildArtifact("libuuidmatch.so") 16399451b44SJordan Rupprecht self.yaml2obj("libuuidmatch.yaml", so_path) 16499451b44SJordan Rupprecht cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 16599451b44SJordan Rupprecht self.dbg.HandleCommand(cmd) 16699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-partial-uuids-match.yaml") 16799451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 1682238dcc3SJonas Devlieghere self.verify_module( 1692238dcc3SJonas Devlieghere modules[0], so_path, "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116" 1702238dcc3SJonas Devlieghere ) 17199451b44SJordan Rupprecht 17299451b44SJordan Rupprecht def test_partial_uuid_mismatch(self): 17399451b44SJordan Rupprecht """ 17499451b44SJordan Rupprecht Breakpad has been known to create minidump files using CvRecord in each 17599451b44SJordan Rupprecht module whose signature is set to PDB70 where the UUID only contains the 17699451b44SJordan Rupprecht first 16 bytes of a 20 byte ELF build ID. Code was added to 17799451b44SJordan Rupprecht ProcessMinidump.cpp to deal with this and allows partial UUID matching. 17899451b44SJordan Rupprecht 17999451b44SJordan Rupprecht This test verifies that if we have a minidump with a 16 byte UUID, that 18099451b44SJordan Rupprecht we are not able to associate a symbol file with a 20 byte UUID only if 18199451b44SJordan Rupprecht any of the first 16 bytes do not match. In this case we will see the UUID 18299451b44SJordan Rupprecht from the minidump file and the path from the minidump file. 18399451b44SJordan Rupprecht """ 18499451b44SJordan Rupprecht so_path = self.getBuildArtifact("libuuidmismatch.so") 18599451b44SJordan Rupprecht self.yaml2obj("libuuidmismatch.yaml", so_path) 18699451b44SJordan Rupprecht cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 18799451b44SJordan Rupprecht self.dbg.HandleCommand(cmd) 18899451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-partial-uuids-mismatch.yaml") 18999451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 1902238dcc3SJonas Devlieghere self.verify_module( 1912238dcc3SJonas Devlieghere modules[0], 19299451b44SJordan Rupprecht "/invalid/path/on/current/system/libuuidmismatch.so", 1932238dcc3SJonas Devlieghere "7295E17C-6668-9E05-CBB5-DEE5003865D5", 1942238dcc3SJonas Devlieghere ) 19599451b44SJordan Rupprecht 1960e6c9a6eSGreg Clayton def test_breakpad_hash_match(self): 1970e6c9a6eSGreg Clayton """ 1980e6c9a6eSGreg Clayton Breakpad creates minidump files using CvRecord in each module whose 1990e6c9a6eSGreg Clayton signature is set to PDB70 where the UUID is a hash generated by 2000e6c9a6eSGreg Clayton breakpad of the .text section. This is only done when the 2010e6c9a6eSGreg Clayton executable has no ELF build ID. 2020e6c9a6eSGreg Clayton 2030e6c9a6eSGreg Clayton This test verifies that if we have a minidump with a 16 byte UUID, 2040e6c9a6eSGreg Clayton that we are able to associate a symbol file with no ELF build ID 2050e6c9a6eSGreg Clayton and match it up by hashing the .text section. 2060e6c9a6eSGreg Clayton """ 2070e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 2080e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad.yaml", so_path) 2090e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 2100e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 2110e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 2120e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 2130e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 2140e6c9a6eSGreg Clayton # will check that this matches. 2150e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "D9C480E8") 2160e6c9a6eSGreg Clayton 217d30797b4SJoseph Tremoulet def test_breakpad_hash_match_sysroot(self): 218d30797b4SJoseph Tremoulet """ 219d30797b4SJoseph Tremoulet Check that we can match the breakpad .text section hash when the 220d30797b4SJoseph Tremoulet module is located under a user-provided sysroot. 221d30797b4SJoseph Tremoulet """ 222d30797b4SJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 223d30797b4SJoseph Tremoulet # Create the directory under the sysroot where the minidump reports 224d30797b4SJoseph Tremoulet # the module. 2252238dcc3SJonas Devlieghere so_dir = os.path.join( 2262238dcc3SJonas Devlieghere sysroot_path, "invalid", "path", "on", "current", "system" 2272238dcc3SJonas Devlieghere ) 228d30797b4SJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 229d30797b4SJoseph Tremoulet lldbutil.mkdir_p(so_dir) 230d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 231d30797b4SJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 232d30797b4SJoseph Tremoulet modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 233d30797b4SJoseph Tremoulet self.assertEqual(1, len(modules)) 234d30797b4SJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 235d30797b4SJoseph Tremoulet # will check that this matches. 236d30797b4SJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 237d30797b4SJoseph Tremoulet 238d30797b4SJoseph Tremoulet def test_breakpad_hash_match_sysroot_decoy(self): 239d30797b4SJoseph Tremoulet """ 240d30797b4SJoseph Tremoulet Check that we can match the breakpad .text section hash when there is 241d30797b4SJoseph Tremoulet a module with the right name but wrong contents under a user-provided 242d30797b4SJoseph Tremoulet sysroot, and the right module is at the given search path.. 243d30797b4SJoseph Tremoulet """ 244d30797b4SJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 245d30797b4SJoseph Tremoulet # Create the directory under the sysroot where the minidump reports 246d30797b4SJoseph Tremoulet # the module. 2472238dcc3SJonas Devlieghere decoy_dir = os.path.join( 2482238dcc3SJonas Devlieghere sysroot_path, "invalid", "path", "on", "current", "system" 2492238dcc3SJonas Devlieghere ) 250d30797b4SJoseph Tremoulet decoy_path = os.path.join(decoy_dir, "libbreakpad.so") 251d30797b4SJoseph Tremoulet lldbutil.mkdir_p(decoy_dir) 252d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad-decoy.yaml", decoy_path) 253d30797b4SJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 254d30797b4SJoseph Tremoulet so_dir = os.path.join(self.getBuildDir(), "searchpath_dir") 255d30797b4SJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 256d30797b4SJoseph Tremoulet lldbutil.mkdir_p(so_dir) 257d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 258d30797b4SJoseph Tremoulet self.runCmd('settings set target.exec-search-paths "%s"' % so_dir) 259d30797b4SJoseph Tremoulet modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 260d30797b4SJoseph Tremoulet self.assertEqual(1, len(modules)) 261d30797b4SJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 262d30797b4SJoseph Tremoulet # will check that this matches. 263d30797b4SJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 264d30797b4SJoseph Tremoulet 2650e6c9a6eSGreg Clayton def test_breakpad_overflow_hash_match(self): 2660e6c9a6eSGreg Clayton """ 2670e6c9a6eSGreg Clayton This is a similar to test_breakpad_hash_match, but it verifies that 2680e6c9a6eSGreg Clayton if the .text section does not end on a 16 byte boundary, then it 2690e6c9a6eSGreg Clayton will overflow into the next section's data by up to 15 bytes. This 2700e6c9a6eSGreg Clayton verifies that we are able to match what breakpad does as it will do 2710e6c9a6eSGreg Clayton this. 2720e6c9a6eSGreg Clayton """ 2730e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 2740e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad-overflow.yaml", so_path) 2750e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 2760e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 2770e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 2780e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 2790e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 2800e6c9a6eSGreg Clayton # will check that this matches. 2810e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "48EB9FD7") 2820e6c9a6eSGreg Clayton 283d20aa7caSJoseph Tremoulet def test_breakpad_hash_match_exe_outside_sysroot(self): 284d20aa7caSJoseph Tremoulet """ 285d20aa7caSJoseph Tremoulet Check that we can match the breakpad .text section hash when the 286d20aa7caSJoseph Tremoulet module is specified as the exe during launch, and a syroot is 287d20aa7caSJoseph Tremoulet provided, which does not contain the exe. 288d20aa7caSJoseph Tremoulet """ 289d20aa7caSJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 290d20aa7caSJoseph Tremoulet lldbutil.mkdir_p(sysroot_path) 291d20aa7caSJoseph Tremoulet so_dir = os.path.join(self.getBuildDir(), "binary") 292d20aa7caSJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 293d20aa7caSJoseph Tremoulet lldbutil.mkdir_p(so_dir) 294d20aa7caSJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 295d20aa7caSJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 2962238dcc3SJonas Devlieghere modules = self.get_minidump_modules( 2972238dcc3SJonas Devlieghere "linux-arm-breakpad-uuid-match.yaml", so_path 2982238dcc3SJonas Devlieghere ) 299d20aa7caSJoseph Tremoulet self.assertEqual(1, len(modules)) 300d20aa7caSJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 301d20aa7caSJoseph Tremoulet # will check that this matches. 302d20aa7caSJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 3030e6c9a6eSGreg Clayton 3040e6c9a6eSGreg Clayton def test_facebook_hash_match(self): 3050e6c9a6eSGreg Clayton """ 3060e6c9a6eSGreg Clayton Breakpad creates minidump files using CvRecord in each module whose 3070e6c9a6eSGreg Clayton signature is set to PDB70 where the UUID is a hash generated by 3080e6c9a6eSGreg Clayton breakpad of the .text section and Facebook modified this hash to 3090e6c9a6eSGreg Clayton avoid collisions. This is only done when the executable has no ELF 3100e6c9a6eSGreg Clayton build ID. 3110e6c9a6eSGreg Clayton 3120e6c9a6eSGreg Clayton This test verifies that if we have a minidump with a 16 byte UUID, 3130e6c9a6eSGreg Clayton that we are able to associate a symbol file with no ELF build ID 3140e6c9a6eSGreg Clayton and match it up by hashing the .text section like Facebook does. 3150e6c9a6eSGreg Clayton """ 3160e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 3170e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad.yaml", so_path) 3180e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 3190e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 3200e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-facebook-uuid-match.yaml") 3210e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 3220e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 3230e6c9a6eSGreg Clayton # will check that this matches. 3240e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "D9C480E8") 3250e6c9a6eSGreg Clayton 32699451b44SJordan Rupprecht def test_relative_module_name(self): 32799451b44SJordan Rupprecht old_cwd = os.getcwd() 32899451b44SJordan Rupprecht self.addTearDownHook(lambda: os.chdir(old_cwd)) 32999451b44SJordan Rupprecht os.chdir(self.getBuildDir()) 33099451b44SJordan Rupprecht name = "file-with-a-name-unlikely-to-exist-in-the-current-directory.so" 33199451b44SJordan Rupprecht open(name, "a").close() 33299451b44SJordan Rupprecht modules = self.get_minidump_modules( 3332238dcc3SJonas Devlieghere self.getSourcePath("relative_module_name.yaml") 3342238dcc3SJonas Devlieghere ) 33599451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 33699451b44SJordan Rupprecht self.verify_module(modules[0], name, None) 3371beffc18SJaroslav Sevcik 3381beffc18SJaroslav Sevcik def test_add_module_build_id_16(self): 3391beffc18SJaroslav Sevcik """ 3401beffc18SJaroslav Sevcik Test that adding module with 16 byte UUID returns the existing 3411beffc18SJaroslav Sevcik module or fails. 3421beffc18SJaroslav Sevcik """ 3431beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml") 3441beffc18SJaroslav Sevcik self.assertEqual(2, len(modules)) 3451beffc18SJaroslav Sevcik 3461beffc18SJaroslav Sevcik # Add the existing modules. 3472238dcc3SJonas Devlieghere self.assertEqual( 3482238dcc3SJonas Devlieghere modules[0], 3492238dcc3SJonas Devlieghere self.target.AddModule( 3502238dcc3SJonas Devlieghere "/some/local/a", "", "01020304-0506-0708-090A-0B0C0D0E0F10" 3512238dcc3SJonas Devlieghere ), 3522238dcc3SJonas Devlieghere ) 3532238dcc3SJonas Devlieghere self.assertEqual( 3542238dcc3SJonas Devlieghere modules[1], 3552238dcc3SJonas Devlieghere self.target.AddModule( 3562238dcc3SJonas Devlieghere "/some/local/b", "", "0A141E28-323C-4650-5A64-6E78828C96A0" 3572238dcc3SJonas Devlieghere ), 3582238dcc3SJonas Devlieghere ) 3591beffc18SJaroslav Sevcik 3601beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 3611beffc18SJaroslav Sevcik self.assertFalse( 3621beffc18SJaroslav Sevcik self.target.AddModule( 3632238dcc3SJonas Devlieghere "a", "", "12345678-1234-1234-1234-123456789ABC" 3642238dcc3SJonas Devlieghere ).IsValid() 3652238dcc3SJonas Devlieghere ) 3661beffc18SJaroslav Sevcik self.assertFalse( 3671beffc18SJaroslav Sevcik self.target.AddModule( 3682238dcc3SJonas Devlieghere "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-12345678" 3692238dcc3SJonas Devlieghere ).IsValid() 3702238dcc3SJonas Devlieghere ) 3711beffc18SJaroslav Sevcik 3721beffc18SJaroslav Sevcik def test_add_module_build_id_20(self): 3731beffc18SJaroslav Sevcik """ 3741beffc18SJaroslav Sevcik Test that adding module with 20 byte UUID returns the existing 3751beffc18SJaroslav Sevcik module or fails. 3761beffc18SJaroslav Sevcik """ 3771beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml") 3781beffc18SJaroslav Sevcik 3791beffc18SJaroslav Sevcik # Add the existing modules. 3802238dcc3SJonas Devlieghere self.assertEqual( 3812238dcc3SJonas Devlieghere modules[0], 3822238dcc3SJonas Devlieghere self.target.AddModule( 3832238dcc3SJonas Devlieghere "/some/local/a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314" 3842238dcc3SJonas Devlieghere ), 3852238dcc3SJonas Devlieghere ) 3862238dcc3SJonas Devlieghere self.assertEqual( 3872238dcc3SJonas Devlieghere modules[1], 3882238dcc3SJonas Devlieghere self.target.AddModule( 3892238dcc3SJonas Devlieghere "/some/local/b", "", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8" 3902238dcc3SJonas Devlieghere ), 3912238dcc3SJonas Devlieghere ) 3921beffc18SJaroslav Sevcik 3931beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 3941beffc18SJaroslav Sevcik self.assertFalse( 3951beffc18SJaroslav Sevcik self.target.AddModule( 3962238dcc3SJonas Devlieghere "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10" 3972238dcc3SJonas Devlieghere ).IsValid() 3982238dcc3SJonas Devlieghere ) 3991beffc18SJaroslav Sevcik self.assertFalse( 4001beffc18SJaroslav Sevcik self.target.AddModule( 4012238dcc3SJonas Devlieghere "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-12345678" 4022238dcc3SJonas Devlieghere ).IsValid() 4032238dcc3SJonas Devlieghere ) 4041beffc18SJaroslav Sevcik 4051beffc18SJaroslav Sevcik def test_add_module_build_id_4(self): 4061beffc18SJaroslav Sevcik """ 4071beffc18SJaroslav Sevcik Test that adding module with 4 byte UUID returns the existing 4081beffc18SJaroslav Sevcik module or fails. 4091beffc18SJaroslav Sevcik """ 4101beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-4.yaml") 4111beffc18SJaroslav Sevcik 4121beffc18SJaroslav Sevcik # Add the existing modules. 4132238dcc3SJonas Devlieghere self.assertEqual( 4142238dcc3SJonas Devlieghere modules[0], self.target.AddModule("/some/local/a.so", "", "01020304") 4152238dcc3SJonas Devlieghere ) 4162238dcc3SJonas Devlieghere self.assertEqual( 4172238dcc3SJonas Devlieghere modules[1], self.target.AddModule("/some/local/b.so", "", "0A141E28") 4182238dcc3SJonas Devlieghere ) 4191beffc18SJaroslav Sevcik 4201beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 4211beffc18SJaroslav Sevcik self.assertFalse( 4221beffc18SJaroslav Sevcik self.target.AddModule( 4232238dcc3SJonas Devlieghere "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10" 4242238dcc3SJonas Devlieghere ).IsValid() 4252238dcc3SJonas Devlieghere ) 4261beffc18SJaroslav Sevcik self.assertFalse(self.target.AddModule("a", "", "01020305").IsValid()) 4271beffc18SJaroslav Sevcik 4281beffc18SJaroslav Sevcik def test_remove_placeholder_add_real_module(self): 4291beffc18SJaroslav Sevcik """ 4301beffc18SJaroslav Sevcik Test that removing a placeholder module and adding back the real 4311beffc18SJaroslav Sevcik module succeeds. 4321beffc18SJaroslav Sevcik """ 4331beffc18SJaroslav Sevcik so_path = self.getBuildArtifact("libuuidmatch.so") 4341beffc18SJaroslav Sevcik self.yaml2obj("libuuidmatch.yaml", so_path) 4351beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-match.yaml") 4361beffc18SJaroslav Sevcik 4372238dcc3SJonas Devlieghere uuid = "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116" 4381beffc18SJaroslav Sevcik self.assertEqual(1, len(modules)) 4391beffc18SJaroslav Sevcik self.verify_module(modules[0], "/target/path/libuuidmatch.so", uuid) 4401beffc18SJaroslav Sevcik 4411beffc18SJaroslav Sevcik self.target.RemoveModule(modules[0]) 4421beffc18SJaroslav Sevcik new_module = self.target.AddModule(so_path, "", uuid) 4431beffc18SJaroslav Sevcik 4441beffc18SJaroslav Sevcik self.verify_module(new_module, so_path, uuid) 4451beffc18SJaroslav Sevcik self.assertEqual(new_module, self.target.modules[0]) 4461beffc18SJaroslav Sevcik self.assertEqual(1, len(self.target.modules)) 447