xref: /llvm-project/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py (revision aa2784876a245f10811f65eb748c43574c17a173)
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