xref: /llvm-project/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py (revision 5033ea73bb01061feb09b3216c74619e1fbefdeb)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest basics of Minidump debugging.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprechtimport shutil
699451b44SJordan Rupprecht
799451b44SJordan Rupprechtimport lldb
899451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
999451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1099451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprecht
1399451b44SJordan Rupprechtclass MiniDumpNewTestCase(TestBase):
1499451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
1599451b44SJordan Rupprecht
1699451b44SJordan Rupprecht    _linux_x86_64_pid = 29917
1799451b44SJordan Rupprecht    _linux_x86_64_not_crashed_pid = 29939
1899451b44SJordan Rupprecht    _linux_x86_64_not_crashed_pid_offset = 0xD967
1999451b44SJordan Rupprecht
2099451b44SJordan Rupprecht    def process_from_yaml(self, yaml_file):
2199451b44SJordan Rupprecht        minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp")
2299451b44SJordan Rupprecht        self.yaml2obj(yaml_file, minidump_path)
2399451b44SJordan Rupprecht        self.target = self.dbg.CreateTarget(None)
2499451b44SJordan Rupprecht        self.process = self.target.LoadCore(minidump_path)
2599451b44SJordan Rupprecht        return self.process
2699451b44SJordan Rupprecht
2799451b44SJordan Rupprecht    def check_state(self):
2899451b44SJordan Rupprecht        with open(os.devnull) as devnul:
2999451b44SJordan Rupprecht            # sanitize test output
3099451b44SJordan Rupprecht            self.dbg.SetOutputFileHandle(devnul, False)
3199451b44SJordan Rupprecht            self.dbg.SetErrorFileHandle(devnul, False)
3299451b44SJordan Rupprecht
3399451b44SJordan Rupprecht            self.assertTrue(self.process.is_stopped)
3499451b44SJordan Rupprecht
3599451b44SJordan Rupprecht            # Process.Continue
3699451b44SJordan Rupprecht            error = self.process.Continue()
3799451b44SJordan Rupprecht            self.assertFalse(error.Success())
3899451b44SJordan Rupprecht            self.assertTrue(self.process.is_stopped)
3999451b44SJordan Rupprecht
4099451b44SJordan Rupprecht            # Thread.StepOut
4199451b44SJordan Rupprecht            thread = self.process.GetSelectedThread()
4299451b44SJordan Rupprecht            thread.StepOut()
4399451b44SJordan Rupprecht            self.assertTrue(self.process.is_stopped)
4499451b44SJordan Rupprecht
4599451b44SJordan Rupprecht            # command line
462238dcc3SJonas Devlieghere            self.dbg.HandleCommand("s")
4799451b44SJordan Rupprecht            self.assertTrue(self.process.is_stopped)
482238dcc3SJonas Devlieghere            self.dbg.HandleCommand("c")
4999451b44SJordan Rupprecht            self.assertTrue(self.process.is_stopped)
5099451b44SJordan Rupprecht
5199451b44SJordan Rupprecht            # restore file handles
5299451b44SJordan Rupprecht            self.dbg.SetOutputFileHandle(None, False)
5399451b44SJordan Rupprecht            self.dbg.SetErrorFileHandle(None, False)
5499451b44SJordan Rupprecht
5599451b44SJordan Rupprecht    def test_loadcore_error_status(self):
5699451b44SJordan Rupprecht        """Test the SBTarget.LoadCore(core, error) overload."""
5799451b44SJordan Rupprecht        minidump_path = self.getBuildArtifact("linux-x86_64.dmp")
5899451b44SJordan Rupprecht        self.yaml2obj("linux-x86_64.yaml", minidump_path)
5999451b44SJordan Rupprecht        self.target = self.dbg.CreateTarget(None)
6099451b44SJordan Rupprecht        error = lldb.SBError()
6199451b44SJordan Rupprecht        self.process = self.target.LoadCore(minidump_path, error)
6299451b44SJordan Rupprecht        self.assertTrue(self.process, PROCESS_IS_VALID)
63779bbbf2SDave Lee        self.assertSuccess(error)
6499451b44SJordan Rupprecht
6599451b44SJordan Rupprecht    def test_loadcore_error_status_failure(self):
6699451b44SJordan Rupprecht        """Test the SBTarget.LoadCore(core, error) overload."""
6799451b44SJordan Rupprecht        self.target = self.dbg.CreateTarget(None)
6899451b44SJordan Rupprecht        error = lldb.SBError()
6999451b44SJordan Rupprecht        self.process = self.target.LoadCore("non-existent.dmp", error)
7099451b44SJordan Rupprecht        self.assertFalse(self.process, PROCESS_IS_VALID)
7199451b44SJordan Rupprecht        self.assertTrue(error.Fail())
7299451b44SJordan Rupprecht
7399451b44SJordan Rupprecht    def test_process_info_in_minidump(self):
7499451b44SJordan Rupprecht        """Test that lldb can read the process information from the Minidump."""
7599451b44SJordan Rupprecht        self.process_from_yaml("linux-x86_64.yaml")
7699451b44SJordan Rupprecht        self.assertTrue(self.process, PROCESS_IS_VALID)
7799451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
7899451b44SJordan Rupprecht        self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
7999451b44SJordan Rupprecht        self.check_state()
8099451b44SJordan Rupprecht
8199451b44SJordan Rupprecht    def test_memory_region_name(self):
8299451b44SJordan Rupprecht        self.process_from_yaml("regions-linux-map.yaml")
8399451b44SJordan Rupprecht        result = lldb.SBCommandReturnObject()
8499451b44SJordan Rupprecht        addr_region_name_pairs = [
8599451b44SJordan Rupprecht            ("0x400d9000", "/system/bin/app_process"),
8699451b44SJordan Rupprecht            ("0x400db000", "/system/bin/app_process"),
8799451b44SJordan Rupprecht            ("0x400dd000", "/system/bin/linker"),
8899451b44SJordan Rupprecht            ("0x400ed000", "/system/bin/linker"),
8999451b44SJordan Rupprecht            ("0x400ee000", "/system/bin/linker"),
9099451b44SJordan Rupprecht            ("0x400fb000", "/system/lib/liblog.so"),
9199451b44SJordan Rupprecht            ("0x400fc000", "/system/lib/liblog.so"),
9299451b44SJordan Rupprecht            ("0x400fd000", "/system/lib/liblog.so"),
9399451b44SJordan Rupprecht            ("0x400ff000", "/system/lib/liblog.so"),
9499451b44SJordan Rupprecht            ("0x40100000", "/system/lib/liblog.so"),
9599451b44SJordan Rupprecht            ("0x40101000", "/system/lib/libc.so"),
9699451b44SJordan Rupprecht            ("0x40122000", "/system/lib/libc.so"),
9799451b44SJordan Rupprecht            ("0x40123000", "/system/lib/libc.so"),
9899451b44SJordan Rupprecht            ("0x40167000", "/system/lib/libc.so"),
9999451b44SJordan Rupprecht            ("0x40169000", "/system/lib/libc.so"),
10099451b44SJordan Rupprecht        ]
10199451b44SJordan Rupprecht        ci = self.dbg.GetCommandInterpreter()
1022238dcc3SJonas Devlieghere        for addr, region_name in addr_region_name_pairs:
1032238dcc3SJonas Devlieghere            command = "memory region " + addr
10499451b44SJordan Rupprecht            ci.HandleCommand(command, result, False)
10599451b44SJordan Rupprecht            message = 'Ensure memory "%s" shows up in output for "%s"' % (
1062238dcc3SJonas Devlieghere                region_name,
1072238dcc3SJonas Devlieghere                command,
1082238dcc3SJonas Devlieghere            )
1093cc37622SDave Lee            self.assertIn(region_name, result.GetOutput(), message)
11099451b44SJordan Rupprecht
11199451b44SJordan Rupprecht    def test_thread_info_in_minidump(self):
11299451b44SJordan Rupprecht        """Test that lldb can read the thread information from the Minidump."""
11399451b44SJordan Rupprecht        self.process_from_yaml("linux-x86_64.yaml")
11499451b44SJordan Rupprecht        self.check_state()
11599451b44SJordan Rupprecht        # This process crashed due to a segmentation fault in its
11699451b44SJordan Rupprecht        # one and only thread.
11799451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
11899451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
1190f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
12099451b44SJordan Rupprecht        stop_description = thread.GetStopDescription(256)
1213cc37622SDave Lee        self.assertIn("SIGSEGV", stop_description)
12299451b44SJordan Rupprecht
123f152472aSDavid Spickett    @skipIfLLVMTargetMissing("X86")
12499451b44SJordan Rupprecht    def test_stack_info_in_minidump(self):
12599451b44SJordan Rupprecht        """Test that we can see a trivial stack in a breakpad-generated Minidump."""
12699451b44SJordan Rupprecht        # target create linux-x86_64 -c linux-x86_64.dmp
12799451b44SJordan Rupprecht        self.dbg.CreateTarget("linux-x86_64")
12899451b44SJordan Rupprecht        self.target = self.dbg.GetSelectedTarget()
12999451b44SJordan Rupprecht        self.process = self.target.LoadCore("linux-x86_64.dmp")
13099451b44SJordan Rupprecht        self.check_state()
13199451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
13299451b44SJordan Rupprecht        self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
13399451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
13499451b44SJordan Rupprecht        # frame #0: linux-x86_64`crash()
13599451b44SJordan Rupprecht        # frame #1: linux-x86_64`_start
13699451b44SJordan Rupprecht        self.assertEqual(thread.GetNumFrames(), 2)
13799451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
13899451b44SJordan Rupprecht        self.assertTrue(frame.IsValid())
13999451b44SJordan Rupprecht        self.assertTrue(frame.GetModule().IsValid())
14099451b44SJordan Rupprecht        pc = frame.GetPC()
14199451b44SJordan Rupprecht        eip = frame.FindRegister("pc")
14299451b44SJordan Rupprecht        self.assertTrue(eip.IsValid())
14399451b44SJordan Rupprecht        self.assertEqual(pc, eip.GetValueAsUnsigned())
14499451b44SJordan Rupprecht
14599451b44SJordan Rupprecht    def test_snapshot_minidump_dump_requested(self):
14699451b44SJordan Rupprecht        """Test that if we load a snapshot minidump file (meaning the process
14799451b44SJordan Rupprecht        did not crash) with exception code "DUMP_REQUESTED" there is no stop reason."""
14899451b44SJordan Rupprecht        # target create -c linux-x86_64_not_crashed.dmp
14999451b44SJordan Rupprecht        self.dbg.CreateTarget(None)
15099451b44SJordan Rupprecht        self.target = self.dbg.GetSelectedTarget()
15199451b44SJordan Rupprecht        self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp")
15299451b44SJordan Rupprecht        self.check_state()
15399451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
15499451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
1550f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
15699451b44SJordan Rupprecht        stop_description = thread.GetStopDescription(256)
15799451b44SJordan Rupprecht        self.assertEqual(stop_description, "")
15899451b44SJordan Rupprecht
15999451b44SJordan Rupprecht    def test_snapshot_minidump_null_exn_code(self):
16099451b44SJordan Rupprecht        """Test that if we load a snapshot minidump file (meaning the process
16199451b44SJordan Rupprecht        did not crash) with exception code zero there is no stop reason."""
16299451b44SJordan Rupprecht        self.process_from_yaml("linux-x86_64_null_signal.yaml")
16399451b44SJordan Rupprecht        self.check_state()
16499451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
16599451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
1660f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
16799451b44SJordan Rupprecht        stop_description = thread.GetStopDescription(256)
16899451b44SJordan Rupprecht        self.assertEqual(stop_description, "")
16999451b44SJordan Rupprecht
17099451b44SJordan Rupprecht    def check_register_unsigned(self, set, name, expected):
17199451b44SJordan Rupprecht        reg_value = set.GetChildMemberWithName(name)
1722238dcc3SJonas Devlieghere        self.assertTrue(
1732238dcc3SJonas Devlieghere            reg_value.IsValid(), 'Verify we have a register named "%s"' % (name)
1742238dcc3SJonas Devlieghere        )
1752238dcc3SJonas Devlieghere        self.assertEqual(
1762238dcc3SJonas Devlieghere            reg_value.GetValueAsUnsigned(),
1772238dcc3SJonas Devlieghere            expected,
1782238dcc3SJonas Devlieghere            'Verify "%s" == %i' % (name, expected),
1792238dcc3SJonas Devlieghere        )
18099451b44SJordan Rupprecht
18199451b44SJordan Rupprecht    def check_register_string_value(self, set, name, expected, format):
18299451b44SJordan Rupprecht        reg_value = set.GetChildMemberWithName(name)
1832238dcc3SJonas Devlieghere        self.assertTrue(
1842238dcc3SJonas Devlieghere            reg_value.IsValid(), 'Verify we have a register named "%s"' % (name)
1852238dcc3SJonas Devlieghere        )
18699451b44SJordan Rupprecht        if format is not None:
18799451b44SJordan Rupprecht            reg_value.SetFormat(format)
1882238dcc3SJonas Devlieghere        self.assertEqual(
1892238dcc3SJonas Devlieghere            reg_value.GetValue(),
1902238dcc3SJonas Devlieghere            expected,
1912238dcc3SJonas Devlieghere            'Verify "%s" has string value "%s"' % (name, expected),
1922238dcc3SJonas Devlieghere        )
19399451b44SJordan Rupprecht
19499451b44SJordan Rupprecht    def test_arm64_registers(self):
19599451b44SJordan Rupprecht        """Test ARM64 registers from a breakpad created minidump."""
19699451b44SJordan Rupprecht        self.process_from_yaml("arm64-macos.yaml")
19799451b44SJordan Rupprecht        self.check_state()
19899451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
19999451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
2000f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
20199451b44SJordan Rupprecht        stop_description = thread.GetStopDescription(256)
20299451b44SJordan Rupprecht        self.assertEqual(stop_description, "")
20399451b44SJordan Rupprecht        registers = thread.GetFrameAtIndex(0).GetRegisters()
20499451b44SJordan Rupprecht        # Verify the GPR registers are all correct
20599451b44SJordan Rupprecht        # Verify x0 - x31 register values
20699451b44SJordan Rupprecht        gpr = registers.GetValueAtIndex(0)
20799451b44SJordan Rupprecht        for i in range(32):
20899451b44SJordan Rupprecht            v = i + 1 | i + 2 << 32 | i + 3 << 48
20999451b44SJordan Rupprecht            w = i + 1
2102238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "x%i" % (i), v)
2112238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "w%i" % (i), w)
21299451b44SJordan Rupprecht        # Verify arg1 - arg8 register values
21399451b44SJordan Rupprecht        for i in range(1, 9):
21499451b44SJordan Rupprecht            v = i | i + 1 << 32 | i + 2 << 48
2152238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "arg%i" % (i), v)
21699451b44SJordan Rupprecht        i = 29
21799451b44SJordan Rupprecht        v = i + 1 | i + 2 << 32 | i + 3 << 48
2182238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "fp", v)
21999451b44SJordan Rupprecht        i = 30
22099451b44SJordan Rupprecht        v = i + 1 | i + 2 << 32 | i + 3 << 48
2212238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "lr", v)
22299451b44SJordan Rupprecht        i = 31
22399451b44SJordan Rupprecht        v = i + 1 | i + 2 << 32 | i + 3 << 48
2242238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "sp", v)
2252238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "pc", 0x1000)
2262238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "cpsr", 0x11223344)
2272238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "psr", 0x11223344)
22899451b44SJordan Rupprecht
22999451b44SJordan Rupprecht        # Verify the FPR registers are all correct
23099451b44SJordan Rupprecht        fpr = registers.GetValueAtIndex(1)
23199451b44SJordan Rupprecht        for i in range(32):
23299451b44SJordan Rupprecht            v = "0x"
23399451b44SJordan Rupprecht            d = "0x"
23499451b44SJordan Rupprecht            s = "0x"
23599451b44SJordan Rupprecht            h = "0x"
23699451b44SJordan Rupprecht            for j in range(i + 15, i - 1, -1):
23799451b44SJordan Rupprecht                v += "%2.2x" % (j)
23899451b44SJordan Rupprecht            for j in range(i + 7, i - 1, -1):
23999451b44SJordan Rupprecht                d += "%2.2x" % (j)
24099451b44SJordan Rupprecht            for j in range(i + 3, i - 1, -1):
24199451b44SJordan Rupprecht                s += "%2.2x" % (j)
24299451b44SJordan Rupprecht            for j in range(i + 1, i - 1, -1):
24399451b44SJordan Rupprecht                h += "%2.2x" % (j)
2442238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "v%i" % (i), v, lldb.eFormatHex)
2452238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "d%i" % (i), d, lldb.eFormatHex)
2462238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "s%i" % (i), s, lldb.eFormatHex)
2472238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "h%i" % (i), h, lldb.eFormatHex)
2482238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "fpsr", 0x55667788)
2492238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "fpcr", 0x99AABBCC)
25099451b44SJordan Rupprecht
25199451b44SJordan Rupprecht    def verify_arm_registers(self, apple=False):
25299451b44SJordan Rupprecht        """
25399451b44SJordan Rupprecht        Verify values of all ARM registers from a breakpad created
25499451b44SJordan Rupprecht        minidump.
25599451b44SJordan Rupprecht        """
25699451b44SJordan Rupprecht        if apple:
25799451b44SJordan Rupprecht            self.process_from_yaml("arm-macos.yaml")
25899451b44SJordan Rupprecht        else:
25999451b44SJordan Rupprecht            self.process_from_yaml("arm-linux.yaml")
26099451b44SJordan Rupprecht        self.check_state()
26199451b44SJordan Rupprecht        self.assertEqual(self.process.GetNumThreads(), 1)
26299451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
2630f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
26499451b44SJordan Rupprecht        stop_description = thread.GetStopDescription(256)
26599451b44SJordan Rupprecht        self.assertEqual(stop_description, "")
26699451b44SJordan Rupprecht        registers = thread.GetFrameAtIndex(0).GetRegisters()
26799451b44SJordan Rupprecht        # Verify the GPR registers are all correct
26899451b44SJordan Rupprecht        # Verify x0 - x31 register values
26999451b44SJordan Rupprecht        gpr = registers.GetValueAtIndex(0)
27099451b44SJordan Rupprecht        for i in range(1, 16):
2712238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "r%i" % (i), i + 1)
27299451b44SJordan Rupprecht        # Verify arg1 - arg4 register values
27399451b44SJordan Rupprecht        for i in range(1, 5):
2742238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "arg%i" % (i), i)
27599451b44SJordan Rupprecht        if apple:
2762238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "fp", 0x08)
27799451b44SJordan Rupprecht        else:
2782238dcc3SJonas Devlieghere            self.check_register_unsigned(gpr, "fp", 0x0C)
2792238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "lr", 0x0F)
2802238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "sp", 0x0E)
2812238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "pc", 0x10)
2822238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "cpsr", 0x11223344)
28399451b44SJordan Rupprecht
28499451b44SJordan Rupprecht        # Verify the FPR registers are all correct
28599451b44SJordan Rupprecht        fpr = registers.GetValueAtIndex(1)
28699451b44SJordan Rupprecht        # Check d0 - d31
2872238dcc3SJonas Devlieghere        self.check_register_unsigned(gpr, "fpscr", 0x55667788AABBCCDD)
28899451b44SJordan Rupprecht        for i in range(32):
28999451b44SJordan Rupprecht            value = (i + 1) | (i + 1) << 8 | (i + 1) << 32 | (i + 1) << 48
29099451b44SJordan Rupprecht            self.check_register_unsigned(fpr, "d%i" % (i), value)
29199451b44SJordan Rupprecht        # Check s0 - s31
29299451b44SJordan Rupprecht        for i in range(32):
29399451b44SJordan Rupprecht            i_val = (i >> 1) + 1
29499451b44SJordan Rupprecht            if i & 1:
29599451b44SJordan Rupprecht                value = "%#8.8x" % (i_val | i_val << 16)
29699451b44SJordan Rupprecht            else:
29799451b44SJordan Rupprecht                value = "%#8.8x" % (i_val | i_val << 8)
2982238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "s%i" % (i), value, lldb.eFormatHex)
29999451b44SJordan Rupprecht        # Check q0 - q15
30099451b44SJordan Rupprecht        for i in range(15):
30199451b44SJordan Rupprecht            a = i * 2 + 1
30299451b44SJordan Rupprecht            b = a + 1
3032238dcc3SJonas Devlieghere            value = (
3042238dcc3SJonas Devlieghere                "0x00%2.2x00%2.2x0000%2.2x%2.2x" "00%2.2x00%2.2x0000%2.2x%2.2x"
3052238dcc3SJonas Devlieghere            ) % (b, b, b, b, a, a, a, a)
3062238dcc3SJonas Devlieghere            self.check_register_string_value(fpr, "q%i" % (i), value, lldb.eFormatHex)
30799451b44SJordan Rupprecht
30899451b44SJordan Rupprecht    def test_linux_arm_registers(self):
30999451b44SJordan Rupprecht        """Test Linux ARM registers from a breakpad created minidump.
31099451b44SJordan Rupprecht
31199451b44SJordan Rupprecht        The frame pointer is R11 for linux.
31299451b44SJordan Rupprecht        """
31399451b44SJordan Rupprecht        self.verify_arm_registers(apple=False)
31499451b44SJordan Rupprecht
31599451b44SJordan Rupprecht    def test_apple_arm_registers(self):
31699451b44SJordan Rupprecht        """Test Apple ARM registers from a breakpad created minidump.
31799451b44SJordan Rupprecht
31899451b44SJordan Rupprecht        The frame pointer is R7 for linux.
31999451b44SJordan Rupprecht        """
32099451b44SJordan Rupprecht        self.verify_arm_registers(apple=True)
32199451b44SJordan Rupprecht
32299451b44SJordan Rupprecht    def do_test_deeper_stack(self, binary, core, pid):
32399451b44SJordan Rupprecht        target = self.dbg.CreateTarget(binary)
32499451b44SJordan Rupprecht        process = target.LoadCore(core)
32599451b44SJordan Rupprecht        thread = process.GetThreadAtIndex(0)
32699451b44SJordan Rupprecht
32799451b44SJordan Rupprecht        self.assertEqual(process.GetProcessID(), pid)
32899451b44SJordan Rupprecht
3292238dcc3SJonas Devlieghere        expected_stack = {1: "bar", 2: "foo", 3: "_start"}
33099451b44SJordan Rupprecht        self.assertGreaterEqual(thread.GetNumFrames(), len(expected_stack))
33156f9cfe3SDave Lee        for index, name in expected_stack.items():
33299451b44SJordan Rupprecht            frame = thread.GetFrameAtIndex(index)
33399451b44SJordan Rupprecht            self.assertTrue(frame.IsValid())
33499451b44SJordan Rupprecht            function_name = frame.GetFunctionName()
3353cc37622SDave Lee            self.assertIn(name, function_name)
33699451b44SJordan Rupprecht
33799451b44SJordan Rupprecht    @skipIfLLVMTargetMissing("X86")
33899451b44SJordan Rupprecht    def test_deeper_stack_in_minidump(self):
33999451b44SJordan Rupprecht        """Test that we can examine a more interesting stack in a Minidump."""
34099451b44SJordan Rupprecht        # Launch with the Minidump, and inspect the stack.
34199451b44SJordan Rupprecht        # target create linux-x86_64_not_crashed -c linux-x86_64_not_crashed.dmp
3422238dcc3SJonas Devlieghere        self.do_test_deeper_stack(
3432238dcc3SJonas Devlieghere            "linux-x86_64_not_crashed",
34499451b44SJordan Rupprecht            "linux-x86_64_not_crashed.dmp",
3452238dcc3SJonas Devlieghere            self._linux_x86_64_not_crashed_pid,
3462238dcc3SJonas Devlieghere        )
34799451b44SJordan Rupprecht
34899451b44SJordan Rupprecht    def do_change_pid_in_minidump(self, core, newcore, offset, oldpid, newpid):
34999451b44SJordan Rupprecht        """This assumes that the minidump is breakpad generated on Linux -
35099451b44SJordan Rupprecht        meaning that the PID in the file will be an ascii string part of
35199451b44SJordan Rupprecht        /proc/PID/status which is written in the file
35299451b44SJordan Rupprecht        """
35399451b44SJordan Rupprecht        shutil.copyfile(core, newcore)
35499451b44SJordan Rupprecht        with open(newcore, "rb+") as f:
35599451b44SJordan Rupprecht            f.seek(offset)
3562238dcc3SJonas Devlieghere            currentpid = f.read(5).decode("utf-8")
35799451b44SJordan Rupprecht            self.assertEqual(currentpid, oldpid)
35899451b44SJordan Rupprecht
35999451b44SJordan Rupprecht            f.seek(offset)
36099451b44SJordan Rupprecht            if len(newpid) < len(oldpid):
36199451b44SJordan Rupprecht                newpid += " " * (len(oldpid) - len(newpid))
36299451b44SJordan Rupprecht            newpid += "\n"
3632238dcc3SJonas Devlieghere            f.write(newpid.encode("utf-8"))
36499451b44SJordan Rupprecht
365f152472aSDavid Spickett    @skipIfLLVMTargetMissing("X86")
36699451b44SJordan Rupprecht    def test_deeper_stack_in_minidump_with_same_pid_running(self):
36799451b44SJordan Rupprecht        """Test that we read the information from the core correctly even if we
36899451b44SJordan Rupprecht        have a running process with the same PID"""
36999451b44SJordan Rupprecht        new_core = self.getBuildArtifact("linux-x86_64_not_crashed-pid.dmp")
3702238dcc3SJonas Devlieghere        self.do_change_pid_in_minidump(
3712238dcc3SJonas Devlieghere            "linux-x86_64_not_crashed.dmp",
37299451b44SJordan Rupprecht            new_core,
37399451b44SJordan Rupprecht            self._linux_x86_64_not_crashed_pid_offset,
37499451b44SJordan Rupprecht            str(self._linux_x86_64_not_crashed_pid),
3752238dcc3SJonas Devlieghere            str(os.getpid()),
3762238dcc3SJonas Devlieghere        )
37799451b44SJordan Rupprecht        self.do_test_deeper_stack("linux-x86_64_not_crashed", new_core, os.getpid())
37899451b44SJordan Rupprecht
379f152472aSDavid Spickett    @skipIfLLVMTargetMissing("X86")
38099451b44SJordan Rupprecht    def test_two_cores_same_pid(self):
38199451b44SJordan Rupprecht        """Test that we handle the situation if we have two core files with the same PID"""
38299451b44SJordan Rupprecht        new_core = self.getBuildArtifact("linux-x86_64_not_crashed-pid.dmp")
3832238dcc3SJonas Devlieghere        self.do_change_pid_in_minidump(
3842238dcc3SJonas Devlieghere            "linux-x86_64_not_crashed.dmp",
38599451b44SJordan Rupprecht            new_core,
38699451b44SJordan Rupprecht            self._linux_x86_64_not_crashed_pid_offset,
38799451b44SJordan Rupprecht            str(self._linux_x86_64_not_crashed_pid),
3882238dcc3SJonas Devlieghere            str(self._linux_x86_64_pid),
3892238dcc3SJonas Devlieghere        )
3902238dcc3SJonas Devlieghere        self.do_test_deeper_stack(
3912238dcc3SJonas Devlieghere            "linux-x86_64_not_crashed", new_core, self._linux_x86_64_pid
3922238dcc3SJonas Devlieghere        )
39399451b44SJordan Rupprecht        self.test_stack_info_in_minidump()
39499451b44SJordan Rupprecht
395f152472aSDavid Spickett    @skipIfLLVMTargetMissing("X86")
39699451b44SJordan Rupprecht    def test_local_variables_in_minidump(self):
39799451b44SJordan Rupprecht        """Test that we can examine local variables in a Minidump."""
39899451b44SJordan Rupprecht        # Launch with the Minidump, and inspect a local variable.
39999451b44SJordan Rupprecht        # target create linux-x86_64_not_crashed -c linux-x86_64_not_crashed.dmp
40099451b44SJordan Rupprecht        self.target = self.dbg.CreateTarget("linux-x86_64_not_crashed")
40199451b44SJordan Rupprecht        self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp")
40299451b44SJordan Rupprecht        self.check_state()
40399451b44SJordan Rupprecht        thread = self.process.GetThreadAtIndex(0)
40499451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(1)
4052238dcc3SJonas Devlieghere        value = frame.EvaluateExpression("x")
40699451b44SJordan Rupprecht        self.assertEqual(value.GetValueAsSigned(), 3)
40799451b44SJordan Rupprecht
40899451b44SJordan Rupprecht    def test_memory_regions_in_minidump(self):
40999451b44SJordan Rupprecht        """Test memory regions from a Minidump"""
41099451b44SJordan Rupprecht        self.process_from_yaml("regions-linux-map.yaml")
41199451b44SJordan Rupprecht        self.check_state()
41299451b44SJordan Rupprecht
41399451b44SJordan Rupprecht        regions_count = 19
41499451b44SJordan Rupprecht        region_info_list = self.process.GetMemoryRegions()
41599451b44SJordan Rupprecht        self.assertEqual(region_info_list.GetSize(), regions_count)
41699451b44SJordan Rupprecht
41799451b44SJordan Rupprecht        def check_region(index, start, end, read, write, execute, mapped, name):
41899451b44SJordan Rupprecht            region_info = lldb.SBMemoryRegionInfo()
41999451b44SJordan Rupprecht            self.assertTrue(
4202238dcc3SJonas Devlieghere                self.process.GetMemoryRegionInfo(start, region_info).Success()
4212238dcc3SJonas Devlieghere            )
42299451b44SJordan Rupprecht            self.assertEqual(start, region_info.GetRegionBase())
42399451b44SJordan Rupprecht            self.assertEqual(end, region_info.GetRegionEnd())
42499451b44SJordan Rupprecht            self.assertEqual(read, region_info.IsReadable())
42599451b44SJordan Rupprecht            self.assertEqual(write, region_info.IsWritable())
42699451b44SJordan Rupprecht            self.assertEqual(execute, region_info.IsExecutable())
42799451b44SJordan Rupprecht            self.assertEqual(mapped, region_info.IsMapped())
42899451b44SJordan Rupprecht            self.assertEqual(name, region_info.GetName())
42999451b44SJordan Rupprecht
43099451b44SJordan Rupprecht            # Ensure we have the same regions as SBMemoryRegionInfoList contains.
43199451b44SJordan Rupprecht            if index >= 0 and index < regions_count:
43299451b44SJordan Rupprecht                region_info_from_list = lldb.SBMemoryRegionInfo()
4332238dcc3SJonas Devlieghere                self.assertTrue(
4342238dcc3SJonas Devlieghere                    region_info_list.GetMemoryRegionAtIndex(
4352238dcc3SJonas Devlieghere                        index, region_info_from_list
4362238dcc3SJonas Devlieghere                    )
4372238dcc3SJonas Devlieghere                )
43899451b44SJordan Rupprecht                self.assertEqual(region_info_from_list, region_info)
43999451b44SJordan Rupprecht
44099451b44SJordan Rupprecht        a = "/system/bin/app_process"
44199451b44SJordan Rupprecht        b = "/system/bin/linker"
44299451b44SJordan Rupprecht        c = "/system/lib/liblog.so"
44399451b44SJordan Rupprecht        d = "/system/lib/libc.so"
44499451b44SJordan Rupprecht        n = None
4452238dcc3SJonas Devlieghere        max_int = 0xFFFFFFFFFFFFFFFF
44699451b44SJordan Rupprecht
44799451b44SJordan Rupprecht        # Test address before the first entry comes back with nothing mapped up
44899451b44SJordan Rupprecht        # to first valid region info
4492238dcc3SJonas Devlieghere        check_region(-1, 0x00000000, 0x400D9000, False, False, False, False, n)
4502238dcc3SJonas Devlieghere        check_region(0, 0x400D9000, 0x400DB000, True, False, True, True, a)
4512238dcc3SJonas Devlieghere        check_region(1, 0x400DB000, 0x400DC000, True, False, False, True, a)
4522238dcc3SJonas Devlieghere        check_region(2, 0x400DC000, 0x400DD000, True, True, False, True, n)
4532238dcc3SJonas Devlieghere        check_region(3, 0x400DD000, 0x400EC000, True, False, True, True, b)
4542238dcc3SJonas Devlieghere        check_region(4, 0x400EC000, 0x400ED000, True, False, False, True, n)
4552238dcc3SJonas Devlieghere        check_region(5, 0x400ED000, 0x400EE000, True, False, False, True, b)
4562238dcc3SJonas Devlieghere        check_region(6, 0x400EE000, 0x400EF000, True, True, False, True, b)
4572238dcc3SJonas Devlieghere        check_region(7, 0x400EF000, 0x400FB000, True, True, False, True, n)
4582238dcc3SJonas Devlieghere        check_region(8, 0x400FB000, 0x400FC000, True, False, True, True, c)
4592238dcc3SJonas Devlieghere        check_region(9, 0x400FC000, 0x400FD000, True, True, True, True, c)
4602238dcc3SJonas Devlieghere        check_region(10, 0x400FD000, 0x400FF000, True, False, True, True, c)
4612238dcc3SJonas Devlieghere        check_region(11, 0x400FF000, 0x40100000, True, False, False, True, c)
46299451b44SJordan Rupprecht        check_region(12, 0x40100000, 0x40101000, True, True, False, True, c)
46399451b44SJordan Rupprecht        check_region(13, 0x40101000, 0x40122000, True, False, True, True, d)
46499451b44SJordan Rupprecht        check_region(14, 0x40122000, 0x40123000, True, True, True, True, d)
46599451b44SJordan Rupprecht        check_region(15, 0x40123000, 0x40167000, True, False, True, True, d)
46699451b44SJordan Rupprecht        check_region(16, 0x40167000, 0x40169000, True, False, False, True, d)
4672238dcc3SJonas Devlieghere        check_region(17, 0x40169000, 0x4016B000, True, True, False, True, d)
4682238dcc3SJonas Devlieghere        check_region(18, 0x4016B000, 0x40176000, True, True, False, True, n)
46999451b44SJordan Rupprecht        check_region(-1, 0x40176000, max_int, False, False, False, False, n)
47020f84257SJoseph Tremoulet
47120f84257SJoseph Tremoulet    @skipIfLLVMTargetMissing("X86")
47220f84257SJoseph Tremoulet    def test_minidump_sysroot(self):
47320f84257SJoseph Tremoulet        """Test that lldb can find a module referenced in an i386 linux minidump using the sysroot."""
47420f84257SJoseph Tremoulet
47520f84257SJoseph Tremoulet        # Copy linux-x86_64 executable to tmp_sysroot/temp/test/ (since it was compiled as
47620f84257SJoseph Tremoulet        # /tmp/test/linux-x86_64)
4772238dcc3SJonas Devlieghere        tmp_sysroot = os.path.join(self.getBuildDir(), "lldb_i386_mock_sysroot")
4782238dcc3SJonas Devlieghere        executable = os.path.join(tmp_sysroot, "tmp", "test", "linux-x86_64")
47920f84257SJoseph Tremoulet        exe_dir = os.path.dirname(executable)
48020f84257SJoseph Tremoulet        lldbutil.mkdir_p(exe_dir)
48120f84257SJoseph Tremoulet        shutil.copyfile("linux-x86_64", executable)
48220f84257SJoseph Tremoulet
48320f84257SJoseph Tremoulet        # Set sysroot and load core
4842238dcc3SJonas Devlieghere        self.runCmd("platform select remote-linux --sysroot '%s'" % tmp_sysroot)
48520f84257SJoseph Tremoulet        self.process_from_yaml("linux-x86_64.yaml")
48620f84257SJoseph Tremoulet        self.check_state()
48720f84257SJoseph Tremoulet
48820f84257SJoseph Tremoulet        # Check that we loaded the module from the sysroot
48920f84257SJoseph Tremoulet        self.assertEqual(self.target.GetNumModules(), 1)
49020f84257SJoseph Tremoulet        module = self.target.GetModuleAtIndex(0)
4914a55c98fSJoseph Tremoulet        spec_dir_norm = os.path.normcase(module.GetFileSpec().GetDirectory())
4924a55c98fSJoseph Tremoulet        exe_dir_norm = os.path.normcase(exe_dir)
4934a55c98fSJoseph Tremoulet        self.assertEqual(spec_dir_norm, exe_dir_norm)
4946cb14599SJacob Lalonde
4956cb14599SJacob Lalonde    def test_minidump_memory64list(self):
4966cb14599SJacob Lalonde        """Test that lldb can read from the memory64list in a minidump."""
4976cb14599SJacob Lalonde        self.process_from_yaml("linux-x86_64_mem64.yaml")
4986cb14599SJacob Lalonde
4996cb14599SJacob Lalonde        region_count = 3
5006cb14599SJacob Lalonde        region_info_list = self.process.GetMemoryRegions()
5016cb14599SJacob Lalonde        self.assertEqual(region_info_list.GetSize(), region_count)
5026cb14599SJacob Lalonde
5036cb14599SJacob Lalonde        region = lldb.SBMemoryRegionInfo()
5046cb14599SJacob Lalonde        self.assertTrue(region_info_list.GetMemoryRegionAtIndex(0, region))
5056cb14599SJacob Lalonde        self.assertEqual(region.GetRegionBase(), 0x7FFF12A84030)
5066cb14599SJacob Lalonde        self.assertTrue(region.GetRegionEnd(), 0x7FFF12A84030 + 0x2FD0)
5076cb14599SJacob Lalonde        self.assertTrue(region_info_list.GetMemoryRegionAtIndex(1, region))
50849268352SJacob Lalonde        self.assertEqual(region.GetRegionBase(), 0x00007FFF12A87000)
50949268352SJacob Lalonde        self.assertTrue(region.GetRegionEnd(), 0x00007FFF12A87000 + 0x00000018)
5106cb14599SJacob Lalonde        self.assertTrue(region_info_list.GetMemoryRegionAtIndex(2, region))
51149268352SJacob Lalonde        self.assertEqual(region.GetRegionBase(), 0x00007FFF12A87018)
51249268352SJacob Lalonde        self.assertTrue(region.GetRegionEnd(), 0x00007FFF12A87018 + 0x00000400)
51349268352SJacob Lalonde
51449268352SJacob Lalonde    def test_multiple_exceptions_or_signals(self):
51549268352SJacob Lalonde        """Test that lldb can read the exception information from the Minidump."""
51649268352SJacob Lalonde        print("Starting to read multiple-sigsev.yaml")
51749268352SJacob Lalonde        self.process_from_yaml("multiple-sigsev.yaml")
51849268352SJacob Lalonde        print("Done reading multiple-sigsev.yaml")
51949268352SJacob Lalonde        self.check_state()
52049268352SJacob Lalonde        # This process crashed due to a segmentation fault in both it's threads.
52149268352SJacob Lalonde        self.assertEqual(self.process.GetNumThreads(), 2)
52249268352SJacob Lalonde        for i in range(2):
52349268352SJacob Lalonde            thread = self.process.GetThreadAtIndex(i)
52449268352SJacob Lalonde            self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
52549268352SJacob Lalonde            stop_description = thread.GetStopDescription(256)
52649268352SJacob Lalonde            self.assertIn("SIGSEGV", stop_description)
527*5033ea73SJacob Lalonde
528*5033ea73SJacob Lalonde    def test_breakpoint_on_minidump(self):
529*5033ea73SJacob Lalonde        """
530*5033ea73SJacob Lalonde        Test that LLDB breakpoints are recorded in Minidumps
531*5033ea73SJacob Lalonde        """
532*5033ea73SJacob Lalonde        yaml = "linux-x86_64-exceptiondescription.yaml"
533*5033ea73SJacob Lalonde        core = self.getBuildArtifact("breakpoint.core.dmp")
534*5033ea73SJacob Lalonde        self.yaml2obj(yaml, core)
535*5033ea73SJacob Lalonde        try:
536*5033ea73SJacob Lalonde            # Create a target with the object file we just created from YAML
537*5033ea73SJacob Lalonde            target = self.dbg.CreateTarget(None)
538*5033ea73SJacob Lalonde            self.assertTrue(target, VALID_TARGET)
539*5033ea73SJacob Lalonde            process = target.LoadCore(core)
540*5033ea73SJacob Lalonde            self.assertTrue(process, VALID_PROCESS)
541*5033ea73SJacob Lalonde            thread = process.GetThreadAtIndex(0)
542*5033ea73SJacob Lalonde            stop_reason = thread.GetStopDescription(256)
543*5033ea73SJacob Lalonde            self.assertIn("breakpoint 1.1", stop_reason)
544*5033ea73SJacob Lalonde        finally:
545*5033ea73SJacob Lalonde            if os.path.isfile(core):
546*5033ea73SJacob Lalonde                os.unlink(core)
547