Page MenuHomePhabricator

Add "support" for DW_CFA_GNU_args_size to the unwinder
ClosedPublic

Authored by labath on Jul 12 2016, 8:09 AM.

Details

Summary

This adds the knowledge of the DW_CFA_GNU_args_size instruction to the eh_frame parsing code.
Right now it is ignored as I am unsure how is it supposed to be handled, but now we are at least
able to parse the rest of the FDE containing this instruction.

I also add a fix for a bug which was exposed by this instruction. Namely, a mismatched sequence
of remember/restore instructions in the input could cause us to pop an empty stack and crash. Now
we just log the error and ignore the offending instruction.

Diff Detail

Repository
rL LLVM

Event Timeline

labath updated this revision to Diff 63678.Jul 12 2016, 8:09 AM
labath retitled this revision from to Add "support" for DW_CFA_GNU_args_size to the unwinder.
labath updated this object.
labath added a reviewer: jasonmolenda.
labath added a subscriber: lldb-commits.
jasonmolenda accepted this revision.Jul 12 2016, 11:00 PM
jasonmolenda edited edge metadata.

This is fine - is there a binary using this? I'd love to see the assembly code and a dump of the eh_frame CFI.

I googled around and didn't find much about DW_CFA_GNU_args_size but in the libunwind llvm sources (v. https://llvm.org/svn/llvm-project/libunwind/trunk/src/ ) it takes the uleb value and adjusts the stack pointer by that value?? I don't see why that wouldn't be encoded in the normal "CFA is sp + offset" type rule of eh_frame so it must not be quite that simple. lldb will probably unwind incorrectly if code built frameless (not using a frame pointer register) is encountered.

This revision is now accepted and ready to land.Jul 12 2016, 11:00 PM
This revision was automatically updated to reflect the committed changes.

This is fine - is there a binary using this? I'd love to see the assembly code and a dump of the eh_frame CFI.

I googled around and didn't find much about DW_CFA_GNU_args_size but in the libunwind llvm sources (v. https://llvm.org/svn/llvm-project/libunwind/trunk/src/ ) it takes the uleb value and adjusts the stack pointer by that value?? I don't see why that wouldn't be encoded in the normal "CFA is sp + offset" type rule of eh_frame so it must not be quite that simple. lldb will probably unwind incorrectly if code built frameless (not using a frame pointer register) is encountered.

That's pretty much what I was able to figure out as well. I haven't managed to understand it's purpose either.

GCC 4.9 seems to produce this instruction fairly liberally. However, I was unable to get it to produce this instruction in an esp-based frame (which could mean that we don't need to handle it? I don't know..) In any case, I am attaching a reduced object file demonstrating it's use of this function

, so you should be able to get all the info you requested from it. If you are able to help us with this, it would be very appreciated. Let me know if there is anything else I can do to help you with that.

For reference, the approximate source code of the function which produced that attribute is:

    extern "C" void*
    execute_native_thread_routine(void* __p)
    {
      thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
      thread::__shared_base_type __local;
      __local.swap(__t->_M_this_ptr);

	{
	  __t->_M_run();
	}

      return 0;
    }