1"""
2Test basics of mini dump debugging.
3"""
4
5from six import iteritems
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class MiniDumpTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17    NO_DEBUG_INFO_TESTCASE = True
18
19    def test_process_info_in_mini_dump(self):
20        """Test that lldb can read the process information from the minidump."""
21        # target create -c fizzbuzz_no_heap.dmp
22        self.dbg.CreateTarget("")
23        self.target = self.dbg.GetSelectedTarget()
24        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
25        self.assertTrue(self.process, PROCESS_IS_VALID)
26        self.assertEqual(self.process.GetNumThreads(), 1)
27        self.assertEqual(self.process.GetProcessID(), 4440)
28
29    def test_thread_info_in_mini_dump(self):
30        """Test that lldb can read the thread information from the minidump."""
31        # target create -c fizzbuzz_no_heap.dmp
32        self.dbg.CreateTarget("")
33        self.target = self.dbg.GetSelectedTarget()
34        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
35        # This process crashed due to an access violation (0xc0000005) in its
36        # one and only thread.
37        self.assertEqual(self.process.GetNumThreads(), 1)
38        thread = self.process.GetThreadAtIndex(0)
39        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonException)
40        stop_description = thread.GetStopDescription(256)
41        self.assertIn("0xc0000005", stop_description)
42
43    def test_modules_in_mini_dump(self):
44        """Test that lldb can read the list of modules from the minidump."""
45        # target create -c fizzbuzz_no_heap.dmp
46        self.dbg.CreateTarget("")
47        self.target = self.dbg.GetSelectedTarget()
48        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
49        self.assertTrue(self.process, PROCESS_IS_VALID)
50        expected_modules = [
51            {
52                'filename' : r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug/fizzbuzz.exe",
53                'uuid' : '0F45B791-9A96-46F9-BF8F-2D6076EA421A-00000011',
54            },
55            {
56                'filename' : r"C:\Windows\SysWOW64/ntdll.dll",
57                'uuid' : 'BBB0846A-402C-4052-A16B-67650BBFE6B0-00000002',
58            },
59            {
60                'filename' : r"C:\Windows\SysWOW64/kernel32.dll",
61                'uuid' : 'E5CB7E1B-005E-4113-AB98-98D6913B52D8-00000002',
62            },
63            {
64                'filename' : r"C:\Windows\SysWOW64/KERNELBASE.dll",
65                'uuid' : '0BF95241-CB0D-4BD4-AC5D-186A6452E522-00000001',
66            },
67            {
68                'filename' : r"C:\Windows\System32/MSVCP120D.dll",
69                'uuid' : '3C05516E-57E7-40EB-8D3F-9722C5BD80DD-00000001',
70            },
71            {
72                'filename' : r"C:\Windows\System32/MSVCR120D.dll",
73                'uuid' : '6382FB86-46C4-4046-AE42-8D97B3F91FF2-00000001',
74            },
75        ]
76        self.assertEqual(self.target.GetNumModules(), len(expected_modules))
77        for module, expected in zip(self.target.modules, expected_modules):
78            self.assertTrue(module.IsValid())
79            self.assertEqual(module.file.fullpath, expected['filename'])
80            self.assertEqual(module.GetUUIDString(), expected['uuid'])
81
82    def test_breakpad_uuid_matching(self):
83        """Test that the uuid computation algorithms in minidump and breakpad
84        files match."""
85        self.target = self.dbg.CreateTarget("")
86        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
87        self.assertTrue(self.process, PROCESS_IS_VALID)
88        self.expect("target symbols add fizzbuzz.syms", substrs=["symbol file",
89            "fizzbuzz.syms", "has been added to", "fizzbuzz.exe"]),
90        self.assertTrue(self.target.modules[0].FindSymbol("main"))
91
92    @skipIfLLVMTargetMissing("X86")
93    def test_stack_info_in_mini_dump(self):
94        """Test that we can see a trivial stack in a VS-generate mini dump."""
95        # target create -c fizzbuzz_no_heap.dmp
96        self.dbg.CreateTarget("")
97        self.target = self.dbg.GetSelectedTarget()
98        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
99        self.assertEqual(self.process.GetNumThreads(), 1)
100        thread = self.process.GetThreadAtIndex(0)
101
102        pc_list = [ 0x00164d14, 0x00167c79, 0x00167e6d, 0x7510336a, 0x77759882, 0x77759855]
103
104        self.assertEqual(thread.GetNumFrames(), len(pc_list))
105        for i in range(len(pc_list)):
106            frame = thread.GetFrameAtIndex(i)
107            self.assertTrue(frame.IsValid())
108            self.assertEqual(frame.GetPC(), pc_list[i])
109            self.assertTrue(frame.GetModule().IsValid())
110
111    @skipUnlessWindows # Minidump saving works only on windows
112    def test_deeper_stack_in_mini_dump(self):
113        """Test that we can examine a more interesting stack in a mini dump."""
114        self.build()
115        exe = self.getBuildArtifact("a.out")
116        core = self.getBuildArtifact("core.dmp")
117        try:
118            # Set a breakpoint and capture a mini dump.
119            target = self.dbg.CreateTarget(exe)
120            breakpoint = target.BreakpointCreateByName("bar")
121            process = target.LaunchSimple(
122                None, None, self.get_process_working_directory())
123            self.assertEqual(process.GetState(), lldb.eStateStopped)
124            self.assertTrue(process.SaveCore(core))
125            self.assertTrue(os.path.isfile(core))
126            self.assertTrue(process.Kill().Success())
127
128            # Launch with the mini dump, and inspect the stack.
129            target = self.dbg.CreateTarget(None)
130            process = target.LoadCore(core)
131            thread = process.GetThreadAtIndex(0)
132
133            expected_stack = {0: 'bar', 1: 'foo', 2: 'main'}
134            self.assertGreaterEqual(thread.GetNumFrames(), len(expected_stack))
135            for index, name in iteritems(expected_stack):
136                frame = thread.GetFrameAtIndex(index)
137                self.assertTrue(frame.IsValid())
138                function_name = frame.GetFunctionName()
139                self.assertIn(name, function_name)
140
141        finally:
142            # Clean up the mini dump file.
143            self.assertTrue(self.dbg.DeleteTarget(target))
144            if (os.path.isfile(core)):
145                os.unlink(core)
146
147    @skipUnlessWindows # Minidump saving works only on windows
148    def test_local_variables_in_mini_dump(self):
149        """Test that we can examine local variables in a mini dump."""
150        self.build()
151        exe = self.getBuildArtifact("a.out")
152        core = self.getBuildArtifact("core.dmp")
153        try:
154            # Set a breakpoint and capture a mini dump.
155            target = self.dbg.CreateTarget(exe)
156            breakpoint = target.BreakpointCreateByName("bar")
157            process = target.LaunchSimple(
158                None, None, self.get_process_working_directory())
159            self.assertEqual(process.GetState(), lldb.eStateStopped)
160            self.assertTrue(process.SaveCore(core))
161            self.assertTrue(os.path.isfile(core))
162            self.assertTrue(process.Kill().Success())
163
164            # Launch with the mini dump, and inspect a local variable.
165            target = self.dbg.CreateTarget(None)
166            process = target.LoadCore(core)
167            thread = process.GetThreadAtIndex(0)
168            frame = thread.GetFrameAtIndex(0)
169            value = frame.EvaluateExpression('x')
170            self.assertEqual(value.GetValueAsSigned(), 3)
171
172        finally:
173            # Clean up the mini dump file.
174            self.assertTrue(self.dbg.DeleteTarget(target))
175            if (os.path.isfile(core)):
176                os.unlink(core)
177