1"""Test that lldb steps correctly after the inferior has crashed while in a recursive routine.""" 2 3 4import lldb 5from lldbsuite.test.decorators import * 6from lldbsuite.test.lldbtest import * 7from lldbsuite.test import lldbplatformutil 8from lldbsuite.test import lldbutil 9 10 11class CrashingRecursiveInferiorStepTestCase(TestBase): 12 13 mydir = TestBase.compute_mydir(__file__) 14 15 def test_recursive_inferior_crashing_step(self): 16 """Test that stepping after a crash behaves correctly.""" 17 self.build() 18 self.recursive_inferior_crashing_step() 19 20 @skipIfTargetAndroid() # debuggerd interferes with this test on Android 21 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 22 @expectedFailureNetBSD 23 def test_recursive_inferior_crashing_step_after_break(self): 24 """Test that lldb functions correctly after stepping through a crash.""" 25 self.build() 26 self.recursive_inferior_crashing_step_after_break() 27 28 # Inferior exits after stepping after a segfault. This is working as 29 # intended IMHO. 30 @skipIf(oslist=["freebsd", "linux", "netbsd"]) 31 def test_recursive_inferior_crashing_expr_step_and_expr(self): 32 """Test that lldb expressions work before and after stepping after a crash.""" 33 self.build() 34 self.recursive_inferior_crashing_expr_step_expr() 35 36 def set_breakpoint(self, line): 37 lldbutil.run_break_set_by_file_and_line( 38 self, "main.c", line, num_expected_locations=1, loc_exact=True) 39 40 def check_stop_reason(self): 41 # We should have one crashing thread 42 self.assertEqual( 43 len( 44 lldbutil.get_crashed_threads( 45 self, 46 self.dbg.GetSelectedTarget().GetProcess())), 1, 47 STOPPED_DUE_TO_EXC_BAD_ACCESS) 48 49 def setUp(self): 50 # Call super's setUp(). 51 TestBase.setUp(self) 52 # Find the line number of the crash. 53 self.line = line_number('main.c', '// Crash here.') 54 55 def recursive_inferior_crashing_step(self): 56 """Test that lldb functions correctly after stepping through a crash.""" 57 exe = self.getBuildArtifact("a.out") 58 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 59 60 self.set_breakpoint(self.line) 61 self.runCmd("run", RUN_SUCCEEDED) 62 63 self.expect( 64 "thread list", 65 STOPPED_DUE_TO_BREAKPOINT, 66 substrs=['main.c:%d' % self.line, 'stop reason = breakpoint']) 67 68 self.runCmd("next") 69 self.check_stop_reason() 70 71 # The lldb expression interpreter should be able to read from addresses 72 # of the inferior after a crash. 73 self.expect("p i", substrs=['(int) $0 =']) 74 75 # lldb should be able to read from registers from the inferior after 76 # crashing. 77 lldbplatformutil.check_first_register_readable(self) 78 79 # And it should report the correct line number. 80 self.expect("thread backtrace all", substrs=['main.c:%d' % self.line]) 81 82 def recursive_inferior_crashing_step_after_break(self): 83 """Test that lldb behaves correctly when stepping after a crash.""" 84 exe = self.getBuildArtifact("a.out") 85 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 86 87 self.runCmd("run", RUN_SUCCEEDED) 88 self.check_stop_reason() 89 90 expected_state = 'exited' # Provide the exit code. 91 if self.platformIsDarwin(): 92 # TODO: Determine why 'next' and 'continue' have no effect after a 93 # crash. 94 expected_state = 'stopped' 95 96 self.expect("next", substrs=['Process', expected_state]) 97 98 if expected_state == 'exited': 99 self.expect( 100 "thread list", 101 error=True, 102 substrs=['Process must be launched']) 103 else: 104 self.check_stop_reason() 105 106 def recursive_inferior_crashing_expr_step_expr(self): 107 """Test that lldb expressions work before and after stepping after a crash.""" 108 exe = self.getBuildArtifact("a.out") 109 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 110 111 self.runCmd("run", RUN_SUCCEEDED) 112 self.check_stop_reason() 113 114 # The lldb expression interpreter should be able to read from addresses 115 # of the inferior after a crash. 116 self.expect("p null", startstr='(char *) $0 = 0x0') 117 118 self.runCmd("next") 119 120 # The lldb expression interpreter should be able to read from addresses 121 # of the inferior after a step. 122 self.expect("p null", startstr='(char *) $1 = 0x0') 123 124 self.check_stop_reason() 125