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