067b04d997d0f465d830cdb9f461126df84127ce
[openbsd] /
1 """
2 Test NetBSD core file debugging.
3 """
4
5 from __future__ import division, print_function
6
7 import signal
8 import os
9
10 import lldb
11 from lldbsuite.test.decorators import *
12 from lldbsuite.test.lldbtest import *
13 from lldbsuite.test import lldbutil
14
15
16 class NetBSDCoreCommonTestCase(TestBase):
17     NO_DEBUG_INFO_TESTCASE = True
18
19     mydir = TestBase.compute_mydir(__file__)
20
21     def setUp(self):
22         super(NetBSDCoreCommonTestCase, self).setUp()
23         self._initial_platform = lldb.DBG.GetSelectedPlatform()
24
25     def tearDown(self):
26         lldb.DBG.SetSelectedPlatform(self._initial_platform)
27         super(NetBSDCoreCommonTestCase, self).tearDown()
28
29     def check_memory_regions(self, process, region_count):
30         region_list = process.GetMemoryRegions()
31         self.assertEqual(region_list.GetSize(), region_count)
32
33         region = lldb.SBMemoryRegionInfo()
34
35         # Check we have the right number of regions.
36         self.assertEqual(region_list.GetSize(), region_count)
37
38         # Check that getting a region beyond the last in the list fails.
39         self.assertFalse(
40             region_list.GetMemoryRegionAtIndex(
41                 region_count, region))
42
43         # Check each region is valid.
44         for i in range(region_list.GetSize()):
45             # Check we can actually get this region.
46             self.assertTrue(region_list.GetMemoryRegionAtIndex(i, region))
47
48             # Every region in the list should be mapped.
49             self.assertTrue(region.IsMapped())
50
51             # Test the address at the start of a region returns it's enclosing
52             # region.
53             begin_address = region.GetRegionBase()
54             region_at_begin = lldb.SBMemoryRegionInfo()
55             error = process.GetMemoryRegionInfo(begin_address, region_at_begin)
56             self.assertEqual(region, region_at_begin)
57
58             # Test an address in the middle of a region returns it's enclosing
59             # region.
60             middle_address = (region.GetRegionBase() +
61                               region.GetRegionEnd()) // 2
62             region_at_middle = lldb.SBMemoryRegionInfo()
63             error = process.GetMemoryRegionInfo(
64                 middle_address, region_at_middle)
65             self.assertEqual(region, region_at_middle)
66
67             # Test the address at the end of a region returns it's enclosing
68             # region.
69             end_address = region.GetRegionEnd() - 1
70             region_at_end = lldb.SBMemoryRegionInfo()
71             error = process.GetMemoryRegionInfo(end_address, region_at_end)
72             self.assertEqual(region, region_at_end)
73
74             # Check that quering the end address does not return this region but
75             # the next one.
76             next_region = lldb.SBMemoryRegionInfo()
77             error = process.GetMemoryRegionInfo(
78                 region.GetRegionEnd(), next_region)
79             self.assertNotEqual(region, next_region)
80             self.assertEqual(
81                 region.GetRegionEnd(),
82                 next_region.GetRegionBase())
83
84         # Check that query beyond the last region returns an unmapped region
85         # that ends at LLDB_INVALID_ADDRESS
86         last_region = lldb.SBMemoryRegionInfo()
87         region_list.GetMemoryRegionAtIndex(region_count - 1, last_region)
88         end_region = lldb.SBMemoryRegionInfo()
89         error = process.GetMemoryRegionInfo(
90             last_region.GetRegionEnd(), end_region)
91         self.assertFalse(end_region.IsMapped())
92         self.assertEqual(
93             last_region.GetRegionEnd(),
94             end_region.GetRegionBase())
95         self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS)
96
97     def check_state(self, process):
98         with open(os.devnull) as devnul:
99             # sanitize test output
100             self.dbg.SetOutputFileHandle(devnul, False)
101             self.dbg.SetErrorFileHandle(devnul, False)
102
103             self.assertTrue(process.is_stopped)
104
105             # Process.Continue
106             error = process.Continue()
107             self.assertFalse(error.Success())
108             self.assertTrue(process.is_stopped)
109
110             # Thread.StepOut
111             thread = process.GetSelectedThread()
112             thread.StepOut()
113             self.assertTrue(process.is_stopped)
114
115             # command line
116             self.dbg.HandleCommand('s')
117             self.assertTrue(process.is_stopped)
118             self.dbg.HandleCommand('c')
119             self.assertTrue(process.is_stopped)
120
121             # restore file handles
122             self.dbg.SetOutputFileHandle(None, False)
123             self.dbg.SetErrorFileHandle(None, False)
124
125     def check_backtrace(self, thread, filename, backtrace):
126         self.assertGreaterEqual(thread.GetNumFrames(), len(backtrace))
127         src = filename.rpartition('.')[0] + '.c'
128         for i in range(len(backtrace)):
129             frame = thread.GetFrameAtIndex(i)
130             self.assertTrue(frame)
131             if not backtrace[i].startswith('_'):
132                 self.assertEqual(frame.GetFunctionName(), backtrace[i])
133                 self.assertEqual(frame.GetLineEntry().GetLine(),
134                                  line_number(src, "Frame " + backtrace[i]))
135                 self.assertEqual(
136                     frame.FindVariable("F").GetValueAsUnsigned(), ord(
137                         backtrace[i][0]))
138
139     def do_test(self, filename, pid, region_count):
140         target = self.dbg.CreateTarget(filename)
141         process = target.LoadCore(filename + ".core")
142
143         self.assertTrue(process, PROCESS_IS_VALID)
144         self.assertEqual(process.GetNumThreads(), self.THREAD_COUNT)
145         self.assertEqual(process.GetProcessID(), pid)
146
147         self.check_state(process)
148
149         self.check_stack(process, pid, filename)
150
151         self.check_memory_regions(process, region_count)
152
153         self.dbg.DeleteTarget(target)
154
155
156 class NetBSD1LWPCoreTestCase(NetBSDCoreCommonTestCase):
157     THREAD_COUNT = 1
158
159     def check_stack(self, process, pid, filename):
160         thread = process.GetSelectedThread()
161         self.assertTrue(thread)
162         self.assertEqual(thread.GetThreadID(), 1)
163         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
164         self.assertEqual(thread.GetStopReasonDataCount(), 1)
165         self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
166         backtrace = ["bar", "foo", "main"]
167         self.check_backtrace(thread, filename, backtrace)
168
169     @skipIfLLVMTargetMissing("AArch64")
170     def test_aarch64(self):
171         """Test single-threaded aarch64 core dump."""
172         self.do_test("1lwp_SIGSEGV.aarch64", pid=8339, region_count=32)
173
174     @skipIfLLVMTargetMissing("X86")
175     def test_amd64(self):
176         """Test single-threaded amd64 core dump."""
177         self.do_test("1lwp_SIGSEGV.amd64", pid=693, region_count=21)
178
179
180 class NetBSD2LWPT2CoreTestCase(NetBSDCoreCommonTestCase):
181     THREAD_COUNT = 2
182
183     def check_stack(self, process, pid, filename):
184         thread = process.GetSelectedThread()
185         self.assertTrue(thread)
186         self.assertEqual(thread.GetThreadID(), 2)
187         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
188         self.assertEqual(thread.GetStopReasonDataCount(), 1)
189         self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
190         backtrace = ["bar", "foo", "lwp_main"]
191         self.check_backtrace(thread, filename, backtrace)
192
193         # thread 1 should have no signal
194         thread = process.GetThreadByID(1)
195         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
196         self.assertEqual(thread.GetStopReasonDataCount(), 1)
197         self.assertEqual(thread.GetStopReasonDataAtIndex(0), 0)
198
199     @skipIfLLVMTargetMissing("AArch64")
200     def test_aarch64(self):
201         """Test double-threaded aarch64 core dump where thread 2 is signalled."""
202         self.do_test("2lwp_t2_SIGSEGV.aarch64", pid=14142, region_count=31)
203
204     @skipIfLLVMTargetMissing("X86")
205     def test_amd64(self):
206         """Test double-threaded amd64 core dump where thread 2 is signalled."""
207         self.do_test("2lwp_t2_SIGSEGV.amd64", pid=622, region_count=24)
208
209
210 class NetBSD2LWPProcessSigCoreTestCase(NetBSDCoreCommonTestCase):
211     THREAD_COUNT = 2
212
213     def check_stack(self, process, pid, filename):
214         thread = process.GetSelectedThread()
215         self.assertTrue(thread)
216         self.assertEqual(thread.GetThreadID(), 2)
217         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
218         self.assertEqual(thread.GetStopReasonDataCount(), 1)
219         self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
220         backtrace = ["bar", "foo", "lwp_main"]
221         self.check_backtrace(thread, filename, backtrace)
222
223         # thread 1 should have the same signal
224         thread = process.GetThreadByID(1)
225         self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
226         self.assertEqual(thread.GetStopReasonDataCount(), 1)
227         self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
228
229     @skipIfLLVMTargetMissing("AArch64")
230     def test_aarch64(self):
231         """Test double-threaded aarch64 core dump where process is signalled."""
232         self.do_test("2lwp_process_SIGSEGV.aarch64", pid=1403, region_count=30)
233
234     @skipIfLLVMTargetMissing("X86")
235     def test_amd64(self):
236         """Test double-threaded amd64 core dump where process is signalled."""
237         self.do_test("2lwp_process_SIGSEGV.amd64", pid=665, region_count=24)