[lldb-dev] Problem unwinding from inside of a CRT function
jingham at apple.com
jingham at apple.com
Fri Jan 16 15:10:20 PST 2015
> On Jan 16, 2015, at 1:42 PM, Reid Kleckner <rnk at google.com> wrote:
> On Fri, Jan 16, 2015 at 12:44 PM, <jingham at apple.com> wrote:
> 1) In the original implementation, (and this is how gdb does it, BTW) lldb single-stepped till "something interesting happened." As an optimization, when you are doing any kind of step through source range, I changed lldb so it runs from "instruction that could branch" to "instruction that could branch" using breakpoints. Then when it hits an instruction that could branch it single steps that instruction, and then figures out from where that went what to do next.
> BTW, if it were helpful to figure out what to do next, we could store some info (the old stack frame or whatever) when we hit a branch instruction, and then use it when the single-step completed. I haven't needed to do that yet, however; Jason's always been able to get the unwinder work reliably enough not to require this.
> First, we should definitely teach the Windows unwinder to fall back to frame pointers if no debug info is present. That's an obvious win.
> However, there are lots of environments (not just Windows) where unwinding is unreliable due to third party libraries, so it'd be nice if we can get by without unwinding.
> 2) If the single step pushes a frame, and we are "stepping over", lldb sets a breakpoint on the return address and continues. When the return address is hit (for the current frame of course since it could be hit recursively) then we continue stepping as above.
> Any objection to asking the target if the previous opcode is something typically used for a call (x86 call, ARM bl), single step, and then load the retaddr or link register? Is that hard to thread through? I suppose it would fire on 32-bit x86 PIC sequences (call 0 ; pop %ebx), but that won't hurt.
The agents that manage stepping, etc (ThreadPlans) are persistent through-out the operation they manage. They live in a little stack of operations, so there's always one entity per step type operation (i.e. if you next, hit a breakpoint, call a function, hit a breakpoint in the function, next again, etc. each of these operations has a Thread Plan to govern it.) It wouldn't be hard to store some data in them, and use it either to convey hints to the unwinder when you step in, as Jason suggests, or whatever you needed to do.
One thing, the ThreadPlans are currently architecture agnostic, and I'd like to keep it that way, so whatever you need to express should be done in an architecture-independent way. That might add a little complexity, but one I think will be worthwhile long term.
But I agree with Jason that, from a resource allocation standpoint, time spent on the unwinder would benefit the whole system much more than time spent hacking around its deficiencies in the ThreadPlans.
More information about the lldb-dev