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 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 16 def test_recursive_inferior_crashing_step(self): 17 """Test that stepping after a crash behaves correctly.""" 18 self.build() 19 self.recursive_inferior_crashing_step() 20 21 @skipIfTargetAndroid() # debuggerd interferes with this test on Android 22 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 23 @expectedFailureNetBSD 24 def test_recursive_inferior_crashing_step_after_break(self): 25 """Test that lldb functions correctly after stepping through a crash.""" 26 self.build() 27 self.recursive_inferior_crashing_step_after_break() 28 29 # Inferior exits after stepping after a segfault. This is working as 30 # intended IMHO. 31 @skipIf(oslist=["freebsd", "linux", "netbsd"]) 32 def test_recursive_inferior_crashing_expr_step_and_expr(self): 33 """Test that lldb expressions work before and after stepping after a crash.""" 34 self.build() 35 self.recursive_inferior_crashing_expr_step_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( 45 lldbutil.get_crashed_threads( 46 self, 47 self.dbg.GetSelectedTarget().GetProcess())), 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_step(self): 57 """Test that lldb functions correctly after stepping through a crash.""" 58 exe = self.getBuildArtifact("a.out") 59 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 60 61 self.set_breakpoint(self.line) 62 self.runCmd("run", RUN_SUCCEEDED) 63 64 self.expect( 65 "thread list", 66 STOPPED_DUE_TO_BREAKPOINT, 67 substrs=['main.c:%d' % self.line, 'stop reason = breakpoint']) 68 69 self.runCmd("next") 70 self.check_stop_reason() 71 72 # The lldb expression interpreter should be able to read from addresses 73 # of the inferior after a crash. 74 self.expect("p i", substrs=['(int) $0 =']) 75 76 # lldb should be able to read from registers from the inferior after 77 # crashing. 78 lldbplatformutil.check_first_register_readable(self) 79 80 # And it should report the correct line number. 81 self.expect("thread backtrace all", substrs=['main.c:%d' % self.line]) 82 83 def recursive_inferior_crashing_step_after_break(self): 84 """Test that lldb behaves correctly when stepping after a crash.""" 85 exe = self.getBuildArtifact("a.out") 86 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 87 88 self.runCmd("run", RUN_SUCCEEDED) 89 self.check_stop_reason() 90 91 expected_state = 'exited' # Provide the exit code. 92 if self.platformIsDarwin(): 93 # TODO: Determine why 'next' and 'continue' have no effect after a 94 # crash. 95 expected_state = 'stopped' 96 97 self.expect("next", substrs=['Process', expected_state]) 98 99 if expected_state == 'exited': 100 self.expect( 101 "thread list", 102 error=True, 103 substrs=['Process must be launched']) 104 else: 105 self.check_stop_reason() 106 107 def recursive_inferior_crashing_expr_step_expr(self): 108 """Test that lldb expressions work before and after stepping after a crash.""" 109 exe = self.getBuildArtifact("a.out") 110 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 111 112 self.runCmd("run", RUN_SUCCEEDED) 113 self.check_stop_reason() 114 115 # The lldb expression interpreter should be able to read from addresses 116 # of the inferior after a crash. 117 self.expect("p null", startstr='(char *) $0 = 0x0') 118 119 self.runCmd("next") 120 121 # The lldb expression interpreter should be able to read from addresses 122 # of the inferior after a step. 123 self.expect("p null", startstr='(char *) $1 = 0x0') 124 125 self.check_stop_reason() 126