-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb] Expose QueueThreadPlanForStepSingleInstruction function to SBThreadPlan #137904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
998d59c
7cedaf5
b9658d5
4d7a735
1faea15
df629ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,48 @@ def step_out_with_scripted_plan(self, name): | |
stop_desc = thread.GetStopDescription(1000) | ||
self.assertIn("Stepping out from", stop_desc, "Got right description") | ||
|
||
def run_until_branch_instruction(self): | ||
self.build() | ||
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( | ||
self, "Break on branch instruction", self.main_source_file | ||
) | ||
|
||
# Check that we landed in a call instruction | ||
frame = thread.GetFrameAtIndex(0) | ||
current_instruction = target.ReadInstructions(frame.GetPCAddress(), 1)[0] | ||
self.assertEqual( | ||
lldb.eInstructionControlFlowKindCall, | ||
current_instruction.GetControlFlowKind(target), | ||
) | ||
return (target, process, thread, bkpt) | ||
|
||
def test_step_single_instruction(self): | ||
(target, process, thread, bkpt) = self.run_until_branch_instruction() | ||
|
||
err = thread.StepUsingScriptedThreadPlan("Steps.StepSingleInstruction") | ||
self.assertSuccess(err) | ||
|
||
# Verify that stepping a single instruction after "foo();" steps into `foo` | ||
frame = thread.GetFrameAtIndex(0) | ||
self.assertEqual("foo", frame.GetFunctionName()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case of step-i, we are really trying to assert that we step just one instruction. That's actually not all that hard to test exactly. Just add some simple arithmetic computation to the test, so it won't have branches, and then stop at the beginning of the computation, run your step-i plan, and assert that you did get to the NEXT instruction on the instruction list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that testing a branch is more powerful though, because in a case of a non branch instruction both |
||
|
||
def test_step_single_instruction_with_step_over(self): | ||
(target, process, thread, bkpt) = self.run_until_branch_instruction() | ||
|
||
frame = thread.GetFrameAtIndex(0) | ||
next_instruction = target.ReadInstructions(frame.GetPCAddress(), 2)[1] | ||
next_instruction_address = next_instruction.GetAddress() | ||
|
||
err = thread.StepUsingScriptedThreadPlan( | ||
"Steps.StepSingleInstructionWithStepOver" | ||
) | ||
self.assertSuccess(err) | ||
|
||
# Verify that stepping over an instruction doesn't step into `foo` | ||
frame = thread.GetFrameAtIndex(0) | ||
self.assertEqual("main", frame.GetFunctionName()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the thread plan failed to move at all, this assert would pass. Figuring out where you go with nexti over a function call is a little trickier than stepi, so it's probably okay here to just assert that you didn't step into foo but the PC did change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might also assert before the nexti that you really are at a branch (you can get the instruction list for the function, find the instruction you are stopped at and ask it IsBranch. It seems really unlikely that any compiler/architecture would would emit more than a single branch and link for a call to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense, I didn't have any other straightfoward idea for a 100% way to break on a branch instruction but adding a check is a good idea |
||
self.assertEqual(next_instruction_address, frame.GetPCAddress()) | ||
|
||
def test_misspelled_plan_name(self): | ||
"""Test that we get a useful error if we misspell the plan class name""" | ||
self.build() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,6 @@ void foo() { | |
} | ||
|
||
int main() { | ||
foo(); | ||
foo(); // Break on branch instruction. | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I don't think is implemented for arm targets