[lldb-dev] eh_frame or debug_frame

Jason Molenda jmolenda at apple.com
Tue Oct 14 15:51:36 PDT 2014


> On Oct 13, 2014, at 9:55 AM, Greg Clayton <gclayton at apple.com> wrote:
> 
> 
>> On Oct 10, 2014, at 1:58 PM, Francois Pichet <pichet2000 at gmail.com> wrote:
>> 
>> 
>> 
>> On Fri, Oct 10, 2014 at 4:20 PM, Greg Clayton <gclayton at apple.com> wrote:
>> 
>>> On Oct 10, 2014, at 1:05 PM, Philippe Lavoie <philippe.lavoie at octasic.com> wrote:
>>> 
>>> 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?
>> 
>> 
>> What about about C or C++ program compiled with -fno-exceptions? 
>> 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



More information about the lldb-dev mailing list