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