eh_frame or debug_frame

Hi,

I noticed that by default lldb does not read .debug_frame section to unwind frames but relies instead on .eh_frame .

Is there a way to fallback to reading .debug_frame?

I tried getting DWARFCallFrameInfo to read a .debug_frame section, but it fails interpreting the CIE_id field. It assumes that it is a CIE Pointer.

error: unable to find CIE at 0x00000014 for cie_id = 0x000000c8 for entry at 0x000000d8.
error: unable to find CIE at 0x0000004c for cie_id = 0x000000c8 for entry at 0x00000110.
error: unable to find CIE at 0x00000068 for cie_id = 0x000000c8 for entry at 0x0000012c.

Thanks,
-Philippe

Hi,

I noticed that by default lldb does not read .debug_frame section to unwind frames but relies instead on .eh_frame .

Is there a way to fallback to reading .debug_frame?

Not currently. Most compilers (gcc _and_ clang) put the same old stuff in .debug_frame as they do in .eh_frame, so we haven't had to use .debug_frame over .eh_frame yet. What compiler are using that is putting different (more complete) info in .debug_frame vs .eh_frame?

I tried getting DWARFCallFrameInfo to read a .debug_frame section, but it fails interpreting the CIE_id field. It assumes that it is a CIE Pointer.

There is a boolean you have to set to true or false in the contractor:

    DWARFCallFrameInfo (ObjectFile& objfile,
                        lldb::SectionSP& section,
                        lldb::RegisterKind reg_kind,
                        bool is_eh_frame);

Set "is_eh_frame" to false if you are using DWARF and the errors below will disappear.

s/contractor/constructor/

They will fall back to the UnwindAssembly way even if the .debug_frame is
present right?

If no EH frame exists for a frame, then we will always fall back to UnwindAssembly. We always use UnwindAssembly for the first frame and for any frame that is past an async interrupt (sigtramp). We use the EH frame/.debug_frame for any non-zero frames, but will always use UnwindAssembly if there is no such info.

I want to expand on what Greg said earlier about eh_frame versus debug_frame.

Ideally, eh_frame will be the minimal unwind instructions necessary to unwind the stack when exceptions are thrown/caught. eh_frame will not include unwind instructions for the prologue instructions or epilogue instructions -- because we can't throw an exception there, or have an exception thrown from a called function "below" us on the stack. We call these unwind instructions "synchronous" because they only describe the unwind state from a small set of locations.

debug_frame would describe how to unwind the stack at every instruction location. Every instruction of the prologue and epilogue. If the code is built without a frame pointer, then it would have unwind instructions at every place where the stack pointer is modified. We describe these unwind instructions as "asynchronous" because they describe the unwind state at every instruction location.

Instead what we have with gcc and clang is eh_frame instructions that describe the prologue (and some versions of gcc, the epilogue) plus the unwind state at synchronous unwind locations (where an exception can be thrown). We have a half-way blend of asynchronous and synchronous ... it's "pretty good" but not "guaranteed" from a debugger's perspective. It would be great if eh_frame was genuinely only the unwind instructions for exception handling and debug_frame had the full unwind state at every instruction and we could depend on debug_frame. But in reality, the same unwind instructions are put in both eh_frame and debug_frame -- so there's little point in ever reading debug_frame. lldb does not read debug_frame today, although it would be easy to do so.

As an experiment starting late August (r216406), lldb is now trying to use eh_frame for the currently-executing frame. Even though it isn't *guaranteed* to be accurate at all instructions, in practice it's pretty good -- good enough that gdb seems to be able to live on it. Tong Shen's patch in r216406 does augment the eh_frame unwind instructions with the epilogue unwind... newer gcc's apparently describe the epilogue in eh_frame but few other compilers do.

It's an open question how well living off eh_frame unwind instructions will work with a non-gcc/non-clang compiler. That's why I say this is an "experiment" - we may have to revert to lldb's UnwindAssembly profiling code for the currently-executing function if this breaks with other compilers.

J