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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
"""
Test stepping out from a function in a multi-threaded program.
"""
from __future__ import print_function
import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class ThreadStepOutTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
# Test occasionally times out on the Linux build bot
@skipIfLinux
@expectedFailureAll(
oslist=["linux"],
bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot")
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr18066 inferior does not exit")
@expectedFailureAll(oslist=["windows"])
def test_step_single_thread(self):
"""Test thread step out on one thread via command interpreter. """
self.build(dictionary=self.getBuildFlags())
self.step_out_test(self.step_out_single_thread_with_cmd)
# Test occasionally times out on the Linux build bot
@skipIfLinux
@expectedFailureAll(
oslist=["linux"],
bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot")
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint")
@expectedFailureAll(oslist=["windows"])
@expectedFailureAll(oslist=["watchos"], archs=['armv7k'], bugnumber="rdar://problem/34674488") # stop reason is trace when it should be step-out
def test_step_all_threads(self):
"""Test thread step out on all threads via command interpreter. """
self.build(dictionary=self.getBuildFlags())
self.step_out_test(self.step_out_all_threads_with_cmd)
# Test occasionally times out on the Linux build bot
@skipIfLinux
@expectedFailureAll(
oslist=["linux"],
bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot")
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint")
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681")
def test_python(self):
"""Test thread step out on one thread via Python API (dwarf)."""
self.build(dictionary=self.getBuildFlags())
self.step_out_test(self.step_out_with_python)
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number for our breakpoint.
self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
if "gcc" in self.getCompiler() or self.isIntelCompiler():
self.step_out_destination = line_number(
'main.cpp', '// Expect to stop here after step-out (icc and gcc)')
else:
self.step_out_destination = line_number(
'main.cpp', '// Expect to stop here after step-out (clang)')
def step_out_single_thread_with_cmd(self):
self.step_out_with_cmd("this-thread")
self.expect(
"thread backtrace all",
"Thread location after step out is correct",
substrs=[
"main.cpp:%d" %
self.step_out_destination,
"main.cpp:%d" %
self.breakpoint])
def step_out_all_threads_with_cmd(self):
self.step_out_with_cmd("all-threads")
self.expect(
"thread backtrace all",
"Thread location after step out is correct",
substrs=[
"main.cpp:%d" %
self.step_out_destination])
def step_out_with_cmd(self, run_mode):
self.runCmd("thread select %d" % self.step_out_thread.GetIndexID())
self.runCmd("thread step-out -m %s" % run_mode)
self.expect("process status", "Expected stop reason to be step-out",
substrs=["stop reason = step out"])
self.expect(
"thread list",
"Selected thread did not change during step-out",
substrs=[
"* thread #%d" %
self.step_out_thread.GetIndexID()])
def step_out_with_python(self):
self.step_out_thread.StepOut()
reason = self.step_out_thread.GetStopReason()
self.assertEqual(
lldb.eStopReasonPlanComplete,
reason,
"Expected thread stop reason 'plancomplete', but got '%s'" %
lldbutil.stop_reason_to_str(reason))
# Verify location after stepping out
frame = self.step_out_thread.GetFrameAtIndex(0)
desc = lldbutil.get_description(frame.GetLineEntry())
expect = "main.cpp:%d" % self.step_out_destination
self.assertTrue(
expect in desc, "Expected %s but thread stopped at %s" %
(expect, desc))
def step_out_test(self, step_out_func):
"""Test single thread step out of a function."""
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# This should create a breakpoint in the main thread.
lldbutil.run_break_set_by_file_and_line(
self, "main.cpp", self.breakpoint, num_expected_locations=1)
# The breakpoint list should show 1 location.
self.expect(
"breakpoint list -f",
"Breakpoint location shown correctly",
substrs=[
"1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" %
self.breakpoint])
# Run the program.
self.runCmd("run", RUN_SUCCEEDED)
# Get the target process
self.inferior_target = self.dbg.GetSelectedTarget()
self.inferior_process = self.inferior_target.GetProcess()
# Get the number of threads, ensure we see all three.
num_threads = self.inferior_process.GetNumThreads()
self.assertEqual(
num_threads,
3,
'Number of expected threads and actual threads do not match.')
(breakpoint_threads, other_threads) = ([], [])
lldbutil.sort_stopped_threads(self.inferior_process,
breakpoint_threads=breakpoint_threads,
other_threads=other_threads)
while len(breakpoint_threads) < 2:
self.runCmd("thread continue %s" %
" ".join([str(x.GetIndexID()) for x in other_threads]))
lldbutil.sort_stopped_threads(
self.inferior_process,
breakpoint_threads=breakpoint_threads,
other_threads=other_threads)
self.step_out_thread = breakpoint_threads[0]
# Step out of thread stopped at breakpoint
step_out_func()
# Run to completion
self.runCmd("continue")
# At this point, the inferior process should have exited.
self.assertTrue(self.inferior_process.GetState() ==
lldb.eStateExited, PROCESS_EXITED)
|