1""" 2Test NetBSD core file debugging. 3""" 4 5from __future__ import division, print_function 6 7import signal 8import os 9 10import lldb 11from lldbsuite.test.decorators import * 12from lldbsuite.test.lldbtest import * 13from lldbsuite.test import lldbutil 14 15 16class 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 156class 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 180class 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 210class 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) 238