afb8c2370b36531f205625f47308b9ed9552ab2b
[openbsd] /
1 """Test that lldb steps correctly after the inferior has crashed."""
2
3
4 import lldb
5 from lldbsuite.test import lldbutil
6 from lldbsuite.test import lldbplatformutil
7 from lldbsuite.test.decorators import *
8 from lldbsuite.test.lldbtest import *
9
10
11 class CrashingInferiorStepTestCase(TestBase):
12
13     mydir = TestBase.compute_mydir(__file__)
14
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)."""
19         self.build()
20         self.inferior_crashing()
21
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)."""
25         self.build()
26         self.inferior_crashing_registers()
27
28     @add_test_categories(['pyapi'])
29     def test_inferior_crashing_python(self):
30         """Test that lldb reliably catches the inferior crashing (Python API)."""
31         self.build()
32         self.inferior_crashing_python()
33
34     def test_inferior_crashing_expr(self):
35         """Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
36         self.build()
37         self.inferior_crashing_expr()
38
39     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
40     def test_inferior_crashing_step(self):
41         """Test that stepping after a crash behaves correctly."""
42         self.build()
43         self.inferior_crashing_step()
44
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."""
49         self.build()
50         self.inferior_crashing_step_after_break()
51
52     # Inferior exits after stepping after a segfault. This is working as
53     # intended IMHO.
54     @skipIfLinux
55     @skipIfFreeBSD
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."""
59         self.build()
60         self.inferior_crashing_expr_step_expr()
61
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)
65
66     def check_stop_reason(self):
67         # We should have one crashing thread
68         self.assertEqual(
69             len(
70                 lldbutil.get_crashed_threads(
71                     self,
72                     self.dbg.GetSelectedTarget().GetProcess())), 1,
73             STOPPED_DUE_TO_EXC_BAD_ACCESS)
74
75     def get_api_stop_reason(self):
76         return lldb.eStopReasonException
77
78     def setUp(self):
79         # Call super's setUp().
80         TestBase.setUp(self)
81         # Find the line number of the crash.
82         self.line = line_number('main.c', '// Crash here.')
83
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)
88
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'
95         else:
96             stop_reason = 'stop reason = invalid address'
97         self.expect(
98             "thread list",
99             STOPPED_DUE_TO_EXC_BAD_ACCESS,
100             substrs=['stopped', stop_reason])
101
102         # And it should report the correct line number.
103         self.expect(
104             "thread backtrace all",
105             substrs=[stop_reason, 'main.c:%d' % self.line])
106
107     def inferior_crashing_python(self):
108         """Inferior crashes upon launching; lldb should catch the event and stop."""
109         exe = self.getBuildArtifact("a.out")
110
111         target = self.dbg.CreateTarget(exe)
112         self.assertTrue(target, VALID_TARGET)
113
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())
118
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()))
123
124         threads = lldbutil.get_crashed_threads(self, process)
125         self.assertEqual(
126             len(threads), 1,
127             "Failed to stop the thread upon bad access exception")
128
129         if self.TraceOn():
130             lldbutil.print_stacktrace(threads[0])
131
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)
136
137         self.runCmd("run", RUN_SUCCEEDED)
138         self.check_stop_reason()
139
140         # lldb should be able to read from registers from the inferior after
141         # crashing.
142         lldbplatformutil.check_first_register_readable(self)
143
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)
148
149         self.runCmd("run", RUN_SUCCEEDED)
150         self.check_stop_reason()
151
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')
155
156         self.expect("p hello_world", substrs=['Hello'])
157
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)
162
163         self.set_breakpoint(self.line)
164         self.runCmd("run", RUN_SUCCEEDED)
165
166         self.expect(
167             "thread list",
168             STOPPED_DUE_TO_BREAKPOINT,
169             substrs=['main.c:%d' % self.line, 'stop reason = breakpoint'])
170
171         self.runCmd("next")
172         self.check_stop_reason()
173
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'])
178
179         # lldb should be able to read from registers from the inferior after
180         # crashing.
181         lldbplatformutil.check_first_register_readable(self)
182
183         # And it should report the correct line number.
184         self.expect("thread backtrace all", substrs=['main.c:%d' % self.line])
185
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)
191
192         self.runCmd("run", RUN_SUCCEEDED)
193         self.check_stop_reason()
194
195         expected_state = 'exited'  # Provide the exit code.
196         if self.platformIsDarwin():
197             # TODO: Determine why 'next' and 'continue' have no effect after a
198             # crash.
199             expected_state = 'stopped'
200
201         self.expect("next", substrs=['Process', expected_state])
202
203         if expected_state == 'exited':
204             self.expect(
205                 "thread list",
206                 error=True,
207                 substrs=['Process must be launched'])
208         else:
209             self.check_stop_reason()
210
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)
215
216         self.runCmd("run", RUN_SUCCEEDED)
217         self.check_stop_reason()
218
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'])
222
223         self.runCmd("next")
224         self.check_stop_reason()
225
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'])