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