discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: eh_personality.c in libobjc2


From: David Chisnall
Subject: Re: eh_personality.c in libobjc2
Date: Wed, 5 Mar 2014 14:13:01 +0000

Hi Mathias,

I had to stop reading your email once it became clear that you had posted code 
snippets to GPLv3 code.

The EH personality function on ARM has not been very well tested, and I 
currently don't have a working ARM box to test it with, so patches and comments 
are very welcome, but please avoid posting GPLv3 code (e.g. the libgcc 
unwinder), because that makes it difficult for me to continue reading.  

From your early description, it sounds like we need to search the LSDA until we 
find a catch in phase 1, even if we find a cleanup first, is that correct?  Do 
we also need to visit the cleanup, or do we assume catches supersede cleanups?

David

On 5 Mar 2014, at 13:52, Mathias Bauer <mathias_bauer@gmx.net> wrote:

> Hi dear list members,
> 
> as already reported here, libobjc2 and the latest exception handling produced 
> by clang 3.5pre builds an ARM don't work together well. In all but trivial 
> cases it ends up in an endless loop.
> 
> I investigated the unwinder code in gcc for both ARM and DWARF EHABI. From 
> what I saw there and from what I see in the personality routine of libobjc2, 
> I see a possible reason why this doesn't go together well.
> 
> OTOH I assume that exception handling on ARM usually works on gcc builds with 
> libobjc2 (does it?), so I'm unsure how to align that with my findings. Maybe 
> myfindings are wrong, so if someone that better than me, please help me 
> understanding that better.
> 
> Here's what I believe is going on:
> 
> The ARM EHABI spec states:
> (http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf)
> 
>> Finally the unwinder calls the PR, passing state
>> _US_VIRTUAL_UNWIND_FRAME, the UCB pointer, and an _Unwind_Context
>> pointer for VRS access.
>> The PR must discover whether this frame contains a propagation
>> barrier to the exception object, by examining the EHT entry, pointed
>> to from the UCB pr_cache. It must also adjust the VRS as necessary by
>> calling functions in the language-independent unwinding library. It
>> returns to _Unwind_RaiseException with one of:
>> - Barrier found (_URC_HANDLER_FOUND)
>> - No barrier (_URC_CONTINUE_UNWIND)
>> - Error (_URC_FAILURE)
> 
> Consequently, this is what the ARM unwinder does (unwind-arm.c in gcc):
> 
>>  /* Unwind until we reach a propagation barrier.  */
>>  do
>>    {
>>      /* Find the entry for this routine.  */
>>      if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
>>      return _URC_FAILURE;
>> 
>>      /* Call the pr to decide what to do.  */
>>      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
>>      (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
>>    }
>>  while (pr_result == _URC_CONTINUE_UNWIND);
> 
> So what happens in the personality routine? (eh_personality.c, function 
> "internal_objc_personality"):
> 
> The first thing that the PR does wrong is that it does not examine the whole 
> frames' data, only the current context. If that is a cleanup, the PR will 
> stop there and return _URC_CONTINUE_UNWIND. But according to the spec it 
> should check the whole frame for a "barrier" (a catch handler) and return 
> _URC_HANDLER_FOUND if it found one.
> 
> Only if the frame does not contain such a handler, the return code 
> _URC_CONTINUE_UNWIND would be correct, but in that case the personality 
> routine had to do something more, as stated in the ARM EHABI spec:
> 
>> _URC_CONTINUE_UNWIND indicates that no applicable propagation barrier
>> was found in the function. Before returning, the PR is required to
>> have done a virtual unwind by updating the VRS to reflect the machine
>> state at the call to the current function.
> 
> But the PR in eh_personality.c does not do that.
> 
> So in case the current context points to a cleanup, neither the unwinder nor 
> the personality routine will change any data. The PR will return 
> _URC_CONTINUE_UNWIND and will be called by the unwinder again and again with 
> the same input data. It's obvious that this will create an endless loop.
> 
> The PR obviously does only what it needs to support the DWARF unwinder:
> (http://mentorembedded.github.io/cxx-abi/abi-eh.html)
> 
>> In the search phase, the framework repeatedly calls the personality
>> routine, with the _UA_SEARCH_PHASE flag as described below, first for
>> the current PC and register state, and then unwinding a frame to a
>> new PC at each step, until the personality routine reports either
>> success (a handler found in the queried frame) or failure (no
>> handler) in all frames.
> 
> So the DWARF unwinder does this (undwind.inc in gcc):
> 
>>  /* Phase 1: Search.  Unwind the stack, calling the personality routine
>>     with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
>>  while (1)
>>    {
>>      _Unwind_FrameState fs;
>> 
>>      /* Set up fs to describe the FDE for the caller of cur_context.  The
>>       first time through the loop, that means __cxa_throw.  */
>>      code = uw_frame_state_for (&cur_context, &fs);
>> 
>>      if (code == _URC_END_OF_STACK)
>>      /* Hit end of stack with no handler found.  */
>>      return _URC_END_OF_STACK;
>> 
>>      if (code != _URC_NO_REASON)
>>      /* Some error encountered.  Usually the unwinder doesn't
>>         diagnose these and merely crashes.  */
>>      return _URC_FATAL_PHASE1_ERROR;
>> 
>>      /* Unwind successful.  Run the personality routine, if any.  */
>>      if (fs.personality)
>>      {
>>        code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
>>                                  exc, &cur_context);
>>        if (code == _URC_HANDLER_FOUND)
>>          break;
>>        else if (code != _URC_CONTINUE_UNWIND)
>>          return _URC_FATAL_PHASE1_ERROR;
>>      }
>> 
>>      /* Update cur_context to describe the same frame as fs.  */
>>      uw_update_context (&cur_context, &fs);
>>    }
> 
> Now the PR does not need to do anything with the context if it points to a 
> cleanup, as the unwinder takes care of updating the context after each call 
> to the personality routine.
> 
> It seems that we have to change the personality routine to support the ARM 
> EHABI spec.
> 
> Comments welcome.
> 
> Regards,
> Mathias
> 
> _______________________________________________
> Discuss-gnustep mailing list
> Discuss-gnustep@gnu.org
> https://lists.gnu.org/mailman/listinfo/discuss-gnustep




-- Sent from my STANTEC-ZEBRA




reply via email to

[Prev in Thread] Current Thread [Next in Thread]