1"""Test that lldb functions correctly after the inferior has crashed while in a recursive routine.""" 2 3 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbplatformutil 9from lldbsuite.test import lldbutil 10 11 12class CrashingRecursiveInferiorTestCase(TestBase): 13 14 mydir = TestBase.compute_mydir(__file__) 15 16 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 17 @expectedFailureNetBSD 18 def test_recursive_inferior_crashing(self): 19 """Test that lldb reliably catches the inferior crashing (command).""" 20 self.build() 21 self.recursive_inferior_crashing() 22 23 def test_recursive_inferior_crashing_register(self): 24 """Test that lldb reliably reads registers from the inferior after crashing (command).""" 25 self.build() 26 self.recursive_inferior_crashing_registers() 27 28 @add_test_categories(['pyapi']) 29 def test_recursive_inferior_crashing_python(self): 30 """Test that lldb reliably catches the inferior crashing (Python API).""" 31 self.build() 32 self.recursive_inferior_crashing_python() 33 34 def test_recursive_inferior_crashing_expr(self): 35 """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" 36 self.build() 37 self.recursive_inferior_crashing_expr() 38 39 def set_breakpoint(self, line): 40 lldbutil.run_break_set_by_file_and_line( 41 self, "main.c", line, num_expected_locations=1, loc_exact=True) 42 43 def check_stop_reason(self): 44 # We should have one crashing thread 45 self.assertEqual( 46 len(lldbutil.get_crashed_threads(self, self.dbg.GetSelectedTarget().GetProcess())), 47 1, 48 STOPPED_DUE_TO_EXC_BAD_ACCESS) 49 50 def setUp(self): 51 # Call super's setUp(). 52 TestBase.setUp(self) 53 # Find the line number of the crash. 54 self.line = line_number('main.c', '// Crash here.') 55 56 def recursive_inferior_crashing(self): 57 """Inferior crashes upon launching; lldb should catch the event and stop.""" 58 exe = self.getBuildArtifact("a.out") 59 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 60 61 self.runCmd("run", RUN_SUCCEEDED) 62 63 # The exact stop reason depends on the platform 64 if self.platformIsDarwin(): 65 stop_reason = 'stop reason = EXC_BAD_ACCESS' 66 elif self.getPlatform() == "linux" or self.getPlatform() == "freebsd": 67 stop_reason = 'stop reason = signal SIGSEGV' 68 else: 69 stop_reason = 'stop reason = invalid address' 70 self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS, 71 substrs=['stopped', 72 stop_reason]) 73 74 # And it should report a backtrace that includes main and the crash 75 # site. 76 self.expect( 77 "thread backtrace all", 78 substrs=[ 79 stop_reason, 80 'recursive_function', 81 'main', 82 'argc', 83 'argv', 84 ]) 85 86 # And it should report the correct line number. 87 self.expect("thread backtrace all", 88 substrs=[stop_reason, 89 'main.c:%d' % self.line]) 90 91 def recursive_inferior_crashing_python(self): 92 """Inferior crashes upon launching; lldb should catch the event and stop.""" 93 exe = self.getBuildArtifact("a.out") 94 95 target = self.dbg.CreateTarget(exe) 96 self.assertTrue(target, VALID_TARGET) 97 98 # Now launch the process, and do not stop at entry point. 99 # Both argv and envp are null. 100 process = target.LaunchSimple( 101 None, None, self.get_process_working_directory()) 102 103 if process.GetState() != lldb.eStateStopped: 104 self.fail("Process should be in the 'stopped' state, " 105 "instead the actual state is: '%s'" % 106 lldbutil.state_type_to_str(process.GetState())) 107 108 threads = lldbutil.get_crashed_threads(self, process) 109 self.assertEqual( 110 len(threads), 111 1, 112 "Failed to stop the thread upon bad access exception") 113 114 if self.TraceOn(): 115 lldbutil.print_stacktrace(threads[0]) 116 117 def recursive_inferior_crashing_registers(self): 118 """Test that lldb can read registers after crashing.""" 119 exe = self.getBuildArtifact("a.out") 120 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 121 122 self.runCmd("run", RUN_SUCCEEDED) 123 self.check_stop_reason() 124 125 # lldb should be able to read from registers from the inferior after 126 # crashing. 127 lldbplatformutil.check_first_register_readable(self) 128 129 def recursive_inferior_crashing_expr(self): 130 """Test that the lldb expression interpreter can read symbols after crashing.""" 131 exe = self.getBuildArtifact("a.out") 132 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 133 134 self.runCmd("run", RUN_SUCCEEDED) 135 self.check_stop_reason() 136 137 # The lldb expression interpreter should be able to read from addresses 138 # of the inferior after a crash. 139 self.expect("p i", 140 startstr='(int) $0 =') 141