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