forked from OSchip/llvm-project
Don't assume that stepping out of a function will land on the next line.
For instance, some recent clang emits this code on x86_64: 0x100002b99 <+57>: callq 0x100002b40 ; step_out_of_here at main.cpp:11 -> 0x100002b9e <+62>: xorl %eax, %eax 0x100002ba0 <+64>: popq %rbp 0x100002ba1 <+65>: retq and the "xorl %eax, %eax" is attributed to the same line as the callq. Since step out is supposed to stop just on returning from the function, you can't guarantee it will end up on the next line. I changed the test to check that we were either on the call line or on the next line, since either would be right depending on the debug information.
This commit is contained in:
parent
fa26da0582
commit
71c4da83b6
|
@ -62,50 +62,58 @@ class ThreadStepOutTestCase(TestBase):
|
||||||
"""Test thread step out on one thread via Python API (dwarf)."""
|
"""Test thread step out on one thread via Python API (dwarf)."""
|
||||||
self.build(dictionary=self.getBuildFlags())
|
self.build(dictionary=self.getBuildFlags())
|
||||||
self.step_out_test(self.step_out_with_python)
|
self.step_out_test(self.step_out_with_python)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Call super's setUp().
|
# Call super's setUp().
|
||||||
TestBase.setUp(self)
|
TestBase.setUp(self)
|
||||||
# Find the line number for our breakpoint.
|
# Find the line number for our breakpoint.
|
||||||
self.bkpt_string = '// Set breakpoint here'
|
self.bkpt_string = '// Set breakpoint here'
|
||||||
self.breakpoint = line_number('main.cpp', self.bkpt_string)
|
self.breakpoint = line_number('main.cpp', self.bkpt_string)
|
||||||
|
self.step_in_line = line_number('main.cpp', '// But we might still be here')
|
||||||
|
self.step_out_dest = line_number('main.cpp', '// Expect to stop here after step-out.')
|
||||||
|
|
||||||
self.step_out_destination = line_number(
|
def check_stepping_thread(self):
|
||||||
'main.cpp', '// Expect to stop here after step-out.')
|
zeroth_frame = self.step_out_thread.frames[0]
|
||||||
|
line_entry = zeroth_frame.line_entry
|
||||||
|
self.assertTrue(line_entry.IsValid(), "Stopped at a valid line entry")
|
||||||
|
self.assertEqual("main.cpp", line_entry.file.basename, "Still in main.cpp")
|
||||||
|
# We can't really tell whether we stay on our line
|
||||||
|
# or get to the next line, it depends on whether there are any
|
||||||
|
# instructions between the call and the return.
|
||||||
|
line = line_entry.line
|
||||||
|
self.assertTrue(line == self.step_out_dest or line == self.step_in_line, "Stepped to the wrong line: {0}".format(line))
|
||||||
|
|
||||||
def step_out_single_thread_with_cmd(self):
|
def step_out_single_thread_with_cmd(self):
|
||||||
|
other_threads = {}
|
||||||
|
for thread in self.process.threads:
|
||||||
|
if thread.GetIndexID() == self.step_out_thread.GetIndexID():
|
||||||
|
continue
|
||||||
|
other_threads[thread.GetIndexID()] = thread.frames[0].line_entry
|
||||||
|
|
||||||
|
# There should be other threads...
|
||||||
|
self.assertNotEqual(len(other_threads), 0)
|
||||||
self.step_out_with_cmd("this-thread")
|
self.step_out_with_cmd("this-thread")
|
||||||
self.expect(
|
# The other threads should not have made progress:
|
||||||
"thread backtrace all",
|
for thread in self.process.threads:
|
||||||
"Thread location after step out is correct",
|
index_id = thread.GetIndexID()
|
||||||
substrs=[
|
line_entry = other_threads.get(index_id)
|
||||||
"main.cpp:%d" %
|
if line_entry:
|
||||||
self.step_out_destination,
|
self.assertEqual(thread.frames[0].line_entry.file.basename, line_entry.file.basename, "Thread {0} moved by file".format(index_id))
|
||||||
"main.cpp:%d" %
|
self.assertEqual(thread.frames[0].line_entry.line, line_entry.line, "Thread {0} moved by line".format(index_id))
|
||||||
self.breakpoint])
|
|
||||||
|
|
||||||
def step_out_all_threads_with_cmd(self):
|
def step_out_all_threads_with_cmd(self):
|
||||||
self.step_out_with_cmd("all-threads")
|
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):
|
def step_out_with_cmd(self, run_mode):
|
||||||
self.runCmd("thread select %d" % self.step_out_thread.GetIndexID())
|
self.runCmd("thread select %d" % self.step_out_thread.GetIndexID())
|
||||||
self.runCmd("thread step-out -m %s" % run_mode)
|
self.runCmd("thread step-out -m %s" % run_mode)
|
||||||
self.expect("process status", "Expected stop reason to be step-out",
|
self.expect("process status", "Expected stop reason to be step-out",
|
||||||
substrs=["stop reason = step out"])
|
substrs=["stop reason = step out"])
|
||||||
|
|
||||||
self.expect(
|
selected_thread = self.process.GetSelectedThread()
|
||||||
"thread list",
|
self.assertEqual(selected_thread.GetIndexID(), self.step_out_thread.GetIndexID(), "Step out changed selected thread.")
|
||||||
"Selected thread did not change during step-out",
|
self.check_stepping_thread()
|
||||||
substrs=[
|
|
||||||
"* thread #%d" %
|
|
||||||
self.step_out_thread.GetIndexID()])
|
|
||||||
|
|
||||||
def step_out_with_python(self):
|
def step_out_with_python(self):
|
||||||
self.step_out_thread.StepOut()
|
self.step_out_thread.StepOut()
|
||||||
|
|
||||||
|
@ -115,18 +123,12 @@ class ThreadStepOutTestCase(TestBase):
|
||||||
reason,
|
reason,
|
||||||
"Expected thread stop reason 'plancomplete', but got '%s'" %
|
"Expected thread stop reason 'plancomplete', but got '%s'" %
|
||||||
lldbutil.stop_reason_to_str(reason))
|
lldbutil.stop_reason_to_str(reason))
|
||||||
|
self.check_stepping_thread()
|
||||||
# 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):
|
def step_out_test(self, step_out_func):
|
||||||
"""Test single thread step out of a function."""
|
"""Test single thread step out of a function."""
|
||||||
(self.inferior_target, self.inferior_process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
(self.inferior_target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
self, self.bkpt_string, lldb.SBFileSpec('main.cpp'), only_one_thread = False)
|
self, self.bkpt_string, lldb.SBFileSpec('main.cpp'), only_one_thread = False)
|
||||||
|
|
||||||
# We hit the breakpoint on at least one thread. If we hit it on both threads
|
# We hit the breakpoint on at least one thread. If we hit it on both threads
|
||||||
|
@ -135,13 +137,13 @@ class ThreadStepOutTestCase(TestBase):
|
||||||
# the breakpoint:
|
# the breakpoint:
|
||||||
|
|
||||||
(breakpoint_threads, other_threads) = ([], [])
|
(breakpoint_threads, other_threads) = ([], [])
|
||||||
lldbutil.sort_stopped_threads(self.inferior_process,
|
lldbutil.sort_stopped_threads(self.process,
|
||||||
breakpoint_threads=breakpoint_threads,
|
breakpoint_threads=breakpoint_threads,
|
||||||
other_threads=other_threads)
|
other_threads=other_threads)
|
||||||
if len(breakpoint_threads) == 1:
|
if len(breakpoint_threads) == 1:
|
||||||
success = thread.Suspend()
|
success = thread.Suspend()
|
||||||
self.assertTrue(success, "Couldn't suspend a thread")
|
self.assertTrue(success, "Couldn't suspend a thread")
|
||||||
bkpt_threads = lldbutil.continue_to_breakpoint(self.inferior_process,
|
bkpt_threads = lldbutil.continue_to_breakpoint(self.process,
|
||||||
bkpt)
|
bkpt)
|
||||||
self.assertEqual(len(bkpt_threads), 1, "Second thread stopped")
|
self.assertEqual(len(bkpt_threads), 1, "Second thread stopped")
|
||||||
success = thread.Resume()
|
success = thread.Resume()
|
||||||
|
|
|
@ -19,7 +19,7 @@ thread_func ()
|
||||||
pseudo_barrier_wait(g_barrier);
|
pseudo_barrier_wait(g_barrier);
|
||||||
|
|
||||||
// Do something
|
// Do something
|
||||||
step_out_of_here();
|
step_out_of_here(); // But we might still be here
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return NULL; // Expect to stop here after step-out.
|
return NULL; // Expect to stop here after step-out.
|
||||||
|
|
Loading…
Reference in New Issue