124 lines · python
1"""Test that lldb steps correctly after the inferior has crashed while in a recursive routine."""2 3 4import lldb5from lldbsuite.test.decorators import *6from lldbsuite.test.lldbtest import *7from lldbsuite.test import lldbplatformutil8from lldbsuite.test import lldbutil9 10 11class CrashingRecursiveInferiorStepTestCase(TestBase):12 def test_recursive_inferior_crashing_step(self):13 """Test that stepping after a crash behaves correctly."""14 self.build()15 self.recursive_inferior_crashing_step()16 17 @skipIfTargetAndroid() # debuggerd interferes with this test on Android18 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")19 @expectedFailureNetBSD20 def test_recursive_inferior_crashing_step_after_break(self):21 """Test that lldb functions correctly after stepping through a crash."""22 self.build()23 self.recursive_inferior_crashing_step_after_break()24 25 # Inferior exits after stepping after a segfault. This is working as26 # intended IMHO.27 @skipIf(oslist=["freebsd", "linux", "netbsd"])28 def test_recursive_inferior_crashing_expr_step_and_expr(self):29 """Test that lldb expressions work before and after stepping after a crash."""30 self.build()31 self.recursive_inferior_crashing_expr_step_expr()32 33 def set_breakpoint(self, line):34 lldbutil.run_break_set_by_file_and_line(35 self, "main.c", line, num_expected_locations=1, loc_exact=True36 )37 38 def check_stop_reason(self):39 # We should have one crashing thread40 self.assertEqual(41 len(42 lldbutil.get_crashed_threads(43 self, self.dbg.GetSelectedTarget().GetProcess()44 )45 ),46 1,47 STOPPED_DUE_TO_EXC_BAD_ACCESS,48 )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 70 self.runCmd("next")71 self.check_stop_reason()72 73 # The lldb expression interpreter should be able to read from addresses74 # of the inferior after a crash.75 self.expect("expression i", substrs=["(int) $0 ="])76 77 # lldb should be able to read from registers from the inferior after78 # crashing.79 lldbplatformutil.check_first_register_readable(self)80 81 # And it should report the correct line number.82 self.expect("thread backtrace all", substrs=["main.c:%d" % self.line])83 84 def recursive_inferior_crashing_step_after_break(self):85 """Test that lldb behaves correctly when stepping after a crash."""86 exe = self.getBuildArtifact("a.out")87 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)88 89 self.runCmd("run", RUN_SUCCEEDED)90 self.check_stop_reason()91 92 expected_state = "exited" # Provide the exit code.93 if self.platformIsDarwin():94 # TODO: Determine why 'next' and 'continue' have no effect after a95 # crash.96 expected_state = "stopped"97 98 self.expect("next", substrs=["Process", expected_state])99 100 if expected_state == "exited":101 self.expect("thread list", error=True, substrs=["process must be launched"])102 else:103 self.check_stop_reason()104 105 def recursive_inferior_crashing_expr_step_expr(self):106 """Test that lldb expressions work before and after stepping after a crash."""107 exe = self.getBuildArtifact("a.out")108 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)109 110 self.runCmd("run", RUN_SUCCEEDED)111 self.check_stop_reason()112 113 # The lldb expression interpreter should be able to read from addresses114 # of the inferior after a crash.115 self.expect("expression null", startstr="(char *) $0 = 0x0")116 117 self.runCmd("next")118 119 # The lldb expression interpreter should be able to read from addresses120 # of the inferior after a step.121 self.expect("expression null", startstr="(char *) $1 = 0x0")122 123 self.check_stop_reason()124