[lldb-dev] Stack unwinding with hand-crafted CFI

Jason Molenda jason at molenda.com
Wed Apr 22 11:16:00 PDT 2015

> On Apr 22, 2015, at 6:56 AM, Pavel Labath <labath at google.com> wrote:
> Forgot to add the list.
> On 22 April 2015 at 14:54, Pavel Labath <labath at google.com> wrote:
>> Hello,
>> On 21 April 2015 at 18:04, Greg Clayton <gclayton at apple.com> wrote:
>>> The main problem is 99% of all the EH frame info is valid only at call sites. Because of this we don't use EH frame in the first frame and we don't use it after async interrupt functions like sigtramp.

Small clarification on Greg's summary here.  Since last summer, we've started using eh_frame for the currently-executing frame.  Both gcc and clang were generating eh_frame which described the function prologues.  And modern gcc's emit eh_frame which describes the epilogue.  So Tong Shen, an intern at Google, added code to add epilogue instructions if it looked like the eh_frame was missing them.

There's no guarantee that eh_frame unwind instructions will describe the prologue/epilogue, or that it will describe any important changes in the middle of the function except at places where the func can throw, or a callee can throw, but in practice the prologue at least is present.  So we decided to try living off eh_frame for the currently executing frame, and it seems to be working OK.

>> What I suggest is to change the logic to something like this:
>> eh := GetEHFrameUnwindPlan();
>> if (I_know_how_to_augment(eh))
>>  return Augment(eh)
>> else if (Plan_is_very_complicated(eh))
>>  return eh; // if the EH section contains a complicated plan, then
>> our attempts to do instruction profiling will likely fail. Let's just
>> stick to the EH plan instead.

This sounds like a good idea.  The augmentation detection code in UnwindAssembly-x86.cpp is kind of hacky (and it's done at two different layers in different ways) -- my main concern here was modifying a correct set of unwind instructions from eh_frame by adding incorrect garbage to it.  So it goes out of its way to limit the augmentation to functions that look "straightforward".

I had a similar problem with the objective c runtime on macosx.  It has several hand-written assembly functions that the assembly instruction profiler cannot handle correctly.  The maintainer of that solib added hand-written -- I added the DynamicLoader::AlwaysRelyOnEHUnwindInfo method for this case.  The unwinder will call the DynamicLoader and say "should I trust the eh_frame for this solib?" and the MacOSX DynamicLoader plugin will say yes for libobjc functions.  (this was back when we never used eh_frame instructions for the currently-executing frame)

That would be another way to handle this -- to whitelist the libc solib on Linux.  But I think your idea of flagging eh_frame which looks hand-written/complicated is a good one too.


More information about the lldb-dev mailing list