1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
| """Test that lldb steps correctly after the inferior has crashed while in a recursive routine."""
from __future__ import print_function
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbplatformutil
from lldbsuite.test import lldbutil
class CrashingRecursiveInferiorStepTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_step(self):
"""Test that stepping after a crash behaves correctly."""
self.build()
self.recursive_inferior_crashing_step()
@skipIfTargetAndroid() # debuggerd interferes with this test on Android
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_step_after_break(self):
"""Test that lldb functions correctly after stepping through a crash."""
self.build()
self.recursive_inferior_crashing_step_after_break()
# Inferior exits after stepping after a segfault. This is working as
# intended IMHO.
@skipIfLinux
@skipIfFreeBSD
@expectedFailureNetBSD
def test_recursive_inferior_crashing_expr_step_and_expr(self):
"""Test that lldb expressions work before and after stepping after a crash."""
self.build()
self.recursive_inferior_crashing_expr_step_expr()
def set_breakpoint(self, line):
lldbutil.run_break_set_by_file_and_line(
self, "main.c", line, num_expected_locations=1, loc_exact=True)
def check_stop_reason(self):
# We should have one crashing thread
self.assertEqual(
len(
lldbutil.get_crashed_threads(
self,
self.dbg.GetSelectedTarget().GetProcess())), 1,
STOPPED_DUE_TO_EXC_BAD_ACCESS)
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number of the crash.
self.line = line_number('main.c', '// Crash here.')
def recursive_inferior_crashing_step(self):
"""Test that lldb functions correctly after stepping through a crash."""
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
self.set_breakpoint(self.line)
self.runCmd("run", RUN_SUCCEEDED)
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT,
substrs=['main.c:%d' % self.line, 'stop reason = breakpoint'])
self.runCmd("next")
self.check_stop_reason()
# The lldb expression interpreter should be able to read from addresses
# of the inferior after a crash.
self.expect("p i", substrs=['(int) $0 ='])
# lldb should be able to read from registers from the inferior after
# crashing.
lldbplatformutil.check_first_register_readable(self)
# And it should report the correct line number.
self.expect("thread backtrace all", substrs=['main.c:%d' % self.line])
def recursive_inferior_crashing_step_after_break(self):
"""Test that lldb behaves correctly when stepping after a crash."""
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
self.runCmd("run", RUN_SUCCEEDED)
self.check_stop_reason()
expected_state = 'exited' # Provide the exit code.
if self.platformIsDarwin():
# TODO: Determine why 'next' and 'continue' have no effect after a
# crash.
expected_state = 'stopped'
self.expect("next", substrs=['Process', expected_state])
if expected_state == 'exited':
self.expect(
"thread list",
error=True,
substrs=['Process must be launched'])
else:
self.check_stop_reason()
def recursive_inferior_crashing_expr_step_expr(self):
"""Test that lldb expressions work before and after stepping after a crash."""
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
self.runCmd("run", RUN_SUCCEEDED)
self.check_stop_reason()
# The lldb expression interpreter should be able to read from addresses
# of the inferior after a crash.
self.expect("p null", startstr='(char *) $0 = 0x0')
self.runCmd("next")
# The lldb expression interpreter should be able to read from addresses
# of the inferior after a step.
self.expect("p null", startstr='(char *) $1 = 0x0')
self.check_stop_reason()
|