e63172f917b6d4decfa374ef80038f36e6d90fe5
[openbsd] /
1 """Test that lldb steps correctly after the inferior has crashed while in a recursive routine."""
2
3
4 import lldb
5 from lldbsuite.test.decorators import *
6 from lldbsuite.test.lldbtest import *
7 from lldbsuite.test import lldbplatformutil
8 from lldbsuite.test import lldbutil
9
10
11 class 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     def test_recursive_inferior_crashing_step_after_break(self):
24         """Test that lldb functions correctly after stepping through a crash."""
25         self.build()
26         self.recursive_inferior_crashing_step_after_break()
27
28     # Inferior exits after stepping after a segfault. This is working as
29     # intended IMHO.
30     @skipIfLinux
31     @skipIfFreeBSD
32     @expectedFailureNetBSD
33     def test_recursive_inferior_crashing_expr_step_and_expr(self):
34         """Test that lldb expressions work before and after stepping after a crash."""
35         self.build()
36         self.recursive_inferior_crashing_expr_step_expr()
37
38     def set_breakpoint(self, line):
39         lldbutil.run_break_set_by_file_and_line(
40             self, "main.c", line, num_expected_locations=1, loc_exact=True)
41
42     def check_stop_reason(self):
43         # We should have one crashing thread
44         self.assertEqual(
45             len(
46                 lldbutil.get_crashed_threads(
47                     self,
48                     self.dbg.GetSelectedTarget().GetProcess())), 1,
49             STOPPED_DUE_TO_EXC_BAD_ACCESS)
50
51     def setUp(self):
52         # Call super's setUp().
53         TestBase.setUp(self)
54         # Find the line number of the crash.
55         self.line = line_number('main.c', '// Crash here.')
56
57     def recursive_inferior_crashing_step(self):
58         """Test that lldb functions correctly after stepping through a crash."""
59         exe = self.getBuildArtifact("a.out")
60         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
61
62         self.set_breakpoint(self.line)
63         self.runCmd("run", RUN_SUCCEEDED)
64
65         self.expect(
66             "thread list",
67             STOPPED_DUE_TO_BREAKPOINT,
68             substrs=['main.c:%d' % self.line, 'stop reason = breakpoint'])
69
70         self.runCmd("next")
71         self.check_stop_reason()
72
73         # The lldb expression interpreter should be able to read from addresses
74         # of the inferior after a crash.
75         self.expect("p i", substrs=['(int) $0 ='])
76
77         # lldb should be able to read from registers from the inferior after
78         # 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 a
95             # crash.
96             expected_state = 'stopped'
97
98         self.expect("next", substrs=['Process', expected_state])
99
100         if expected_state == 'exited':
101             self.expect(
102                 "thread list",
103                 error=True,
104                 substrs=['Process must be launched'])
105         else:
106             self.check_stop_reason()
107
108     def recursive_inferior_crashing_expr_step_expr(self):
109         """Test that lldb expressions work before and after stepping after a crash."""
110         exe = self.getBuildArtifact("a.out")
111         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
112
113         self.runCmd("run", RUN_SUCCEEDED)
114         self.check_stop_reason()
115
116         # The lldb expression interpreter should be able to read from addresses
117         # of the inferior after a crash.
118         self.expect("p null", startstr='(char *) $0 = 0x0')
119
120         self.runCmd("next")
121
122         # The lldb expression interpreter should be able to read from addresses
123         # of the inferior after a step.
124         self.expect("p null", startstr='(char *) $1 = 0x0')
125
126         self.check_stop_reason()