Yeah, lldb uses similar tricks.  If you have eh_frame instructions, unwinding 
from -fomit-frame-pointer code is easy.  And if you have accurate function 
bounds for all the frames, lldb can usually manage to unwind an 
-fomit-frame-pointer stack without eh_frame (because it inspects the actual 
assembly instructions in the prologue to understand the stack setup).  But in 
this particular backtrace we've got -fomit-frame-pointer frames using eh_frame, 
then one function that doesn't have any symbol name or eh_frame entry, and I 
honestly have no idea how gdb found its way out of that one.  The only 
reasonable approach here would be to assume that this frame used a frame 
pointer (rbp), grab the saved rbp value and try to find the caller's pc based 
on that -- but that failed.

Well, maybe the additional information from Ben (the eh_frame instructions for 
abort() most importantly) will provide a hint.  The only thing I can think is 
that maybe lldb misinterpreted that function's eh_frame instructions.

J


On Apr 8, 2013, at 1:20 AM, Luddy Harrison wrote:

> having done lots of asm debugging with gdb, I can offer a guess.  gdb seems 
> to able to unwind frameless leaf functions with no unwind info.   so perhaps 
> as a final fallback it pops the top entry on the stack and treats it as the 
> return pc.  if it can unwind the caller using that pc, the it is good.
> 
> just a guess...
> 
> -Luddy
> 
> Sent from my iPhone
> 
> On 8 Apr, 2013, at 6:01, Jason Molenda <[email protected]> wrote:
> 
>> I see what's going on here.
>> 
>> /lib/x86_64-linux-gnu/libc.so.6 was built -fomit-frame-pointer, and it 
>> includes eh_frame instructions on how to unwind the frames.  But when lldb 
>> gets to 
>> 
>> #2  0x00007ffff7a4a0ee in ?? () from /lib/x86_64-linux-gnu/libc.so.6
>> 
>> it doesn't have any eh_frame instructions.  lldb can figure out the stack 
>> pointer value (from frame 1) which tells us the "bottom" of this stack frame 
>> but it can't find the "top" without eh_frame unwind instructions or knowing 
>> what function it is in so it can do an assembly instruction scan to 
>> understand how the stack frame was set up.  lldb tries to get a saved frame 
>> pointer (rbp) which would give us the "top" of the stack frame but the saved 
>> rbp value it gets (0x40067e0) is obviously invalid.
>> 
>> It might be interesting to see the output of 
>> 
>> image show-unwind -n abort
>> 
>> to see exactly what the eh_frame instructions read (this is lldb's 
>> interpretation of the eh_frame instructions, of course, it might be useful 
>> to include the output of readelf -wf libc.so.6 or readelf -wF libc.so.6 for 
>> the abort() function, going by a web page for readelf I found on the web.)  
>> The log output included this,
>> 
>> th1/fr0 supplying caller's saved reg 16's location, cached
>> th1/fr1 requested caller's saved PC but this UnwindPlan uses a RA reg; 
>> getting reg 16 instead
>> th1/fr1 supplying caller's saved reg 16's location using eh_frame CFI 
>> UnwindPlan
>> th1/fr1 supplying caller's register 16 from the stack, saved at CFA plus 
>> offset
>> th1/fr2 pc = 0x00007f216e4850ee
>> 
>> That bit about "this UnwindPlan uses a RA reg" is novel for x86 code, it's 
>> normally you see in arm code where the caller's saved pc value is in the 
>> link register on a function call.  But as you'd guess from the name abort(), 
>> this may have the caller's register context saved in an unusual way so this 
>> may be fine.
>> 
>> I'm surprised gdb can unwind this successfully.
>> 
>> As I alluded to above, lldb can profile the assembly language instructions 
>> of a function to understand the prologue setup (where registers are saved, 
>> how the stack is set up, etc.) -- but to do this, it needs to know the start 
>> address of the function.  This "#2  0x00007ffff7a4a0ee in ?? ()" frame 
>> clearly doesn't have any symbolic information with its address range so lldb 
>> can't do its assembly scan.  And it doesn't have eh_frame instructions to 
>> help either.
>> 
>> On Mac OS X we're often working with binaries that have had most of their 
>> symbols stripped.  Because it is so valuable to lldb to have accurate 
>> function ranges, we supplement the symbol table with two sources:  The 
>> LC_FUNCTION_STARTS section, and barring that (this is new), the eh_frame 
>> section.  LC_FUNCTION_STARTS is an array of LEB128 encoded offsets of all 
>> the start addresses of the functions in the file.  The first function is at 
>> offset 0, etc.  It's real compact, typically a few bytes per function.  The 
>> eh_frame section is another great source of function bounds information but 
>> it tends to be larger and slower to parse through.  lldb adds fake symbol 
>> names for these function ranges that it adds, e.g. a fake symbol added to 
>> the program Dock might be "__lldb_unnamed_function3491$$Dock".
>> 
>> Of course, given that lldb couldn't find eh_frame instructions for "#2  
>> 0x00007ffff7a4a0ee in ?? ()", maybe even that wouldn't have helped.
>> 
>> 
>> The only solution I can think of here is if abort()'s eh_frame does provide 
>> a saved location for rbp but lldb failed to read it correctly.  Else, I have 
>> no idea how gdb managed to unwind out of this one.
>> 
>> 
>> On Apr 7, 2013, at 5:46 AM, Langmuir, Ben wrote:
>> 
>>> Done.
>>> 
>>> -----Original Message-----
>>> From: Jason Molenda [mailto:[email protected]] 
>>> Sent: Sunday, April 07, 2013 5:50 AM
>>> To: Langmuir, Ben
>>> Subject: regarding [Bug 15671] New: backtrace truncated after assertion 
>>> failure in inferior
>>> 
>>> I don't know if I have a bugzilla account on llvm.org (I should but I don't 
>>> know what password it might have) but I wanted to ask you to do
>>> 
>>> (lldb) log enable lldb unwind
>>> (lldb) run
>>> (lldb) bt
>>> 
>>> 
>>> and attach that output to http://llvm.org/bugs/show_bug.cgi?id=15671 
>>> 
>>> lldb should use a DefaultUnwindPlan for frame 2 ("?? ()" in gdb's 
>>> backtrace) to continue the unwind.  I don't have linux installed on any 
>>> devices so I haven't looked but the output will probably be a good clue as 
>>> to why the unwind stopped early.
>>> 
>>> 
>>> 
>>> J
>> 
>> 
>> _______________________________________________
>> lldb-dev mailing list
>> [email protected]
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev


_______________________________________________
lldb-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to