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