This is an archive of the discontinued LLVM Phabricator instance.

LLDB step-instruction gets stuck on jump to self
Needs RevisionPublic

Authored by sirmc on Jun 14 2020, 11:00 AM.

Details

Reviewers
jingham
teemperor
Group Reviewers
Restricted Project
Summary

When executing thread step-inst / si on an instruction that returns to the same PC, LLDB currently keeps stepping indefinitely.

I couldn't find the exact semantics for the step-instruction, but https://lldb.llvm.org/use/map.html suggests the behavior to be equivalent to GDB's si. GDB steps exactly one instruction, without the assumption that the program counter has to change.

Reproduce with the following code:

int main()
{
  while(1){};
  return 0;
}

When compiled with clang -g a.c, the above example generates an instruction (X86-64 jmpq) that jumps to the address of itself. When reaching the line with the loop, a si will never stop/break in this case, since the assumption is that the PC needs to change for the stepping to be finished.

Diff Detail

Event Timeline

sirmc created this revision.Jun 14 2020, 11:00 AM
sirmc edited the summary of this revision. (Show Details)Jun 14 2020, 11:01 AM
miko added a subscriber: miko.Jun 15 2020, 1:27 AM

Just to be clear, the lldb -> gdb command map doesn't prescribe behavior for lldb commands. It just suggests the analogous command in gdb. We are still free to implement lldb behavior however seems best to us.

The logic in lldb doesn't change the logic of the program's execution. This is just about when we return control to the user.

I can't 100% remember why I checked that the pc changed originally - it has been this way forever... But I think I was worried that you would do a stepi and another thread would make progress but this thread wouldn't and then we'd call the stepi completed. That would be confusing, since you would look to see the effects of the instruction we told you got to run, and they wouldn't be there...

However, the code that queries for stop reasons is pretty careful to avoid asking questions of threads that didn't stop "for a reason". So, what actually happens nowadays is that we would note that we hadn't gotten the "trace" stop state for this thread, not consult the thread's plan stack at all, and so we wouldn't end up misreporting the stop reason. So I don't think that's a real concern.

On the grounds that it is always better, when in doubt, to return control to the user & let them figure out what to do that to keep going on, I'm fine with the changed behavior.

If you want to keep this behavior from changing over time, however, you probably want to write a test for it. I don't think you can count on while {} always having a jump back to itself. But you could write an inline asm test that inserts this instruction and make sure that stops after the stepi. That would be architecture specific, but I don't see another way to get this behavior in a way that you can test for it.

sirmc added a comment.Jun 16 2020, 8:27 AM

Yes, I wasn't sure what the exact semantics were for step-inst for LLDB. I think the issue is not mainly the mimicking of GDB behavior, but rather that it is inconvenient for some use-cases.

To give some context on why I propose this change: the current behavior is pretty cumbersome when doing automated testing with LLDB of unknown/ generated programs. For example making use of the Python API, AFAIK, there is no interface where you can run a bounded number of instructions if lldb.SBThread.StepInstruction is not guaranteed to return (the current hack around it would be run this in a separate thread with a timeout).

Yes, I wasn't sure what the exact semantics were for step-inst for LLDB. I think the issue is not mainly the mimicking of GDB behavior, but rather that it is inconvenient for some use-cases.

To give some context on why I propose this change: the current behavior is pretty cumbersome when doing automated testing with LLDB of unknown/ generated programs. For example making use of the Python API, AFAIK, there is no interface where you can run a bounded number of instructions if lldb.SBThread.StepInstruction is not guaranteed to return (the current hack around it would be run this in a separate thread with a timeout).

This seems entirely reasonable. It would be good to get a test case so somebody doesn't inadvertently change the behavior.

teemperor requested changes to this revision.Mar 25 2021, 6:31 AM
teemperor added a subscriber: teemperor.

(Marking as requested-changes to get this out of my review queue)

This revision now requires changes to proceed.Mar 25 2021, 6:31 AM