kernel/eka/compsupp/symaehabi/unwind_pr.c
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 /* unwind_pr.c - ARM-defined model personality routines
       
     2  *
       
     3  * Copyright 2002-2005 ARM Limited. All rights reserved.
       
     4  *
       
     5  * Your rights to use this code are set out in the accompanying licence
       
     6  * text file LICENCE.txt (ARM contract number LEC-ELA-00080 v1.0).
       
     7  */
       
     8 
       
     9 /* Portions copyright Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). */
       
    10 
       
    11 /*
       
    12  * RCS $Revision: 92986 $
       
    13  * Checkin $Date: 2005-10-13 15:56:12 +0100 (Thu, 13 Oct 2005) $
       
    14  * Revising $Author: achapman $
       
    15  */
       
    16 
       
    17 #include <cstdlib>
       
    18 /* Environment: */
       
    19 #include "unwind_env.h"
       
    20 /* Language-independent unwinder declarations: */
       
    21 #include "unwinder.h"
       
    22 
       
    23 /* Define PR_DIAGNOSTICS for printed diagnostics from the personality routine */
       
    24 
       
    25 #ifdef __EPOC32__
       
    26 /* Symbian specific support */
       
    27 #include "symbian_support.h"
       
    28 #endif
       
    29 
       
    30 #ifdef PR_DIAGNOSTICS
       
    31 #ifndef __EPOC32__
       
    32 extern int printf(const char *, ...);
       
    33 #endif
       
    34 #endif
       
    35 
       
    36 
       
    37 /* Forward decl: */
       
    38 extern _Unwind_Reason_Code __ARM_unwind_cpp_prcommon(_Unwind_State state,
       
    39                                                      _Unwind_Control_Block *ucbp,
       
    40                                                      _Unwind_Context *context,
       
    41                                                      uint32_t idx);
       
    42 
       
    43 /* Personality routines - external entry points.
       
    44  * pr0: short unwind description, 16 bit EHT offsets.
       
    45  * pr1: long unwind description, 16 bit EHT offsets.
       
    46  * pr2: long unwind description, 32 bit EHT offsets.
       
    47  */
       
    48 
       
    49 #ifdef pr0_c
       
    50 _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(_Unwind_State state,
       
    51                                            _Unwind_Control_Block *ucbp,
       
    52                                            _Unwind_Context *context) {
       
    53   return __ARM_unwind_cpp_prcommon(state, ucbp, context, 0);
       
    54 }
       
    55 #endif
       
    56 
       
    57 #ifdef pr1_c
       
    58 EXPORT_C _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(_Unwind_State state,
       
    59                                                     _Unwind_Control_Block *ucbp,
       
    60                                                     _Unwind_Context *context) {
       
    61   return __ARM_unwind_cpp_prcommon(state, ucbp, context, 1);
       
    62 }
       
    63 #endif
       
    64 
       
    65 #ifdef pr2_c
       
    66 EXPORT_C _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(_Unwind_State state,
       
    67                                                     _Unwind_Control_Block *ucbp,
       
    68                                                     _Unwind_Context *context) {
       
    69   return __ARM_unwind_cpp_prcommon(state, ucbp, context, 2);
       
    70 }
       
    71 #endif
       
    72 
       
    73 /* The rest of the file deals with the common routine */
       
    74 
       
    75 #ifdef prcommon_c
       
    76 
       
    77 /* C++ exceptions ABI required here:
       
    78  * Declare protocol routines called by the personality routine.
       
    79  * These are weak references so that referencing them here is
       
    80  * insufficient to pull them into the image - they will only be
       
    81  * included if application code uses a __cxa routine.
       
    82  */
       
    83 
       
    84 typedef unsigned char bool;
       
    85 static const bool false = 0;
       
    86 static const bool true = !false;
       
    87 
       
    88 typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
       
    89 
       
    90 IMPORT_C WEAKDECL void __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
       
    91 IMPORT_C WEAKDECL bool __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
       
    92 typedef enum {
       
    93     ctm_failed = 0,
       
    94     ctm_succeeded = 1,
       
    95     ctm_succeeded_with_ptr_to_base = 2
       
    96   } __cxa_type_match_result;
       
    97 IMPORT_C WEAKDECL __cxa_type_match_result __cxa_type_match(_Unwind_Control_Block *ucbp,
       
    98                                                            const type_info *rttip,
       
    99                                                            bool is_reference_type,
       
   100                                                            void **matched_object);
       
   101 
       
   102 /* ----- Helper routines, private ----- */
       
   103 
       
   104 /* R_ARM_PREL31 is a place-relative 31-bit signed relocation.  The
       
   105  * routine takes the address of a location that was relocated by
       
   106  * R_ARM_PREL31, and returns an absolute address.
       
   107  */
       
   108 static FORCEINLINE uint32_t __ARM_resolve_prel31(void *p)
       
   109 {
       
   110   return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
       
   111 }
       
   112 
       
   113 /* --------- VRS manipulation: --------- */
       
   114 
       
   115 #define R_SP 13
       
   116 #define R_LR 14
       
   117 #define R_PC 15
       
   118 
       
   119 static FORCEINLINE uint32_t core_get(_Unwind_Context *context, uint32_t regno)
       
   120 {
       
   121   uint32_t val;
       
   122   /* This call is required to never fail if given a valid regno */
       
   123   _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
       
   124   return val;
       
   125 }
       
   126 
       
   127 static FORCEINLINE void core_set(_Unwind_Context *context, uint32_t regno, uint32_t newval)
       
   128 {
       
   129   /* This call is required to never fail if given a valid regno */
       
   130   _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &newval);
       
   131 }
       
   132 
       
   133 static FORCEINLINE uint32_t count_to_mask(uint32_t count) {
       
   134   return (1 << count) - 1;
       
   135 }
       
   136 
       
   137 /* --------- Support for unwind instruction stream: --------- */
       
   138 
       
   139 #define CODE_FINISH (0xb0)
       
   140 
       
   141 typedef struct uwdata {
       
   142   uint32_t unwind_word;                  /* current word of unwind description */
       
   143   uint32_t *unwind_word_pointer;         /* ptr to next word */
       
   144   uint8_t unwind_word_bytes_remaining;   /* count of bytes left in current word */
       
   145   uint8_t unwind_words_remaining;        /* count of words left, at ptr onwards */
       
   146 } uwdata;
       
   147 
       
   148 static INLINE uint8_t next_unwind_byte(uwdata *u) {
       
   149   uint8_t ub;
       
   150   if (u->unwind_word_bytes_remaining == 0) {  /* Load another word */
       
   151     if (u->unwind_words_remaining == 0) return CODE_FINISH; /* nothing left - yield NOP */
       
   152     u->unwind_words_remaining--;
       
   153     u->unwind_word = *(u->unwind_word_pointer++);
       
   154     u->unwind_word_bytes_remaining = 4;
       
   155   }
       
   156   
       
   157   u->unwind_word_bytes_remaining--;
       
   158   ub = (u->unwind_word & 0xff000000) >> 24;
       
   159   u->unwind_word <<= 8;
       
   160   return ub;
       
   161 }
       
   162 
       
   163 
       
   164 /* --------- Personality routines: --------- */
       
   165 
       
   166 /* The C++ Standard is silent on what is supposed to happen if an internal
       
   167  * inconsistency occurs during unwinding. In our design, we return to the
       
   168  * caller with _URC_FAILURE. During phase 1 this causes a return from the
       
   169  * language-independent unwinder to its caller (__cxa_throw or __cxa_rethrow)
       
   170  * which will then call terminate(). If an error occurs during phase 2, the
       
   171  * caller will call abort().
       
   172  */
       
   173 
       
   174 /* Types to assist with reading EHT's */
       
   175 
       
   176 typedef struct {
       
   177   uint16_t length;
       
   178   uint16_t offset;
       
   179 } EHT16;
       
   180 
       
   181 typedef struct {
       
   182   uint32_t length;
       
   183   uint32_t offset;
       
   184 } EHT32;
       
   185 
       
   186 typedef uint32_t landingpad_t;
       
   187 
       
   188 typedef struct {
       
   189   landingpad_t landingpad;
       
   190 } EHT_cleanup_tail;
       
   191 
       
   192 typedef struct {
       
   193   landingpad_t landingpad;
       
   194   uint32_t rtti_ref;
       
   195 } EHT_catch_tail;
       
   196 
       
   197 typedef struct {
       
   198   uint32_t rtti_count;           /* table count (possibly 0) */
       
   199   uint32_t (rtti_refs[1]);       /* variable length table, possibly followed by landing pad */
       
   200 } EHT_fnspec_tail;
       
   201 
       
   202 
       
   203 /* Macros: */
       
   204 
       
   205 /* Barrier cache: */
       
   206 /* Requirement imposed by C++ semantics module - pointer to match object in slot 0: */
       
   207 #define BARRIER_HANDLEROBJECT (0)
       
   208 /* Requirement imposed by C++ semantics module - function exception spec info */
       
   209 #define BARRIER_FNSPECCOUNT  (1)
       
   210 #define BARRIER_FNSPECBASE   (2)
       
   211 #define BARRIER_FNSPECSTRIDE (3)
       
   212 #define BARRIER_FNSPECARRAY  (4)
       
   213 /* Private use for us until catch handler entry complete: */
       
   214 #define BARRIER_TEMPORARYMATCHOBJECT (1)
       
   215 /* Private use for us between phase 1 & 2: */
       
   216 #define BARRIER_EHTP (2)
       
   217 
       
   218 #define SAVE_CATCH_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP,HANDLEROBJECT) \
       
   219   (UCB_PTR)->barrier_cache.sp = (VSP);    \
       
   220   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
       
   221   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)(HANDLEROBJECT);
       
   222 
       
   223 #define SAVE_CATCH_OF_BASEPTR_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP,HANDLEROBJECT) \
       
   224   (UCB_PTR)->barrier_cache.sp = (VSP);    \
       
   225   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
       
   226   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_TEMPORARYMATCHOBJECT] = (uint32_t)(HANDLEROBJECT); \
       
   227   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)&((UCB_PTR)->barrier_cache.bitpattern[BARRIER_TEMPORARYMATCHOBJECT]);
       
   228 
       
   229 #define SAVE_FNSPEC_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP) \
       
   230   (UCB_PTR)->barrier_cache.sp = (VSP);    \
       
   231   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
       
   232   (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)0;
       
   233 
       
   234 #define CHECK_FOR_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP) \
       
   235    ((UCB_PTR)->barrier_cache.sp == (VSP) &&    \
       
   236     (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] == (uint32_t)(EHTP))
       
   237 
       
   238 
       
   239 /* Cleanup cache: We only use one field */
       
   240 #define CLEANUP_EHTP (0)
       
   241 
       
   242 
       
   243 /* Special catch rtti values */
       
   244 #define CATCH_ALL               (0xffffffff)
       
   245 #define CATCH_ALL_AND_TERMINATE (0xfffffffe)
       
   246 /* Landing pad bit for catching a reference type */
       
   247 #define CATCH_REFERENCE         (0x80000000)
       
   248 
       
   249 
       
   250 /* Common personality routine: receives pr index as an argument.
       
   251  *
       
   252  * Note this implementation contains no explicit check against attempting to
       
   253  * unwind off the top of the stack. Instead it relies (in cooperation with
       
   254  * the language-independent unwinder) on there being a propagation barrier
       
   255  * somewhere on the stack, perhaps the caller to main being not
       
   256  * unwindable. An alternative would be to check for the stack pointer
       
   257  * addressing a stack limit symbol.
       
   258  */
       
   259 
       
   260 _Unwind_Reason_Code __ARM_unwind_cpp_prcommon(_Unwind_State state,
       
   261                                               _Unwind_Control_Block *ucbp,
       
   262                                               _Unwind_Context *context,
       
   263                                               uint32_t idx)
       
   264 {
       
   265   _Unwind_EHT_Header *eht_startp;  /* EHT start pointer */
       
   266   uint8_t *ehtp; /* EHT pointer, incremented as required */
       
   267   /* Flag for fnspec violations in which the frame should be unwound before calling unexpected() */
       
   268   bool phase2_call_unexpected_after_unwind;
       
   269   /* Flag for whether we have loaded r15 (pc) with a return address while executing
       
   270    * unwind instructions.
       
   271    * Set this on any write to r15 while executing the unwind instructions.
       
   272    */
       
   273   bool wrote_pc = false;
       
   274   /* Flag for whether we have loaded r14 (lr) with a return address while executing
       
   275    * unwind instructions.
       
   276    * Set this on any write to r14 while executing the unwind instructions.
       
   277    */
       
   278   bool wrote_lr = false;
       
   279   /* Flag for whether we loaded r15 from r14 while executing the unwind instructions */
       
   280   bool wrote_pc_from_lr = false;
       
   281   uwdata ud;
       
   282 
       
   283   /* Are we version 2 of the EHABI ? */
       
   284   bool ehabiv2 = EHABI_V2(ucbp);
       
   285 
       
   286   /* Mark all as well and extract the EHT pointer */
       
   287 
       
   288   eht_startp = ucbp->pr_cache.ehtp;
       
   289 
       
   290 #ifdef PR_DIAGNOSTICS
       
   291   printf("PR entered: state=%d, r15=0x%x, fnstart=0x%x\n",
       
   292          state, core_get(context, R_PC), ucbp->pr_cache.fnstart);
       
   293 #endif
       
   294   
       
   295   /* What are we supposed to do? */
       
   296 
       
   297   if (state != _US_VIRTUAL_UNWIND_FRAME &&
       
   298       state != _US_UNWIND_FRAME_STARTING &&
       
   299       state != _US_UNWIND_FRAME_RESUME) {
       
   300     DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_UNSPECIFIED);
       
   301     return _URC_FAILURE;
       
   302   }
       
   303 
       
   304   phase2_call_unexpected_after_unwind = false;
       
   305 
       
   306   /* Traverse the current EHT, if there is one.
       
   307    * The required behaviours are:
       
   308    * _US_VIRTUAL_UNWIND_FRAME: search for a propagation barrier in this frame.
       
   309    * otherwise look for the propagation barrier we found in phase 1,
       
   310    * performing cleanups on the way. In this case if state will be one of:
       
   311    *   _US_UNWIND_FRAME_STARTING  first time with this frame
       
   312    *   _US_UNWIND_FRAME_RESUME    not first time, we are part-way through the EHT.
       
   313    */
       
   314   
       
   315   if ((ucbp->pr_cache.additional & 1) == 0) { /* EHT inline in index table? */
       
   316     /* No: thus there is a real EHT */
       
   317     
       
   318     if (state == _US_UNWIND_FRAME_RESUME) {
       
   319       /* Recover saved pointer to next EHT entry */
       
   320       ehtp = (uint8_t *)ucbp->cleanup_cache.bitpattern[CLEANUP_EHTP];
       
   321 #ifdef PR_DIAGNOSTICS
       
   322       printf("PR EHT recovered pointer 0x%x\n", (int)ehtp);
       
   323 #endif
       
   324     } else {
       
   325       /* Point at the first EHT entry.
       
   326        * For pr0, the unwind description is entirely within the header word.
       
   327        * For pr1 & pr2, an unwind description extension word count is
       
   328        * held in bits 16-23 of the header word.
       
   329        */
       
   330       uint32_t unwind_extension_word_count = (idx == 0 ? 0 : ((*eht_startp) >> 16) & 0xff);
       
   331       ehtp = (uint8_t *)(eht_startp + 1 + unwind_extension_word_count);
       
   332       
       
   333 #ifdef PR_DIAGNOSTICS
       
   334       printf("PR EHT first entry at 0x%x\n", (int)ehtp);
       
   335 #endif
       
   336     }
       
   337     
       
   338     /* scan ... */
       
   339 
       
   340     while (1) {
       
   341       
       
   342       /* Extract 32 bit length and offset */
       
   343       uint32_t length;
       
   344       uint32_t offset;
       
   345       if (idx == 2) {
       
   346         /* 32 bit offsets */
       
   347         length = ((EHT32 *)ehtp)->length;
       
   348         if (length == 0) break; /* end of table */
       
   349         offset = ((EHT32 *)ehtp)->offset;
       
   350         ehtp += sizeof(EHT32);
       
   351       } else {
       
   352         /* 16 bit offsets */
       
   353         length = ((EHT16 *)ehtp)->length;
       
   354         if (length == 0) break; /* end of table */
       
   355         offset = ((EHT16 *)ehtp)->offset;
       
   356         ehtp += sizeof(EHT16);
       
   357       }
       
   358       
       
   359 #ifdef PR_DIAGNOSTICS
       
   360       printf("PR Got entry at 0x%x code=%d, length=0x%x, offset=0x%x\n",
       
   361              (int)(ehtp-4), ((offset & 1) << 1) | (length & 1),
       
   362              length & ~1, offset & ~1);
       
   363 #endif
       
   364 
       
   365       /* Dispatch on the kind of entry */
       
   366       switch (((offset & 1) << 1) | (length & 1)) {
       
   367       case 0: /* cleanup */
       
   368         if (state == _US_VIRTUAL_UNWIND_FRAME) {
       
   369           /* Not a propagation barrier - skip */
       
   370         } else {
       
   371           /* Phase 2: call the cleanup if the return address is in range */
       
   372           uint32_t padaddress;
       
   373           uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset;
       
   374           uint32_t rtn_addr = core_get(context, R_PC);
       
   375           if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
       
   376             /* It is in range. */
       
   377 	    /* We need both of these to support v1 and v2 */
       
   378             landingpad_t *landingpadp = &((EHT_cleanup_tail *)ehtp)->landingpad;
       
   379             landingpad_t landingpad = *landingpadp;
       
   380             ehtp += sizeof(EHT_cleanup_tail);
       
   381             /* Dump state into the ECO so we resume correctly after the cleanup. */
       
   382             /* We simply save the address of the next EHT entry. */
       
   383             ucbp->cleanup_cache.bitpattern[CLEANUP_EHTP] = (uint32_t)ehtp;
       
   384             if (!__cxa_begin_cleanup(ucbp)) {
       
   385               /* Should be impossible, using ARM's library */
       
   386               DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_UNSPECIFIED);
       
   387               return _URC_FAILURE;
       
   388             }
       
   389             /* Set up the VRS to enter the landing pad. */
       
   390             padaddress = ehabiv2 ?
       
   391 	      __ARM_resolve_prel31(landingpadp) :
       
   392 	      ER_RO_OFFSET_TO_ADDR(landingpad,ucbp);
       
   393             core_set(context, R_PC, padaddress);
       
   394 #ifdef PR_DIAGNOSTICS
       
   395             printf("PR Got cleanup in range, cleanup addr=0x%x\n", core_get(context, R_PC));
       
   396             printf("PR Saving EHT pointer 0x%x\n", (int)ehtp);
       
   397 #endif
       
   398             DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, padaddress);
       
   399             /* Exit requesting upload the VRS to the real machine. */
       
   400            return _URC_INSTALL_CONTEXT;
       
   401           }
       
   402         }
       
   403         /* Phase 1, or phase 2 and not in range */
       
   404         ehtp += sizeof(EHT_cleanup_tail);
       
   405         break;
       
   406       case 1: /* catch */
       
   407         {
       
   408           if (state == _US_VIRTUAL_UNWIND_FRAME) {
       
   409             /* In range, and with a matching type? */
       
   410             uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset;
       
   411             uint32_t rtn_addr = core_get(context, R_PC);
       
   412             void *matched_object;
       
   413             length -= 1;   /* length had low bit set - clear it */
       
   414             if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
       
   415               /* In range */
       
   416               __cxa_type_match_result matched_result;
       
   417               uint32_t *rtti_ref = &((EHT_catch_tail *)ehtp)->rtti_ref;
       
   418               uint32_t rtti_val = *rtti_ref;
       
   419               if (rtti_val == CATCH_ALL_AND_TERMINATE) {
       
   420                 /* Always matches and causes propagation failure in phase 1 */
       
   421 #ifdef PR_DIAGNOSTICS
       
   422                 printf("PR Got CATCH_ALL_AND_TERMINATE in phase 1\n");
       
   423 #endif
       
   424                 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_NOUNWIND);
       
   425                 return _URC_FAILURE;    
       
   426               } else if (rtti_val == CATCH_ALL) {
       
   427                 matched_object = ucbp + 1;
       
   428                 matched_result = ctm_succeeded;
       
   429               } else {
       
   430                 bool is_reference_type = ((uint32_t)(((EHT_catch_tail *)ehtp)->landingpad) & CATCH_REFERENCE)
       
   431                                                            == CATCH_REFERENCE;
       
   432                 rtti_val = ehabiv2 ?
       
   433 		  (uint32_t)__ARM_resolve_target2((void *)rtti_ref) :
       
   434 		  (uint32_t)ER_RO_OFFSET_TO_ADDR(rtti_val, ucbp);
       
   435                 matched_result =__cxa_type_match(ucbp,
       
   436                                                  (type_info *)rtti_val,
       
   437                                                  is_reference_type,
       
   438                                                  &matched_object);
       
   439               }
       
   440               if (matched_result != ctm_failed) {
       
   441                 /* In range and matches.
       
   442                  * Record the propagation barrier details for ease of detection in phase 2.
       
   443                  * We save a pointer to the middle of the handler entry -
       
   444                  * this is fine, so long as we are consistent about it.
       
   445                  */
       
   446 #ifdef PR_DIAGNOSTICS
       
   447                 printf("PR Got barrier in phase 1, result %d\n", (int)matched_result);
       
   448                 printf("PR Matched object address 0x%8.8x\n", matched_object); 
       
   449 #endif
       
   450                 if (matched_result == ctm_succeeded_with_ptr_to_base) {
       
   451                   SAVE_CATCH_OF_BASEPTR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP),
       
   452                                                             ehtp, matched_object);
       
   453 
       
   454                 } else {
       
   455                   SAVE_CATCH_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP),
       
   456                                                  ehtp, matched_object);
       
   457                 }
       
   458                 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_BARRIERFOUND,
       
   459                                     (ehabiv2 ?
       
   460 				      __ARM_resolve_prel31(&((EHT_catch_tail *)ehtp)->landingpad) :
       
   461 				      ER_RO_OFFSET_TO_ADDR(((EHT_catch_tail *)ehtp)->landingpad, ucbp)));
       
   462                 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_CPP_TYPEINFO, rtti_val);
       
   463                 return _URC_HANDLER_FOUND;
       
   464               }
       
   465             }
       
   466             /* Not in range or no type match - fall thru to carry on scanning the table */
       
   467           } else {
       
   468             /* Else this is phase 2: have we encountered the saved barrier? */
       
   469             if (CHECK_FOR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp)) {
       
   470               /* Yes we have.
       
   471                * Set up the VRS to enter the landing pad,
       
   472                * and upload the VRS to the real machine.
       
   473                */
       
   474               landingpad_t *landingpadp = &((EHT_catch_tail *)ehtp)->landingpad;
       
   475               landingpad_t landingpad = *landingpadp;
       
   476               uint32_t padaddress = ehabiv2 ?
       
   477 		__ARM_resolve_prel31(landingpadp) :
       
   478 		ER_RO_OFFSET_TO_ADDR(landingpad, ucbp);
       
   479 #ifdef PR_DIAGNOSTICS
       
   480               printf("PR Got catch barrier in phase 2\n");
       
   481 #endif
       
   482               core_set(context, R_PC, padaddress);
       
   483               core_set(context, 0, (uint32_t)ucbp);
       
   484               DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, padaddress);
       
   485               /* Exit requesting upload the VRS to the real machine. */
       
   486               return _URC_INSTALL_CONTEXT;
       
   487             }
       
   488           }
       
   489           /* Else carry on scanning the table */
       
   490           ehtp += sizeof(EHT_catch_tail);
       
   491           break;
       
   492         }
       
   493       case 2: /* function exception specification (fnspec) */
       
   494         {
       
   495           uint32_t counter_word = ((EHT_fnspec_tail *)ehtp)->rtti_count;
       
   496           uint32_t rtti_count = counter_word & 0x7fffffff;   /* Extract offset count */
       
   497           if (state == _US_VIRTUAL_UNWIND_FRAME) {
       
   498             /* Phase 1 */
       
   499             /* In range? Offset had low bit set - clear it */
       
   500             uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset - 1;
       
   501             uint32_t rtn_addr = core_get(context, R_PC);
       
   502             if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
       
   503               /* See if any type matches */
       
   504               uint32_t *rttipp = &((EHT_fnspec_tail *)ehtp)->rtti_refs[0];
       
   505               uint32_t i;
       
   506               for (i = 0; i < rtti_count; i++) {
       
   507                  void *matched_object;
       
   508 		 type_info * artti;
       
   509 		 if (ehabiv2)
       
   510 		   artti = (type_info *)__ARM_resolve_target2(rttipp);
       
   511 		 else
       
   512 		   artti = (type_info *)ER_RO_OFFSET_TO_ADDR(*rttipp, ucbp);
       
   513                  if (__cxa_type_match(ucbp, artti, false, &matched_object)) {
       
   514 #ifdef PR_DIAGNOSTICS
       
   515                    printf("PR Fnspec matched in phase 1\n");
       
   516 #endif
       
   517                    break;
       
   518                  }
       
   519                  rttipp++;
       
   520               }
       
   521 
       
   522               if (i == rtti_count) { /* NB case rtti_count==0 forces no match [for throw()] */
       
   523                 /* No match - fnspec violation is a propagation barrier */
       
   524 #ifdef PR_DIAGNOSTICS
       
   525                 printf("PR Got fnspec barrier in phase 1\n");
       
   526 #endif
       
   527                 SAVE_FNSPEC_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp); /* save ptr to the count of types */
       
   528                 /* Even if this is a fnspec with a landing pad, we always end up in
       
   529                  * __cxa_call_unexpected so tell the debugger thats where we're going
       
   530                  */
       
   531                 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_BARRIERFOUND, &__cxa_call_unexpected);
       
   532                 return _URC_HANDLER_FOUND;
       
   533               }
       
   534             } /* if (in range...) */
       
   535 
       
   536             /* Fall out of the 'if' to continue table scanning */
       
   537 
       
   538           } else {
       
   539             /* Else this is phase 2: have we encountered the saved barrier? */
       
   540             if (CHECK_FOR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp)) {
       
   541               /* Yes we have. Fill in the UCB barrier_cache for entry to __cxa_call_unexpected */
       
   542               uint32_t *p = (uint32_t *)ehtp; /* ptr to rtti count */
       
   543               ucbp->barrier_cache.bitpattern[BARRIER_FNSPECCOUNT] = rtti_count;
       
   544               ucbp->barrier_cache.bitpattern[BARRIER_FNSPECBASE] = ehabiv2 ? 0 :ER_RO_OFFSET_TO_ADDR(0, ucbp);
       
   545               ucbp->barrier_cache.bitpattern[BARRIER_FNSPECSTRIDE] = 4; /* stride */
       
   546               ucbp->barrier_cache.bitpattern[BARRIER_FNSPECARRAY]  = (uint32_t)(p + 1); /* address of rtti offset list */
       
   547 
       
   548               /* If this is a fnspec with an attached landing pad, we must enter
       
   549                * the pad immediately. Otherwise we need to unwind the frame before
       
   550                * calling __cxa_call_unexpected() so set a flag to make this happen.
       
   551                */
       
   552               if (counter_word == rtti_count)
       
   553                 phase2_call_unexpected_after_unwind = true; /* no pad, enter later */
       
   554               else { /* pad */
       
   555                 landingpad_t *landingpadp;
       
   556                 landingpad_t landingpad;
       
   557                 uint32_t padaddress;
       
   558 #ifdef PR_DIAGNOSTICS
       
   559                 printf("PR Got fnspec barrier in phase 2 (immediate entry)\n");
       
   560 #endif
       
   561                 ehtp += (sizeof(((EHT_fnspec_tail *)ehtp)->rtti_count) +
       
   562                          sizeof(uint32_t) * rtti_count);  /* point at pad offset */
       
   563                 landingpadp = (landingpad_t *)ehtp;
       
   564                 landingpad = *(landingpad_t *)ehtp;
       
   565                 padaddress = ehabiv2 ?
       
   566 		  __ARM_resolve_prel31(landingpadp) :
       
   567 		  ER_RO_OFFSET_TO_ADDR(landingpad, ucbp);
       
   568                 core_set(context, 0, (uint32_t)ucbp);
       
   569                 core_set(context, R_PC, padaddress);
       
   570                 /* Even if this is a fnspec with a landing pad, in phase 1 we said we'd
       
   571                  * end up in __cxa_call_unexpected so show the same thing now
       
   572                  */
       
   573                 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, &__cxa_call_unexpected);
       
   574                 return _URC_INSTALL_CONTEXT;
       
   575               }
       
   576             } /* endif (barrier match) */
       
   577           } /* endif (which phase) */
       
   578           
       
   579           /* Advance to the next item, remembering to skip the landing pad if present */
       
   580           ehtp += (sizeof(((EHT_fnspec_tail *)ehtp)->rtti_count) +
       
   581                    sizeof(uint32_t) * rtti_count +
       
   582                    (counter_word == rtti_count ? 0 : sizeof(landingpad_t)));
       
   583           break;
       
   584         }
       
   585       case 3: /* unallocated */
       
   586         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_TABLECORRUPT);
       
   587         return _URC_FAILURE;
       
   588       } /* switch */
       
   589 
       
   590     } /* while (1) */
       
   591     
       
   592 #ifdef PR_DIAGNOSTICS
       
   593     printf("PR Reached end of EHT\n");
       
   594 #endif
       
   595 
       
   596   } /* if out-of-line EHT */
       
   597 
       
   598 
       
   599   /* Do a virtual unwind of this frame - load the first unwind bytes then loop.
       
   600    * Loop exit is by executing opcode CODE_FINISH.
       
   601    */
       
   602 
       
   603   ud.unwind_word = *(uint32_t *)eht_startp;             /* first word */
       
   604   ud.unwind_word_pointer = (uint32_t *)eht_startp + 1;  /* ptr to extension words, if any */
       
   605   if (idx == 0) {                  /* short description */
       
   606     ud.unwind_words_remaining = 0; /* no further words */
       
   607     ud.unwind_word <<= 8;          /* 3 explicit unwind bytes in this word */
       
   608     ud.unwind_word_bytes_remaining = 3;
       
   609   } else {                         /* long description: extension word count in bits 16-23 */
       
   610     ud.unwind_words_remaining = ((ud.unwind_word) >> 16) & 0xff;
       
   611     ud.unwind_word <<= 16;         /* 2 explicit unwind bytes in this word */
       
   612     ud.unwind_word_bytes_remaining = 2;
       
   613   }
       
   614 
       
   615 #ifdef PR_DIAGNOSTICS
       
   616   /*  debug_print_vrs(context); */
       
   617 #endif
       
   618 
       
   619   while (1) {
       
   620     uint8_t ub = next_unwind_byte(&ud);
       
   621 
       
   622 #ifdef PR_DIAGNOSTICS
       
   623     printf("PR Unwind byte 0x%x\n", ub);
       
   624 #endif
       
   625 
       
   626     /* decode and execute the current byte ... */
       
   627 
       
   628     if (ub == CODE_FINISH) { /* finished unwinding */
       
   629       if (!wrote_pc) {
       
   630         uint32_t lr;
       
   631         if (!wrote_lr) {
       
   632           /* If neither pc nor lr was written, the saved return address was
       
   633            * not restored. This indicates broken unwind instructions.
       
   634            */
       
   635           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_TABLECORRUPT);
       
   636           return _URC_FAILURE;
       
   637         }
       
   638         _Unwind_VRS_Get(context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, &lr);
       
   639         core_set(context, R_PC, lr);
       
   640         wrote_pc_from_lr = true;
       
   641       }
       
   642 #ifdef PR_DIAGNOSTICS
       
   643       {
       
   644         uint32_t nextpc;
       
   645         _Unwind_VRS_Get(context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &nextpc);
       
   646         printf("PR Next PC is  0x%x\n", nextpc);
       
   647       }
       
   648 #endif
       
   649       break;
       
   650     }
       
   651     if (ub <= 0x3f) { /* 00nnnnnn: vsp += (nnnnnn << 2) + 4 */
       
   652       uint32_t increment = ((ub & 0x3f) << 2) + 4;
       
   653       core_set(context, R_SP, core_get(context, R_SP) + increment);
       
   654       continue;
       
   655     }
       
   656     if (ub <= 0x7f) { /* 01xxxxxx: vsp -= (xxxxxx << 2) + 4 */
       
   657       uint32_t decrement = ((ub & 0x3f) << 2) + 4;
       
   658       core_set(context, R_SP, core_get(context, R_SP) - decrement);
       
   659       continue;
       
   660     }
       
   661     if (ub <= 0x8f) { /* 100000000 00000000: refuse, 1000rrrr rrrrrrrr: pop integer regs */
       
   662       uint32_t mask = (ub & 0xf) << 12;
       
   663       ub = next_unwind_byte(&ud);
       
   664       mask |= ub << 4;
       
   665       if (mask == 0) { /* 10000000 00000000 refuse to unwind */
       
   666         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_NOUNWIND);
       
   667         return _URC_FAILURE;
       
   668       }
       
   669       if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
       
   670         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   671         return _URC_FAILURE;
       
   672       }
       
   673       if (mask & (1 << R_PC)) wrote_pc = true;
       
   674       if (mask & (1 << R_LR)) wrote_lr = true;
       
   675       continue;
       
   676     }
       
   677     if (ub <= 0x9f) { /* 1001nnnn: vsp = r[nnnn] if not 13,15 */
       
   678       uint8_t regno = ub & 0xf;
       
   679       if (regno == 13 || regno == R_PC) {  /* reserved */
       
   680         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   681         return _URC_FAILURE;
       
   682       }
       
   683       core_set(context, R_SP, core_get(context, regno));
       
   684       continue;
       
   685     }
       
   686     if (ub <= 0xaf) { /* 1010xnnn: pop r4-r[4+nnn], +r14 if x */
       
   687       uint32_t mask = count_to_mask((ub & 0x7) + 1) << 4;
       
   688       if (ub & 0x8) {
       
   689         mask |= (1 << R_LR);
       
   690         wrote_lr = true;
       
   691       }
       
   692       if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
       
   693         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   694         return _URC_FAILURE;
       
   695       }
       
   696       continue;
       
   697     }
       
   698     if (ub <= 0xb7) {
       
   699       /* if (ub == 0xb0) is CODE_FINISH, handled earlier */
       
   700       if (ub == 0xb1) { /* 10110001 0000iiii pop integer regs, others reserved */
       
   701         uint32_t mask = next_unwind_byte(&ud);
       
   702         if (mask == 0 || mask > 0xf) { /* reserved */
       
   703           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   704           return _URC_FAILURE;
       
   705         }
       
   706         if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
       
   707           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   708           return _URC_FAILURE;
       
   709         }
       
   710         continue;
       
   711       }
       
   712       if (ub == 0xb2) { /* 10110010 uleb128 : vsp += (uleb128 << 2) + 0x204 */
       
   713         uint32_t u = 0;
       
   714         uint32_t n = 0;
       
   715         /* decode */
       
   716         while (1) {
       
   717           ub = next_unwind_byte(&ud);
       
   718           u |= (ub & 0x7f) << n;
       
   719           if ((ub & 0x80) == 0) break;
       
   720           n += 7;
       
   721         }
       
   722         core_set(context, R_SP, core_get(context, R_SP) + (u << 2) + 0x204);
       
   723         continue;
       
   724       }
       
   725       if (ub == 0xb3) { /* 10110011: pop vfp from FSTMFDX */
       
   726         uint32_t discriminator = next_unwind_byte(&ud);
       
   727         discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
       
   728         if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_VFPX) != _UVRSR_OK) {
       
   729           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   730           return _URC_FAILURE;
       
   731         }
       
   732         continue;
       
   733       }
       
   734       { /* 101101nn: was pop fpa, now spare */
       
   735         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   736         return _URC_FAILURE;
       
   737       }
       
   738     } /* if (ub <= 0xb7) ... */
       
   739     if (ub <= 0xbf) { /* 10111nnn: pop vfp from FSTMFDX */
       
   740       uint32_t discriminator = 0x80000 | ((ub & 0x7) + 1);
       
   741       if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_VFPX) != _UVRSR_OK) {
       
   742         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   743         return _URC_FAILURE;
       
   744       }
       
   745       continue;
       
   746     }
       
   747     if (ub <= 0xc7) {
       
   748       if (ub == 0xc7) { /* 11000111: WMMX C regs */
       
   749         uint32_t mask = next_unwind_byte(&ud);
       
   750         if (mask == 0 || mask > 0xf) { /* reserved */
       
   751           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   752           return _URC_FAILURE;
       
   753         }
       
   754         if (_Unwind_VRS_Pop(context, _UVRSC_WMMXC, mask, _UVRSD_UINT32) != _UVRSR_OK) {
       
   755           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   756           return _URC_FAILURE;
       
   757         }
       
   758         continue;
       
   759       } else if (ub == 0xc6) { /* 11000110: WMMX D regs */
       
   760         uint32_t discriminator = next_unwind_byte(&ud);
       
   761         discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
       
   762         if (_Unwind_VRS_Pop(context, _UVRSC_WMMXD, discriminator, _UVRSD_UINT64) != _UVRSR_OK) {
       
   763           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   764           return _URC_FAILURE;
       
   765         }
       
   766         continue;
       
   767       } else {
       
   768         /* 11000nnn (nnn != 6, 7): WMMX D regs */
       
   769         uint32_t discriminator = 0xa0000 | ((ub & 0x7) + 1);
       
   770         if (_Unwind_VRS_Pop(context, _UVRSC_WMMXD, discriminator, _UVRSD_UINT64) != _UVRSR_OK) {
       
   771           DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   772           return _URC_FAILURE;
       
   773         }
       
   774         continue;
       
   775       }
       
   776     } /* if (ub <= 0xc7) ... */
       
   777     if (ub == 0xc8 || /* 11001000 sssscccc: pop VFP hi regs from FSTMFDD */
       
   778         ub == 0xc9) { /* 11001001 sssscccc: pop VFP from FSTMFDD */
       
   779       uint32_t discriminator = next_unwind_byte(&ud);
       
   780       discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
       
   781       if (ub == 0xc8) discriminator += 16 << 16;
       
   782       if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_DOUBLE) != _UVRSR_OK) {
       
   783         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   784         return _URC_FAILURE;
       
   785       }
       
   786       continue;
       
   787     }
       
   788     if (ub <= 0xcf) { /* spare */
       
   789       DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   790       return _URC_FAILURE;
       
   791     }
       
   792     if (ub <= 0xd7) { /* 11010nnn: pop VFP from FSTMFDD */
       
   793       uint32_t discriminator = 0x80000 | ((ub & 0x7) + 1);
       
   794       if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_DOUBLE) != _UVRSR_OK) {
       
   795         DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
       
   796         return _URC_FAILURE;
       
   797       }
       
   798       continue;
       
   799     }
       
   800     /* and in fact everything else is currently reserved or spare */
       
   801     DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
       
   802     return _URC_FAILURE;
       
   803   }
       
   804  
       
   805 #ifdef PR_DIAGNOSTICS
       
   806   /* debug_print_vrs(context); */
       
   807 #endif
       
   808 
       
   809   /* The VRS has now been updated to reflect the virtual unwind.
       
   810    * If we are dealing with an unmatched fnspec, pop intervening frames 
       
   811    * and call unexpected(). Else return to our caller with an
       
   812    * indication to continue unwinding.
       
   813    */
       
   814 
       
   815   if (phase2_call_unexpected_after_unwind) {
       
   816     /* Set up the VRS to enter __cxa_call_unexpected,
       
   817      * and upload the VRS to the real machine.
       
   818      * The barrier_cache was initialised earlier.
       
   819      */
       
   820 #ifdef PR_DIAGNOSTICS
       
   821     printf("PR Got fnspec barrier in phase 2 (unwinding completed)\n");
       
   822 #endif
       
   823     core_set(context, 0, (uint32_t)ucbp);
       
   824     if (!wrote_pc_from_lr) {
       
   825       uint32_t pc;
       
   826       /* Move the return address to lr to simulate a call */
       
   827       _Unwind_VRS_Get(context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &pc);
       
   828       core_set(context, R_LR, pc);
       
   829     }
       
   830     core_set(context, R_PC, (uint32_t)&__cxa_call_unexpected);
       
   831     DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, &__cxa_call_unexpected);
       
   832     return _URC_INSTALL_CONTEXT;
       
   833   }
       
   834   
       
   835   /* Else continue with next frame */
       
   836   return _URC_CONTINUE_UNWIND;
       
   837 }
       
   838 
       
   839 #endif
       
   840 /* end ifdef prcommon_c */