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

Zachary Turner zturner at google.com
Tue Mar 10 17:26:20 PDT 2015


I'm going to be revisiting this soon, but one thing I was never clear about.

If I step over a function call, does it do this algorithm of single
stepping a call instruction and then running until the next branch point
_all the way down_, or does it only do it one level deep?  In other words,
say I have this code

void baz() {
  printf("Test");
}

void bar() {
   baz();
}

void foo() {
   bar();
}

and I'm inside of foo(), and I want to step over bar.  It will single step
the call, end up inside of bar.  Then run to the next branch point.  Does
it now single step baz, end up in baz, run to next branch point, and then
single step printf, and then continue this all the way down?  Or once it
figures out where it is inside of bar, that's sufficient to let it run
until the return address?

If it's the former, where it does this all the way down, what if some
function deep down in the call chain is a hand-written assembly function
that uses a custom calling convention?

On Wed, Jan 21, 2015 at 4:21 PM Greg Clayton <gclayton at apple.com> wrote:

>
> > On Jan 21, 2015, at 2:16 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > On Fri Jan 16 2015 at 1:53:00 PM Greg Clayton <gclayton at apple.com>
> wrote:
> >
> > Also, did you get my comment about improving functions bounds in the
> COFF parser? If you can do this, you won't really need to do any of the
> unwinding stuff because the assembly unwinder will take care of it, you
> just need to get good function bounds for everything using any means
> necessary in the ObjectFileCOFF parser by making all the symbols you can.
> You also need to identify what parts are trampolines. For example a call to
> printf usually goes through a PLT entry. These are often in one place in
> your binary and often there are not symbols in the symbol table for these.
> Identifying the symbols with a name like "printf" and also making the
> symbol a eSymbolTypeTrampoline will allow us to not set a breakpoint on
> your "printf" trampoline when you say "b printf" on the command line, and
> it will also give function bounds to these small trampoline code sections
> so we can step and unwind through them.
> >
> >
> >  Regarding the function bounds, I thought about this some, and I'm not
> sure if this is going to be possible.  Consider a system library, like the
> CRT, being linked against with no symbol information.  Where are the
> function bounds going to coem from?  There's nothing in the symbol table of
> the COFF file, and there's no debug info.  And since we're talking about an
> x86 binary, unwind info is not part of the ABI.  There's just a huge block
> of code in the code section.  Even if we do have symbols (which is how we
> would determine function bounds for code we have no control over), we will
> only have "public symbols" released by Microsoft.  Public symbols do not
> consist of information about every function, and practically any
> non-trivial call is going to at some point transfer control to one of the
> private functions that have no symbol information.
>
> We find ways in MachO that don't involve symbols:
> - EH frame
> - LC_FUNCTION_STARTS
> - dynamic linker stub info we parse
> - dynamic linker trie information for resolver symbols
>
> None of these are symbol table based and yet we can find function bounds.
>
> From:
>
> https://msdn.microsoft.com/en-us/magazine/cc301808.aspx
>
> I see:
>
> Program Exception Data
>       Some architectures (including the IA-64) don't use frame-based
> exception handling, like the x86 does; instead, they used table-based
> exception handling in which there is a table containing information about
> every function that might be affected by exception unwinding. The data for
> each function includes the starting address, the ending address, and
> information about how and where the exception should be handled. When an
> exception occurs, the system searches through the tables to locate the
> appropriate entry and handles it. The exception table is an array of
> IMAGE_RUNTIME_FUNCTION_ENTRY structures. The array is pointed to by the
> IMAGE_DIRECTORY_ENTRY_EXCEPTION entry in the DataDirectory. The format of
> the IMAGE_RUNTIME_FUNCTION_ENTRY structure varies from architecture to
> architecture. For the IA-64, the layout looks like this:
> DWORD BeginAddress;
> DWORD EndAddress;
> DWORD UnwindInfoAddress;
>
> Not sure if it covers all functions, but it does sound like it would at
> least help a little.
>
> If there really is no way to figure this out, we might need to resort to
> looking for function bounds by disassembling and watching for callq
> instructions to look for internal calls. We should be able to identify all
> external symbols via the exports.
>
> Greg
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150311/699f7d68/attachment.html>


More information about the lldb-dev mailing list