[lldb-dev] Problem unwinding from inside of a CRT function

jingham at apple.com jingham at apple.com
Tue Jan 20 13:06:57 PST 2015


> On Jan 20, 2015, at 12:31 PM, Zachary Turner <zturner at google.com> wrote:
> 
> In practice how slow is this for stepping over very lengthy calls?  It sounds like LLDB still generates a call stack at every branch point, which while certainly faster than generating one at every instruction, still seems like it has the potential to be very slow.  

At most, lldb only needs to get the current frame & its parent frame to run its stepping algorithm.  It won't generate a full stack frame unless you ask it to.  Getting two frames should be pretty quick.

> I still wonder about an algorithm such as one that differentiates between local control flow instructions (jmp, jnz, etc) and non-local control flow instructions (call).  Single step the the local control flow instructions, and put a breakpoint at the return address of the non-local control flow instructions.  This requires introducing some architecture specific dependencies into the ThreadPlan, but it doesn't seem much more than those that are already in the thread plan.  For example, the ThreadPlan currently has to scan forward to the next branch instruction to put the breakpoint.  So this only adds the ability to differentiate between different types of branch instructions (e.g. those that transfer-and-forget, and those that transfer-and-return.  Seems like this yields near zero-overhead in terms of executing the step-over.

So one thing to note: I implemented the "run from branch instruction to branch instruction" for two reasons, one was possible performance improvements, and the other because many architectures have some instructions that you can't reliably single step over (as you mentioned earlier.)  So I wanted lldb to single-step as little as possible.  The second goal was achieved by definition.  But I tested the performance improvements for Mac native debugging and for iOS debugging, and while there was some speedup, for the things we cared about, the speedup was quite small, pretty much in the noise.  And here I was saving you many round-trips since most code does a fair bit of work between branches.  At best your suggestion would save one round-trip.

As Jason says, we spent a fair amount of effort on optimizing gdb-remote packet sequences.  And for native process plugins like Windows etc. there's no excuse for these primitive operations to be slow.  And computers are pretty fast these days.  Maybe if you are talking to some really slow device this might start to be an issue.  So I don't think that performance is a good reason to complicate the stepping algorithms in this way.  

If you can get increased stepping accuracy with more predictive approaches, then that might be worth the effort.  However, one of the nice things about the current method is if where you ended up confuses you, you can stop at that point & return control to the user.  The more lldb does "predict where the code is going to go, set a breakpoint there and continue" the more it risks "step -> continue".  That is much worse from a user's perspective than step-over -> step-in.

Jim
 

>  
> 
> As with last time, I'm probably missing something, and I'm mostly just thinking out loud :)
> 
> On Tue Jan 20 2015 at 12:23:28 PM Jason Molenda <jason at molenda.com> wrote:
> 
> > On Jan 20, 2015, at 4:21 AM, Hafiz Abid Qadeer <hafiz_abid at mentor.com> wrote:
> >
> >
> >
> > GDB also has range stepping thing now.
> > https://sourceware.org/ml/gdb-patches/2013-03/msg00450.html
> 
> 
> 
> Jim points out that this is a different approach than lldb took -- it's pushing some limited amount of single instruction stepping down into the remote stub.
> 
> The cost of single instruction stepping can be broken down into (1) time to stop the inferior process, (2) time to communicate inferior state between stub and debugger, and (3) time for the debugger decide whether to resume the process or not.
> 
> The gdb approach reduces 2 & 3.  lldb's approach is addressing all of 1-3.  A single source line may have many function calls embedded within it -- printf("%d\n", f(g(x))); -- so lldb will still be need to stop the inferior 4 more times than gdb for this sequence (stop at the point of the call instruction, then single instruction step into the call -- whereas with gdb's approach the stub will single instruction step into the call and then report back to gdb).
> 
> In lldb we've put a lot of time in optimizing #2.  Besides getting rid of the "acks" in the gdb-remote protocol by default (needed for an unreliable transport medium, like a raw serial connection to a target board), we looked at what pieces of information lldb needs to decide whether to keep stepping or stop.  It needs to know the stop reason, it needs to know the pc, it needs the stack pointer, and it probably needs the frame pointer.  So in the "T" packet which the stub sends to indicate that the inferior has stopped, we have a list of "expedited registers" - register values that the stub provides without being asked.
> 
> The result is that every time lldb needs to step a single instruction within a function bounds, there are two packets sent:  The "T05" packet indicating the inferior stopped, and lldb sending back another "vCont;s" packet saying to instruction step again, if appropriate.  The overhead of #2 has been dramatically reduced by this approach.   (think about a scenario where there are no expedited registers in the T packet - the debugger is going to need to ask for each of these registers individually, or get all registers via the g packet, and it's going to be really slow.)
> 
> 
> The approach Jim did with lldb does assume that you have a disassembler with annotations regarding whether an instruction can affect flow control - branches, calls, jumps, etc.  The llvm disassembler includes these annotations.  Last time I looked at the disassembler gdb is using, it doesn't include this kind of information about instructions.
> 
> J
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev





More information about the lldb-dev mailing list