1 """Test that lldb steps correctly after the inferior has crashed."""
5 from lldbsuite.test import lldbutil
6 from lldbsuite.test import lldbplatformutil
7 from lldbsuite.test.decorators import *
8 from lldbsuite.test.lldbtest import *
11 class CrashingInferiorStepTestCase(TestBase):
13 mydir = TestBase.compute_mydir(__file__)
15 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
16 @expectedFailureNetBSD
17 def test_inferior_crashing(self):
18 """Test that lldb reliably catches the inferior crashing (command)."""
20 self.inferior_crashing()
22 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
23 def test_inferior_crashing_register(self):
24 """Test that lldb reliably reads registers from the inferior after crashing (command)."""
26 self.inferior_crashing_registers()
28 @add_test_categories(['pyapi'])
29 def test_inferior_crashing_python(self):
30 """Test that lldb reliably catches the inferior crashing (Python API)."""
32 self.inferior_crashing_python()
34 def test_inferior_crashing_expr(self):
35 """Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
37 self.inferior_crashing_expr()
39 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
40 def test_inferior_crashing_step(self):
41 """Test that stepping after a crash behaves correctly."""
43 self.inferior_crashing_step()
45 @skipIfTargetAndroid() # debuggerd interferes with this test on Android
46 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
47 def test_inferior_crashing_step_after_break(self):
48 """Test that lldb functions correctly after stepping through a crash."""
50 self.inferior_crashing_step_after_break()
52 # Inferior exits after stepping after a segfault. This is working as
56 @expectedFailureNetBSD
57 def test_inferior_crashing_expr_step_and_expr(self):
58 """Test that lldb expressions work before and after stepping after a crash."""
60 self.inferior_crashing_expr_step_expr()
62 def set_breakpoint(self, line):
63 lldbutil.run_break_set_by_file_and_line(
64 self, "main.c", line, num_expected_locations=1, loc_exact=True)
66 def check_stop_reason(self):
67 # We should have one crashing thread
70 lldbutil.get_crashed_threads(
72 self.dbg.GetSelectedTarget().GetProcess())), 1,
73 STOPPED_DUE_TO_EXC_BAD_ACCESS)
75 def get_api_stop_reason(self):
76 return lldb.eStopReasonException
79 # Call super's setUp().
81 # Find the line number of the crash.
82 self.line = line_number('main.c', '// Crash here.')
84 def inferior_crashing(self):
85 """Inferior crashes upon launching; lldb should catch the event and stop."""
86 exe = self.getBuildArtifact("a.out")
87 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
89 self.runCmd("run", RUN_SUCCEEDED)
90 # The exact stop reason depends on the platform
91 if self.platformIsDarwin():
92 stop_reason = 'stop reason = EXC_BAD_ACCESS'
93 elif self.getPlatform() == "linux" or self.getPlatform() == "freebsd":
94 stop_reason = 'stop reason = signal SIGSEGV'
96 stop_reason = 'stop reason = invalid address'
99 STOPPED_DUE_TO_EXC_BAD_ACCESS,
100 substrs=['stopped', stop_reason])
102 # And it should report the correct line number.
104 "thread backtrace all",
105 substrs=[stop_reason, 'main.c:%d' % self.line])
107 def inferior_crashing_python(self):
108 """Inferior crashes upon launching; lldb should catch the event and stop."""
109 exe = self.getBuildArtifact("a.out")
111 target = self.dbg.CreateTarget(exe)
112 self.assertTrue(target, VALID_TARGET)
114 # Now launch the process, and do not stop at entry point.
115 # Both argv and envp are null.
116 process = target.LaunchSimple(None, None,
117 self.get_process_working_directory())
119 if process.GetState() != lldb.eStateStopped:
120 self.fail("Process should be in the 'stopped' state, "
121 "instead the actual state is: '%s'" %
122 lldbutil.state_type_to_str(process.GetState()))
124 threads = lldbutil.get_crashed_threads(self, process)
127 "Failed to stop the thread upon bad access exception")
130 lldbutil.print_stacktrace(threads[0])
132 def inferior_crashing_registers(self):
133 """Test that lldb can read registers after crashing."""
134 exe = self.getBuildArtifact("a.out")
135 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
137 self.runCmd("run", RUN_SUCCEEDED)
138 self.check_stop_reason()
140 # lldb should be able to read from registers from the inferior after
142 lldbplatformutil.check_first_register_readable(self)
144 def inferior_crashing_expr(self):
145 """Test that the lldb expression interpreter can read symbols after crashing."""
146 exe = self.getBuildArtifact("a.out")
147 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
149 self.runCmd("run", RUN_SUCCEEDED)
150 self.check_stop_reason()
152 # The lldb expression interpreter should be able to read from addresses
153 # of the inferior after a crash.
154 self.expect("p argc", startstr='(int) $0 = 1')
156 self.expect("p hello_world", substrs=['Hello'])
158 def inferior_crashing_step(self):
159 """Test that lldb functions correctly after stepping through a crash."""
160 exe = self.getBuildArtifact("a.out")
161 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
163 self.set_breakpoint(self.line)
164 self.runCmd("run", RUN_SUCCEEDED)
168 STOPPED_DUE_TO_BREAKPOINT,
169 substrs=['main.c:%d' % self.line, 'stop reason = breakpoint'])
172 self.check_stop_reason()
174 # The lldb expression interpreter should be able to read from addresses
175 # of the inferior after a crash.
176 self.expect("p argv[0]", substrs=['a.out'])
177 self.expect("p null_ptr", substrs=['= 0x0'])
179 # lldb should be able to read from registers from the inferior after
181 lldbplatformutil.check_first_register_readable(self)
183 # And it should report the correct line number.
184 self.expect("thread backtrace all", substrs=['main.c:%d' % self.line])
186 @expectedFailureNetBSD
187 def inferior_crashing_step_after_break(self):
188 """Test that lldb behaves correctly when stepping after a crash."""
189 exe = self.getBuildArtifact("a.out")
190 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
192 self.runCmd("run", RUN_SUCCEEDED)
193 self.check_stop_reason()
195 expected_state = 'exited' # Provide the exit code.
196 if self.platformIsDarwin():
197 # TODO: Determine why 'next' and 'continue' have no effect after a
199 expected_state = 'stopped'
201 self.expect("next", substrs=['Process', expected_state])
203 if expected_state == 'exited':
207 substrs=['Process must be launched'])
209 self.check_stop_reason()
211 def inferior_crashing_expr_step_expr(self):
212 """Test that lldb expressions work before and after stepping after a crash."""
213 exe = self.getBuildArtifact("a.out")
214 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
216 self.runCmd("run", RUN_SUCCEEDED)
217 self.check_stop_reason()
219 # The lldb expression interpreter should be able to read from addresses
220 # of the inferior after a crash.
221 self.expect("p argv[0]", substrs=['a.out'])
224 self.check_stop_reason()
226 # The lldb expression interpreter should be able to read from addresses
227 # of the inferior after a crash.
228 self.expect("p argv[0]", substrs=['a.out'])