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