199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest basics of Minidump debugging. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtfrom six import iteritems 699451b44SJordan Rupprecht 799451b44SJordan Rupprecht 899451b44SJordan Rupprechtimport lldb 999451b44SJordan Rupprechtimport os 1099451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 1199451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1299451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1399451b44SJordan Rupprecht 1499451b44SJordan Rupprecht 1599451b44SJordan Rupprechtclass MiniDumpUUIDTestCase(TestBase): 1699451b44SJordan Rupprecht 1799451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprecht def verify_module(self, module, verify_path, verify_uuid): 20fac5d05eSJaroslav Sevcik # Compare the filename and the directory separately. We are avoiding 21fac5d05eSJaroslav Sevcik # SBFileSpec.fullpath because it causes a slash/backslash confusion 22d30797b4SJoseph Tremoulet # on Windows. Similarly, we compare the directories using normcase 23d30797b4SJoseph Tremoulet # because they may contain a Linux-style relative path from the 24d30797b4SJoseph Tremoulet # minidump appended to a Windows-style root path from the host. 25fac5d05eSJaroslav Sevcik self.assertEqual( 26fac5d05eSJaroslav Sevcik os.path.basename(verify_path), module.GetFileSpec().basename) 27fac5d05eSJaroslav Sevcik self.assertEqual( 28d30797b4SJoseph Tremoulet os.path.normcase(os.path.dirname(verify_path)), 29d30797b4SJoseph Tremoulet os.path.normcase(module.GetFileSpec().dirname or "")) 30fac5d05eSJaroslav Sevcik self.assertEqual(verify_uuid, module.GetUUIDString()) 3199451b44SJordan Rupprecht 32*d20aa7caSJoseph Tremoulet def get_minidump_modules(self, yaml_file, exe = None): 3399451b44SJordan Rupprecht minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp") 3499451b44SJordan Rupprecht self.yaml2obj(yaml_file, minidump_path) 35*d20aa7caSJoseph Tremoulet self.target = self.dbg.CreateTarget(exe) 3699451b44SJordan Rupprecht self.process = self.target.LoadCore(minidump_path) 3799451b44SJordan Rupprecht return self.target.modules 3899451b44SJordan Rupprecht 3999451b44SJordan Rupprecht def test_zero_uuid_modules(self): 4099451b44SJordan Rupprecht """ 4199451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 4299451b44SJordan Rupprecht but contains a PDB70 value whose age is zero and whose UUID values are 4399451b44SJordan Rupprecht all zero. Prior to a fix all such modules would be duplicated to the 4499451b44SJordan Rupprecht first one since the UUIDs claimed to be valid and all zeroes. Now we 4599451b44SJordan Rupprecht ensure that the UUID is not valid for each module and that we have 4699451b44SJordan Rupprecht each of the modules in the target after loading the core 4799451b44SJordan Rupprecht """ 4899451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-zero-uuids.yaml") 4999451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 5099451b44SJordan Rupprecht self.verify_module(modules[0], "/file/does/not/exist/a", None) 5199451b44SJordan Rupprecht self.verify_module(modules[1], "/file/does/not/exist/b", None) 5299451b44SJordan Rupprecht 5399451b44SJordan Rupprecht def test_uuid_modules_no_age(self): 5499451b44SJordan Rupprecht """ 5599451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 5699451b44SJordan Rupprecht and contains a PDB70 value whose age is zero and whose UUID values are 5799451b44SJordan Rupprecht valid. Ensure we decode the UUID and don't include the age field in the UUID. 5899451b44SJordan Rupprecht """ 5999451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-no-age.yaml") 6099451b44SJordan Rupprecht modules = self.target.modules 6199451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 6299451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10") 6399451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0") 6499451b44SJordan Rupprecht 6599451b44SJordan Rupprecht def test_uuid_modules_no_age_apple(self): 6699451b44SJordan Rupprecht """ 6799451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 6899451b44SJordan Rupprecht and contains a PDB70 value whose age is zero and whose UUID values are 6999451b44SJordan Rupprecht valid. Ensure we decode the UUID and don't include the age field in the UUID. 7099451b44SJordan Rupprecht Also ensure that the first uint32_t is byte swapped, along with the next 7199451b44SJordan Rupprecht two uint16_t values. Breakpad incorrectly byte swaps these values when it 7299451b44SJordan Rupprecht saves Darwin minidump files. 7399451b44SJordan Rupprecht """ 7499451b44SJordan Rupprecht modules = self.get_minidump_modules("macos-arm-uuids-no-age.yaml") 7599451b44SJordan Rupprecht modules = self.target.modules 7699451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 7799451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "04030201-0605-0807-090A-0B0C0D0E0F10") 7899451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "281E140A-3C32-5046-5A64-6E78828C96A0") 7999451b44SJordan Rupprecht 8099451b44SJordan Rupprecht def test_uuid_modules_with_age(self): 8199451b44SJordan Rupprecht """ 8299451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 8399451b44SJordan Rupprecht and contains a PDB70 value whose age is valid and whose UUID values are 8499451b44SJordan Rupprecht valid. Ensure we decode the UUID and include the age field in the UUID. 8599451b44SJordan Rupprecht """ 8699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-with-age.yaml") 8799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 8899451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-10101010") 8999451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-20202020") 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, 9499451b44SJordan Rupprecht and contains a 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, 10499451b44SJordan Rupprecht and contains a 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)) 10899451b44SJordan Rupprecht self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314") 10999451b44SJordan Rupprecht self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8") 11099451b44SJordan Rupprecht 11199451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_zero(self): 11299451b44SJordan Rupprecht """ 11399451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, 11499451b44SJordan Rupprecht and contains a ELF build ID whose value is all zero. 11599451b44SJordan Rupprecht """ 11699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-zero.yaml") 11799451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 11899451b44SJordan Rupprecht self.verify_module(modules[0], "/not/exist/a", None) 11999451b44SJordan Rupprecht self.verify_module(modules[1], "/not/exist/b", None) 12099451b44SJordan Rupprecht 12199451b44SJordan Rupprecht def test_uuid_modules_elf_build_id_same(self): 12299451b44SJordan Rupprecht """ 12399451b44SJordan Rupprecht Test multiple modules having a MINIDUMP_MODULE.CvRecord that is 12499451b44SJordan Rupprecht valid, and contains a ELF build ID whose value is the same. There 12599451b44SJordan Rupprecht is an assert in the PlaceholderObjectFile that was firing when we 12699451b44SJordan Rupprecht encountered this which was crashing the process that was checking 12799451b44SJordan Rupprecht if PlaceholderObjectFile.m_base was the same as the address this 12899451b44SJordan Rupprecht fake module was being loaded at. We need to ensure we don't crash 12999451b44SJordan Rupprecht in such cases and that we add both modules even though they have 13099451b44SJordan Rupprecht the same UUID. 13199451b44SJordan Rupprecht """ 13299451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-same-uuids.yaml") 13399451b44SJordan Rupprecht self.assertEqual(2, len(modules)) 13499451b44SJordan Rupprecht self.verify_module(modules[0], "/file/does/not/exist/a", 13599451b44SJordan Rupprecht '11223344-1122-3344-1122-334411223344-11223344') 13699451b44SJordan Rupprecht self.verify_module(modules[1], "/file/does/not/exist/b", 13799451b44SJordan Rupprecht '11223344-1122-3344-1122-334411223344-11223344') 13899451b44SJordan Rupprecht 13999451b44SJordan Rupprecht def test_partial_uuid_match(self): 14099451b44SJordan Rupprecht """ 14199451b44SJordan Rupprecht Breakpad has been known to create minidump files using CvRecord in each 14299451b44SJordan Rupprecht module whose signature is set to PDB70 where the UUID only contains the 14399451b44SJordan Rupprecht first 16 bytes of a 20 byte ELF build ID. Code was added to 14499451b44SJordan Rupprecht ProcessMinidump.cpp to deal with this and allows partial UUID matching. 14599451b44SJordan Rupprecht 14699451b44SJordan Rupprecht This test verifies that if we have a minidump with a 16 byte UUID, that 14799451b44SJordan Rupprecht we are able to associate a symbol file with a 20 byte UUID only if the 14899451b44SJordan Rupprecht first 16 bytes match. In this case we will see the path from the file 14999451b44SJordan Rupprecht we found in the test directory and the 20 byte UUID from the actual 15099451b44SJordan Rupprecht file, not the 16 byte shortened UUID from the minidump. 15199451b44SJordan Rupprecht """ 15299451b44SJordan Rupprecht so_path = self.getBuildArtifact("libuuidmatch.so") 15399451b44SJordan Rupprecht self.yaml2obj("libuuidmatch.yaml", so_path) 15499451b44SJordan Rupprecht cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 15599451b44SJordan Rupprecht self.dbg.HandleCommand(cmd) 15699451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-partial-uuids-match.yaml") 15799451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 15899451b44SJordan Rupprecht self.verify_module(modules[0], so_path, 15999451b44SJordan Rupprecht "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116") 16099451b44SJordan Rupprecht 16199451b44SJordan Rupprecht def test_partial_uuid_mismatch(self): 16299451b44SJordan Rupprecht """ 16399451b44SJordan Rupprecht Breakpad has been known to create minidump files using CvRecord in each 16499451b44SJordan Rupprecht module whose signature is set to PDB70 where the UUID only contains the 16599451b44SJordan Rupprecht first 16 bytes of a 20 byte ELF build ID. Code was added to 16699451b44SJordan Rupprecht ProcessMinidump.cpp to deal with this and allows partial UUID matching. 16799451b44SJordan Rupprecht 16899451b44SJordan Rupprecht This test verifies that if we have a minidump with a 16 byte UUID, that 16999451b44SJordan Rupprecht we are not able to associate a symbol file with a 20 byte UUID only if 17099451b44SJordan Rupprecht any of the first 16 bytes do not match. In this case we will see the UUID 17199451b44SJordan Rupprecht from the minidump file and the path from the minidump file. 17299451b44SJordan Rupprecht """ 17399451b44SJordan Rupprecht so_path = self.getBuildArtifact("libuuidmismatch.so") 17499451b44SJordan Rupprecht self.yaml2obj("libuuidmismatch.yaml", so_path) 17599451b44SJordan Rupprecht cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 17699451b44SJordan Rupprecht self.dbg.HandleCommand(cmd) 17799451b44SJordan Rupprecht modules = self.get_minidump_modules("linux-arm-partial-uuids-mismatch.yaml") 17899451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 17999451b44SJordan Rupprecht self.verify_module(modules[0], 18099451b44SJordan Rupprecht "/invalid/path/on/current/system/libuuidmismatch.so", 18199451b44SJordan Rupprecht "7295E17C-6668-9E05-CBB5-DEE5003865D5") 18299451b44SJordan Rupprecht 1830e6c9a6eSGreg Clayton def test_breakpad_hash_match(self): 1840e6c9a6eSGreg Clayton """ 1850e6c9a6eSGreg Clayton Breakpad creates minidump files using CvRecord in each module whose 1860e6c9a6eSGreg Clayton signature is set to PDB70 where the UUID is a hash generated by 1870e6c9a6eSGreg Clayton breakpad of the .text section. This is only done when the 1880e6c9a6eSGreg Clayton executable has no ELF build ID. 1890e6c9a6eSGreg Clayton 1900e6c9a6eSGreg Clayton This test verifies that if we have a minidump with a 16 byte UUID, 1910e6c9a6eSGreg Clayton that we are able to associate a symbol file with no ELF build ID 1920e6c9a6eSGreg Clayton and match it up by hashing the .text section. 1930e6c9a6eSGreg Clayton """ 1940e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 1950e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad.yaml", so_path) 1960e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 1970e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 1980e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 1990e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 2000e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 2010e6c9a6eSGreg Clayton # will check that this matches. 2020e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "D9C480E8") 2030e6c9a6eSGreg Clayton 204d30797b4SJoseph Tremoulet def test_breakpad_hash_match_sysroot(self): 205d30797b4SJoseph Tremoulet """ 206d30797b4SJoseph Tremoulet Check that we can match the breakpad .text section hash when the 207d30797b4SJoseph Tremoulet module is located under a user-provided sysroot. 208d30797b4SJoseph Tremoulet """ 209d30797b4SJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 210d30797b4SJoseph Tremoulet # Create the directory under the sysroot where the minidump reports 211d30797b4SJoseph Tremoulet # the module. 212d30797b4SJoseph Tremoulet so_dir = os.path.join(sysroot_path, "invalid", "path", "on", "current", "system") 213d30797b4SJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 214d30797b4SJoseph Tremoulet lldbutil.mkdir_p(so_dir) 215d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 216d30797b4SJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 217d30797b4SJoseph Tremoulet modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 218d30797b4SJoseph Tremoulet self.assertEqual(1, len(modules)) 219d30797b4SJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 220d30797b4SJoseph Tremoulet # will check that this matches. 221d30797b4SJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 222d30797b4SJoseph Tremoulet 223d30797b4SJoseph Tremoulet def test_breakpad_hash_match_sysroot_decoy(self): 224d30797b4SJoseph Tremoulet """ 225d30797b4SJoseph Tremoulet Check that we can match the breakpad .text section hash when there is 226d30797b4SJoseph Tremoulet a module with the right name but wrong contents under a user-provided 227d30797b4SJoseph Tremoulet sysroot, and the right module is at the given search path.. 228d30797b4SJoseph Tremoulet """ 229d30797b4SJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 230d30797b4SJoseph Tremoulet # Create the directory under the sysroot where the minidump reports 231d30797b4SJoseph Tremoulet # the module. 232d30797b4SJoseph Tremoulet decoy_dir = os.path.join(sysroot_path, "invalid", "path", "on", "current", "system") 233d30797b4SJoseph Tremoulet decoy_path = os.path.join(decoy_dir, "libbreakpad.so") 234d30797b4SJoseph Tremoulet lldbutil.mkdir_p(decoy_dir) 235d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad-decoy.yaml", decoy_path) 236d30797b4SJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 237d30797b4SJoseph Tremoulet so_dir = os.path.join(self.getBuildDir(), "searchpath_dir") 238d30797b4SJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 239d30797b4SJoseph Tremoulet lldbutil.mkdir_p(so_dir) 240d30797b4SJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 241d30797b4SJoseph Tremoulet self.runCmd('settings set target.exec-search-paths "%s"' % so_dir) 242d30797b4SJoseph Tremoulet modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 243d30797b4SJoseph Tremoulet self.assertEqual(1, len(modules)) 244d30797b4SJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 245d30797b4SJoseph Tremoulet # will check that this matches. 246d30797b4SJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 247d30797b4SJoseph Tremoulet 2480e6c9a6eSGreg Clayton def test_breakpad_overflow_hash_match(self): 2490e6c9a6eSGreg Clayton """ 2500e6c9a6eSGreg Clayton This is a similar to test_breakpad_hash_match, but it verifies that 2510e6c9a6eSGreg Clayton if the .text section does not end on a 16 byte boundary, then it 2520e6c9a6eSGreg Clayton will overflow into the next section's data by up to 15 bytes. This 2530e6c9a6eSGreg Clayton verifies that we are able to match what breakpad does as it will do 2540e6c9a6eSGreg Clayton this. 2550e6c9a6eSGreg Clayton """ 2560e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 2570e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad-overflow.yaml", so_path) 2580e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 2590e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 2600e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml") 2610e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 2620e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 2630e6c9a6eSGreg Clayton # will check that this matches. 2640e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "48EB9FD7") 2650e6c9a6eSGreg Clayton 266*d20aa7caSJoseph Tremoulet def test_breakpad_hash_match_exe_outside_sysroot(self): 267*d20aa7caSJoseph Tremoulet """ 268*d20aa7caSJoseph Tremoulet Check that we can match the breakpad .text section hash when the 269*d20aa7caSJoseph Tremoulet module is specified as the exe during launch, and a syroot is 270*d20aa7caSJoseph Tremoulet provided, which does not contain the exe. 271*d20aa7caSJoseph Tremoulet """ 272*d20aa7caSJoseph Tremoulet sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot") 273*d20aa7caSJoseph Tremoulet lldbutil.mkdir_p(sysroot_path) 274*d20aa7caSJoseph Tremoulet so_dir = os.path.join(self.getBuildDir(), "binary") 275*d20aa7caSJoseph Tremoulet so_path = os.path.join(so_dir, "libbreakpad.so") 276*d20aa7caSJoseph Tremoulet lldbutil.mkdir_p(so_dir) 277*d20aa7caSJoseph Tremoulet self.yaml2obj("libbreakpad.yaml", so_path) 278*d20aa7caSJoseph Tremoulet self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path) 279*d20aa7caSJoseph Tremoulet modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml", so_path) 280*d20aa7caSJoseph Tremoulet self.assertEqual(1, len(modules)) 281*d20aa7caSJoseph Tremoulet # LLDB makes up its own UUID as well when there is no build ID so we 282*d20aa7caSJoseph Tremoulet # will check that this matches. 283*d20aa7caSJoseph Tremoulet self.verify_module(modules[0], so_path, "D9C480E8") 2840e6c9a6eSGreg Clayton 2850e6c9a6eSGreg Clayton def test_facebook_hash_match(self): 2860e6c9a6eSGreg Clayton """ 2870e6c9a6eSGreg Clayton Breakpad creates minidump files using CvRecord in each module whose 2880e6c9a6eSGreg Clayton signature is set to PDB70 where the UUID is a hash generated by 2890e6c9a6eSGreg Clayton breakpad of the .text section and Facebook modified this hash to 2900e6c9a6eSGreg Clayton avoid collisions. This is only done when the executable has no ELF 2910e6c9a6eSGreg Clayton build ID. 2920e6c9a6eSGreg Clayton 2930e6c9a6eSGreg Clayton This test verifies that if we have a minidump with a 16 byte UUID, 2940e6c9a6eSGreg Clayton that we are able to associate a symbol file with no ELF build ID 2950e6c9a6eSGreg Clayton and match it up by hashing the .text section like Facebook does. 2960e6c9a6eSGreg Clayton """ 2970e6c9a6eSGreg Clayton so_path = self.getBuildArtifact("libbreakpad.so") 2980e6c9a6eSGreg Clayton self.yaml2obj("libbreakpad.yaml", so_path) 2990e6c9a6eSGreg Clayton cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) 3000e6c9a6eSGreg Clayton self.dbg.HandleCommand(cmd) 3010e6c9a6eSGreg Clayton modules = self.get_minidump_modules("linux-arm-facebook-uuid-match.yaml") 3020e6c9a6eSGreg Clayton self.assertEqual(1, len(modules)) 3030e6c9a6eSGreg Clayton # LLDB makes up it own UUID as well when there is no build ID so we 3040e6c9a6eSGreg Clayton # will check that this matches. 3050e6c9a6eSGreg Clayton self.verify_module(modules[0], so_path, "D9C480E8") 3060e6c9a6eSGreg Clayton 3070e6c9a6eSGreg Clayton 30899451b44SJordan Rupprecht def test_relative_module_name(self): 30999451b44SJordan Rupprecht old_cwd = os.getcwd() 31099451b44SJordan Rupprecht self.addTearDownHook(lambda: os.chdir(old_cwd)) 31199451b44SJordan Rupprecht os.chdir(self.getBuildDir()) 31299451b44SJordan Rupprecht name = "file-with-a-name-unlikely-to-exist-in-the-current-directory.so" 31399451b44SJordan Rupprecht open(name, "a").close() 31499451b44SJordan Rupprecht modules = self.get_minidump_modules( 31599451b44SJordan Rupprecht self.getSourcePath("relative_module_name.yaml")) 31699451b44SJordan Rupprecht self.assertEqual(1, len(modules)) 31799451b44SJordan Rupprecht self.verify_module(modules[0], name, None) 3181beffc18SJaroslav Sevcik 3191beffc18SJaroslav Sevcik def test_add_module_build_id_16(self): 3201beffc18SJaroslav Sevcik """ 3211beffc18SJaroslav Sevcik Test that adding module with 16 byte UUID returns the existing 3221beffc18SJaroslav Sevcik module or fails. 3231beffc18SJaroslav Sevcik """ 3241beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml") 3251beffc18SJaroslav Sevcik self.assertEqual(2, len(modules)) 3261beffc18SJaroslav Sevcik 3271beffc18SJaroslav Sevcik # Add the existing modules. 3281beffc18SJaroslav Sevcik self.assertEqual(modules[0], self.target.AddModule( 3291beffc18SJaroslav Sevcik "/some/local/a", "", "01020304-0506-0708-090A-0B0C0D0E0F10")) 3301beffc18SJaroslav Sevcik self.assertEqual(modules[1], self.target.AddModule( 3311beffc18SJaroslav Sevcik "/some/local/b", "", "0A141E28-323C-4650-5A64-6E78828C96A0")) 3321beffc18SJaroslav Sevcik 3331beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 3341beffc18SJaroslav Sevcik self.assertFalse( 3351beffc18SJaroslav Sevcik self.target.AddModule( 3361beffc18SJaroslav Sevcik "a", "", "12345678-1234-1234-1234-123456789ABC").IsValid()) 3371beffc18SJaroslav Sevcik self.assertFalse( 3381beffc18SJaroslav Sevcik self.target.AddModule( 3391beffc18SJaroslav Sevcik "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-12345678").IsValid()) 3401beffc18SJaroslav Sevcik 3411beffc18SJaroslav Sevcik def test_add_module_build_id_20(self): 3421beffc18SJaroslav Sevcik """ 3431beffc18SJaroslav Sevcik Test that adding module with 20 byte UUID returns the existing 3441beffc18SJaroslav Sevcik module or fails. 3451beffc18SJaroslav Sevcik """ 3461beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml") 3471beffc18SJaroslav Sevcik 3481beffc18SJaroslav Sevcik # Add the existing modules. 3491beffc18SJaroslav Sevcik self.assertEqual(modules[0], self.target.AddModule( 3501beffc18SJaroslav Sevcik "/some/local/a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314")) 3511beffc18SJaroslav Sevcik self.assertEqual(modules[1], self.target.AddModule( 3521beffc18SJaroslav Sevcik "/some/local/b", "", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8")) 3531beffc18SJaroslav Sevcik 3541beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 3551beffc18SJaroslav Sevcik self.assertFalse( 3561beffc18SJaroslav Sevcik self.target.AddModule( 3571beffc18SJaroslav Sevcik "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10").IsValid()) 3581beffc18SJaroslav Sevcik self.assertFalse( 3591beffc18SJaroslav Sevcik self.target.AddModule( 3601beffc18SJaroslav Sevcik "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10-12345678").IsValid()) 3611beffc18SJaroslav Sevcik 3621beffc18SJaroslav Sevcik def test_add_module_build_id_4(self): 3631beffc18SJaroslav Sevcik """ 3641beffc18SJaroslav Sevcik Test that adding module with 4 byte UUID returns the existing 3651beffc18SJaroslav Sevcik module or fails. 3661beffc18SJaroslav Sevcik """ 3671beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-4.yaml") 3681beffc18SJaroslav Sevcik 3691beffc18SJaroslav Sevcik # Add the existing modules. 3701beffc18SJaroslav Sevcik self.assertEqual(modules[0], self.target.AddModule( 3711beffc18SJaroslav Sevcik "/some/local/a.so", "", "01020304")) 3721beffc18SJaroslav Sevcik self.assertEqual(modules[1], self.target.AddModule( 3731beffc18SJaroslav Sevcik "/some/local/b.so", "", "0A141E28")) 3741beffc18SJaroslav Sevcik 3751beffc18SJaroslav Sevcik # Adding modules with non-existing UUID should fail. 3761beffc18SJaroslav Sevcik self.assertFalse( 3771beffc18SJaroslav Sevcik self.target.AddModule( 3781beffc18SJaroslav Sevcik "a", "", "01020304-0506-0708-090A-0B0C0D0E0F10").IsValid()) 3791beffc18SJaroslav Sevcik self.assertFalse(self.target.AddModule("a", "", "01020305").IsValid()) 3801beffc18SJaroslav Sevcik 3811beffc18SJaroslav Sevcik def test_remove_placeholder_add_real_module(self): 3821beffc18SJaroslav Sevcik """ 3831beffc18SJaroslav Sevcik Test that removing a placeholder module and adding back the real 3841beffc18SJaroslav Sevcik module succeeds. 3851beffc18SJaroslav Sevcik """ 3861beffc18SJaroslav Sevcik so_path = self.getBuildArtifact("libuuidmatch.so") 3871beffc18SJaroslav Sevcik self.yaml2obj("libuuidmatch.yaml", so_path) 3881beffc18SJaroslav Sevcik modules = self.get_minidump_modules("linux-arm-uuids-match.yaml") 3891beffc18SJaroslav Sevcik 3901beffc18SJaroslav Sevcik uuid = "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116"; 3911beffc18SJaroslav Sevcik self.assertEqual(1, len(modules)) 3921beffc18SJaroslav Sevcik self.verify_module(modules[0], "/target/path/libuuidmatch.so",uuid) 3931beffc18SJaroslav Sevcik 3941beffc18SJaroslav Sevcik self.target.RemoveModule(modules[0]) 3951beffc18SJaroslav Sevcik new_module = self.target.AddModule(so_path, "", uuid) 3961beffc18SJaroslav Sevcik 3971beffc18SJaroslav Sevcik self.verify_module(new_module, so_path, uuid) 3981beffc18SJaroslav Sevcik self.assertEqual(new_module, self.target.modules[0]) 3991beffc18SJaroslav Sevcik self.assertEqual(1, len(self.target.modules)) 400