1*e4b17023SJohn Marino/* Common unwinding code for ARM EABI and C6X. 2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2009, 2011 Free Software Foundation, Inc. 3*e4b17023SJohn Marino Contributed by Paul Brook 4*e4b17023SJohn Marino 5*e4b17023SJohn Marino This file is free software; you can redistribute it and/or modify it 6*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the 7*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any 8*e4b17023SJohn Marino later version. 9*e4b17023SJohn Marino 10*e4b17023SJohn Marino This file is distributed in the hope that it will be useful, but 11*e4b17023SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of 12*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13*e4b17023SJohn Marino General Public License for more details. 14*e4b17023SJohn Marino 15*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional 16*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version 17*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation. 18*e4b17023SJohn Marino 19*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and 20*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program; 21*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 23*e4b17023SJohn Marino 24*e4b17023SJohn Marino#include "tconfig.h" 25*e4b17023SJohn Marino#include "tsystem.h" 26*e4b17023SJohn Marino#include "unwind.h" 27*e4b17023SJohn Marino 28*e4b17023SJohn Marino/* Used for SystemTap unwinder probe. */ 29*e4b17023SJohn Marino#ifdef HAVE_SYS_SDT_H 30*e4b17023SJohn Marino#include <sys/sdt.h> 31*e4b17023SJohn Marino#endif 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino/* We add a prototype for abort here to avoid creating a dependency on 34*e4b17023SJohn Marino target headers. */ 35*e4b17023SJohn Marinoextern void abort (void); 36*e4b17023SJohn Marino 37*e4b17023SJohn Marino/* Definitions for C++ runtime support routines. We make these weak 38*e4b17023SJohn Marino declarations to avoid pulling in libsupc++ unnecessarily. */ 39*e4b17023SJohn Marinotypedef unsigned char bool; 40*e4b17023SJohn Marino 41*e4b17023SJohn Marinotypedef struct _ZSt9type_info type_info; /* This names C++ type_info type */ 42*e4b17023SJohn Marinoenum __cxa_type_match_result 43*e4b17023SJohn Marino { 44*e4b17023SJohn Marino ctm_failed = 0, 45*e4b17023SJohn Marino ctm_succeeded = 1, 46*e4b17023SJohn Marino ctm_succeeded_with_ptr_to_base = 2 47*e4b17023SJohn Marino }; 48*e4b17023SJohn Marino 49*e4b17023SJohn Marinovoid __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp); 50*e4b17023SJohn Marinobool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp); 51*e4b17023SJohn Marinoenum __cxa_type_match_result __attribute__((weak)) __cxa_type_match 52*e4b17023SJohn Marino (_Unwind_Control_Block *ucbp, const type_info *rttip, 53*e4b17023SJohn Marino bool is_reference, void **matched_object); 54*e4b17023SJohn Marino 55*e4b17023SJohn Marino_Unwind_Ptr __attribute__((weak)) 56*e4b17023SJohn Marino__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *); 57*e4b17023SJohn Marino 58*e4b17023SJohn Marino#define EXIDX_CANTUNWIND 1 59*e4b17023SJohn Marino#define uint32_highbit (((_uw) 1) << 31) 60*e4b17023SJohn Marino 61*e4b17023SJohn Marino#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1) 62*e4b17023SJohn Marino#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2) 63*e4b17023SJohn Marino#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3) 64*e4b17023SJohn Marino#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4) 65*e4b17023SJohn Marino 66*e4b17023SJohn Marino/* Unwind descriptors. */ 67*e4b17023SJohn Marino 68*e4b17023SJohn Marinotypedef struct 69*e4b17023SJohn Marino{ 70*e4b17023SJohn Marino _uw16 length; 71*e4b17023SJohn Marino _uw16 offset; 72*e4b17023SJohn Marino} EHT16; 73*e4b17023SJohn Marino 74*e4b17023SJohn Marinotypedef struct 75*e4b17023SJohn Marino{ 76*e4b17023SJohn Marino _uw length; 77*e4b17023SJohn Marino _uw offset; 78*e4b17023SJohn Marino} EHT32; 79*e4b17023SJohn Marino 80*e4b17023SJohn Marino/* An exception index table entry. */ 81*e4b17023SJohn Marino 82*e4b17023SJohn Marinotypedef struct __EIT_entry 83*e4b17023SJohn Marino{ 84*e4b17023SJohn Marino _uw fnoffset; 85*e4b17023SJohn Marino _uw content; 86*e4b17023SJohn Marino} __EIT_entry; 87*e4b17023SJohn Marino 88*e4b17023SJohn Marino/* Assembly helper functions. */ 89*e4b17023SJohn Marino 90*e4b17023SJohn Marino/* Restore core register state. Never returns. */ 91*e4b17023SJohn Marinovoid __attribute__((noreturn)) restore_core_regs (struct core_regs *); 92*e4b17023SJohn Marino 93*e4b17023SJohn Marino 94*e4b17023SJohn Marino/* Restore coprocessor state after phase1 unwinding. */ 95*e4b17023SJohn Marinostatic void restore_non_core_regs (phase1_vrs * vrs); 96*e4b17023SJohn Marino 97*e4b17023SJohn Marino/* A better way to do this would probably be to compare the absolute address 98*e4b17023SJohn Marino with a segment relative relocation of the same symbol. */ 99*e4b17023SJohn Marino 100*e4b17023SJohn Marinoextern int __text_start; 101*e4b17023SJohn Marinoextern int __data_start; 102*e4b17023SJohn Marino 103*e4b17023SJohn Marino/* The exception index table location. */ 104*e4b17023SJohn Marinoextern __EIT_entry __exidx_start; 105*e4b17023SJohn Marinoextern __EIT_entry __exidx_end; 106*e4b17023SJohn Marino 107*e4b17023SJohn Marino/* Core unwinding functions. */ 108*e4b17023SJohn Marino 109*e4b17023SJohn Marino/* Calculate the address encoded by a 31-bit self-relative offset at address 110*e4b17023SJohn Marino P. */ 111*e4b17023SJohn Marinostatic inline _uw selfrel_offset31 (const _uw *p); 112*e4b17023SJohn Marino 113*e4b17023SJohn Marinostatic _uw __gnu_unwind_get_pr_addr (int idx); 114*e4b17023SJohn Marino 115*e4b17023SJohn Marinostatic void _Unwind_DebugHook (void *, void *) 116*e4b17023SJohn Marino __attribute__ ((__noinline__, __used__, __noclone__)); 117*e4b17023SJohn Marino 118*e4b17023SJohn Marino/* This function is called during unwinding. It is intended as a hook 119*e4b17023SJohn Marino for a debugger to intercept exceptions. CFA is the CFA of the 120*e4b17023SJohn Marino target frame. HANDLER is the PC to which control will be 121*e4b17023SJohn Marino transferred. */ 122*e4b17023SJohn Marino 123*e4b17023SJohn Marinostatic void 124*e4b17023SJohn Marino_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), 125*e4b17023SJohn Marino void *handler __attribute__ ((__unused__))) 126*e4b17023SJohn Marino{ 127*e4b17023SJohn Marino /* We only want to use stap probes starting with v3. Earlier 128*e4b17023SJohn Marino versions added too much startup cost. */ 129*e4b17023SJohn Marino#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3 130*e4b17023SJohn Marino STAP_PROBE2 (libgcc, unwind, cfa, handler); 131*e4b17023SJohn Marino#else 132*e4b17023SJohn Marino asm (""); 133*e4b17023SJohn Marino#endif 134*e4b17023SJohn Marino} 135*e4b17023SJohn Marino 136*e4b17023SJohn Marino/* This is a wrapper to be called when we need to restore core registers. 137*e4b17023SJohn Marino It will call `_Unwind_DebugHook' before restoring the registers, thus 138*e4b17023SJohn Marino making it possible to intercept and debug exceptions. 139*e4b17023SJohn Marino 140*e4b17023SJohn Marino When calling `_Unwind_DebugHook', the first argument (the CFA) is zero 141*e4b17023SJohn Marino because we are not interested in it. However, it must be there (even 142*e4b17023SJohn Marino being zero) because GDB expects to find it when using the probe. */ 143*e4b17023SJohn Marino 144*e4b17023SJohn Marino#define uw_restore_core_regs(TARGET, CORE) \ 145*e4b17023SJohn Marino do \ 146*e4b17023SJohn Marino { \ 147*e4b17023SJohn Marino void *handler = __builtin_frob_return_addr ((void *) VRS_PC (TARGET)); \ 148*e4b17023SJohn Marino _Unwind_DebugHook (0, handler); \ 149*e4b17023SJohn Marino restore_core_regs (CORE); \ 150*e4b17023SJohn Marino } \ 151*e4b17023SJohn Marino while (0) 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino/* Perform a binary search for RETURN_ADDRESS in TABLE. The table contains 154*e4b17023SJohn Marino NREC entries. */ 155*e4b17023SJohn Marino 156*e4b17023SJohn Marinostatic const __EIT_entry * 157*e4b17023SJohn Marinosearch_EIT_table (const __EIT_entry * table, int nrec, _uw return_address) 158*e4b17023SJohn Marino{ 159*e4b17023SJohn Marino _uw next_fn; 160*e4b17023SJohn Marino _uw this_fn; 161*e4b17023SJohn Marino int n, left, right; 162*e4b17023SJohn Marino 163*e4b17023SJohn Marino if (nrec == 0) 164*e4b17023SJohn Marino return (__EIT_entry *) 0; 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino left = 0; 167*e4b17023SJohn Marino right = nrec - 1; 168*e4b17023SJohn Marino 169*e4b17023SJohn Marino while (1) 170*e4b17023SJohn Marino { 171*e4b17023SJohn Marino n = (left + right) / 2; 172*e4b17023SJohn Marino this_fn = selfrel_offset31 (&table[n].fnoffset); 173*e4b17023SJohn Marino if (n != nrec - 1) 174*e4b17023SJohn Marino next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1; 175*e4b17023SJohn Marino else 176*e4b17023SJohn Marino next_fn = (_uw)0 - 1; 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino if (return_address < this_fn) 179*e4b17023SJohn Marino { 180*e4b17023SJohn Marino if (n == left) 181*e4b17023SJohn Marino return (__EIT_entry *) 0; 182*e4b17023SJohn Marino right = n - 1; 183*e4b17023SJohn Marino } 184*e4b17023SJohn Marino else if (return_address <= next_fn) 185*e4b17023SJohn Marino return &table[n]; 186*e4b17023SJohn Marino else 187*e4b17023SJohn Marino left = n + 1; 188*e4b17023SJohn Marino } 189*e4b17023SJohn Marino} 190*e4b17023SJohn Marino 191*e4b17023SJohn Marino/* Find the exception index table eintry for the given address. 192*e4b17023SJohn Marino Fill in the relevant fields of the UCB. 193*e4b17023SJohn Marino Returns _URC_FAILURE if an error occurred, _URC_OK on success. */ 194*e4b17023SJohn Marino 195*e4b17023SJohn Marinostatic _Unwind_Reason_Code 196*e4b17023SJohn Marinoget_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address) 197*e4b17023SJohn Marino{ 198*e4b17023SJohn Marino const __EIT_entry * eitp; 199*e4b17023SJohn Marino int nrec; 200*e4b17023SJohn Marino 201*e4b17023SJohn Marino /* The return address is the address of the instruction following the 202*e4b17023SJohn Marino call instruction (plus one in thumb mode). If this was the last 203*e4b17023SJohn Marino instruction in the function the address will lie in the following 204*e4b17023SJohn Marino function. Subtract 2 from the address so that it points within the call 205*e4b17023SJohn Marino instruction itself. */ 206*e4b17023SJohn Marino return_address -= 2; 207*e4b17023SJohn Marino 208*e4b17023SJohn Marino if (__gnu_Unwind_Find_exidx) 209*e4b17023SJohn Marino { 210*e4b17023SJohn Marino eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address, 211*e4b17023SJohn Marino &nrec); 212*e4b17023SJohn Marino if (!eitp) 213*e4b17023SJohn Marino { 214*e4b17023SJohn Marino UCB_PR_ADDR (ucbp) = 0; 215*e4b17023SJohn Marino return _URC_FAILURE; 216*e4b17023SJohn Marino } 217*e4b17023SJohn Marino } 218*e4b17023SJohn Marino else 219*e4b17023SJohn Marino { 220*e4b17023SJohn Marino eitp = &__exidx_start; 221*e4b17023SJohn Marino nrec = &__exidx_end - &__exidx_start; 222*e4b17023SJohn Marino } 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino eitp = search_EIT_table (eitp, nrec, return_address); 225*e4b17023SJohn Marino 226*e4b17023SJohn Marino if (!eitp) 227*e4b17023SJohn Marino { 228*e4b17023SJohn Marino UCB_PR_ADDR (ucbp) = 0; 229*e4b17023SJohn Marino return _URC_FAILURE; 230*e4b17023SJohn Marino } 231*e4b17023SJohn Marino ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset); 232*e4b17023SJohn Marino 233*e4b17023SJohn Marino /* Can this frame be unwound at all? */ 234*e4b17023SJohn Marino if (eitp->content == EXIDX_CANTUNWIND) 235*e4b17023SJohn Marino { 236*e4b17023SJohn Marino UCB_PR_ADDR (ucbp) = 0; 237*e4b17023SJohn Marino return _URC_END_OF_STACK; 238*e4b17023SJohn Marino } 239*e4b17023SJohn Marino 240*e4b17023SJohn Marino /* Obtain the address of the "real" __EHT_Header word. */ 241*e4b17023SJohn Marino 242*e4b17023SJohn Marino if (eitp->content & uint32_highbit) 243*e4b17023SJohn Marino { 244*e4b17023SJohn Marino /* It is immediate data. */ 245*e4b17023SJohn Marino ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content; 246*e4b17023SJohn Marino ucbp->pr_cache.additional = 1; 247*e4b17023SJohn Marino } 248*e4b17023SJohn Marino else 249*e4b17023SJohn Marino { 250*e4b17023SJohn Marino /* The low 31 bits of the content field are a self-relative 251*e4b17023SJohn Marino offset to an _Unwind_EHT_Entry structure. */ 252*e4b17023SJohn Marino ucbp->pr_cache.ehtp = 253*e4b17023SJohn Marino (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content); 254*e4b17023SJohn Marino ucbp->pr_cache.additional = 0; 255*e4b17023SJohn Marino } 256*e4b17023SJohn Marino 257*e4b17023SJohn Marino /* Discover the personality routine address. */ 258*e4b17023SJohn Marino if (*ucbp->pr_cache.ehtp & (1u << 31)) 259*e4b17023SJohn Marino { 260*e4b17023SJohn Marino /* One of the predefined standard routines. */ 261*e4b17023SJohn Marino _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf; 262*e4b17023SJohn Marino UCB_PR_ADDR (ucbp) = __gnu_unwind_get_pr_addr (idx); 263*e4b17023SJohn Marino if (UCB_PR_ADDR (ucbp) == 0) 264*e4b17023SJohn Marino { 265*e4b17023SJohn Marino /* Failed */ 266*e4b17023SJohn Marino return _URC_FAILURE; 267*e4b17023SJohn Marino } 268*e4b17023SJohn Marino } 269*e4b17023SJohn Marino else 270*e4b17023SJohn Marino { 271*e4b17023SJohn Marino /* Execute region offset to PR */ 272*e4b17023SJohn Marino UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp); 273*e4b17023SJohn Marino } 274*e4b17023SJohn Marino return _URC_OK; 275*e4b17023SJohn Marino} 276*e4b17023SJohn Marino 277*e4b17023SJohn Marino 278*e4b17023SJohn Marino/* Perform phase2 unwinding. VRS is the initial virtual register state. */ 279*e4b17023SJohn Marino 280*e4b17023SJohn Marinostatic void __attribute__((noreturn)) 281*e4b17023SJohn Marinounwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs) 282*e4b17023SJohn Marino{ 283*e4b17023SJohn Marino _Unwind_Reason_Code pr_result; 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino do 286*e4b17023SJohn Marino { 287*e4b17023SJohn Marino /* Find the entry for this routine. */ 288*e4b17023SJohn Marino if (get_eit_entry (ucbp, VRS_PC(vrs)) != _URC_OK) 289*e4b17023SJohn Marino abort (); 290*e4b17023SJohn Marino 291*e4b17023SJohn Marino UCB_SAVED_CALLSITE_ADDR (ucbp) = VRS_PC(vrs); 292*e4b17023SJohn Marino 293*e4b17023SJohn Marino /* Call the pr to decide what to do. */ 294*e4b17023SJohn Marino pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) 295*e4b17023SJohn Marino (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs); 296*e4b17023SJohn Marino } 297*e4b17023SJohn Marino while (pr_result == _URC_CONTINUE_UNWIND); 298*e4b17023SJohn Marino 299*e4b17023SJohn Marino if (pr_result != _URC_INSTALL_CONTEXT) 300*e4b17023SJohn Marino abort(); 301*e4b17023SJohn Marino 302*e4b17023SJohn Marino uw_restore_core_regs (vrs, &vrs->core); 303*e4b17023SJohn Marino} 304*e4b17023SJohn Marino 305*e4b17023SJohn Marino/* Perform phase2 forced unwinding. */ 306*e4b17023SJohn Marino 307*e4b17023SJohn Marinostatic _Unwind_Reason_Code 308*e4b17023SJohn Marinounwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs, 309*e4b17023SJohn Marino int resuming) 310*e4b17023SJohn Marino{ 311*e4b17023SJohn Marino _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp); 312*e4b17023SJohn Marino void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp); 313*e4b17023SJohn Marino _Unwind_Reason_Code pr_result = 0; 314*e4b17023SJohn Marino /* We use phase1_vrs here even though we do not demand save, for the 315*e4b17023SJohn Marino prev_sp field. */ 316*e4b17023SJohn Marino phase1_vrs saved_vrs, next_vrs; 317*e4b17023SJohn Marino 318*e4b17023SJohn Marino /* Save the core registers. */ 319*e4b17023SJohn Marino saved_vrs.core = entry_vrs->core; 320*e4b17023SJohn Marino /* We don't need to demand-save the non-core registers, because we 321*e4b17023SJohn Marino unwind in a single pass. */ 322*e4b17023SJohn Marino saved_vrs.demand_save_flags = 0; 323*e4b17023SJohn Marino 324*e4b17023SJohn Marino /* Unwind until we reach a propagation barrier. */ 325*e4b17023SJohn Marino do 326*e4b17023SJohn Marino { 327*e4b17023SJohn Marino _Unwind_State action; 328*e4b17023SJohn Marino _Unwind_Reason_Code entry_code; 329*e4b17023SJohn Marino _Unwind_Reason_Code stop_code; 330*e4b17023SJohn Marino 331*e4b17023SJohn Marino /* Find the entry for this routine. */ 332*e4b17023SJohn Marino entry_code = get_eit_entry (ucbp, VRS_PC (&saved_vrs)); 333*e4b17023SJohn Marino 334*e4b17023SJohn Marino if (resuming) 335*e4b17023SJohn Marino { 336*e4b17023SJohn Marino action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND; 337*e4b17023SJohn Marino resuming = 0; 338*e4b17023SJohn Marino } 339*e4b17023SJohn Marino else 340*e4b17023SJohn Marino action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND; 341*e4b17023SJohn Marino 342*e4b17023SJohn Marino if (entry_code == _URC_OK) 343*e4b17023SJohn Marino { 344*e4b17023SJohn Marino UCB_SAVED_CALLSITE_ADDR (ucbp) = VRS_PC (&saved_vrs); 345*e4b17023SJohn Marino 346*e4b17023SJohn Marino next_vrs = saved_vrs; 347*e4b17023SJohn Marino 348*e4b17023SJohn Marino /* Call the pr to decide what to do. */ 349*e4b17023SJohn Marino pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) 350*e4b17023SJohn Marino (action, ucbp, (void *) &next_vrs); 351*e4b17023SJohn Marino 352*e4b17023SJohn Marino saved_vrs.prev_sp = VRS_SP (&next_vrs); 353*e4b17023SJohn Marino } 354*e4b17023SJohn Marino else 355*e4b17023SJohn Marino { 356*e4b17023SJohn Marino /* Treat any failure as the end of unwinding, to cope more 357*e4b17023SJohn Marino gracefully with missing EH information. Mixed EH and 358*e4b17023SJohn Marino non-EH within one object will usually result in failure, 359*e4b17023SJohn Marino because the .ARM.exidx tables do not indicate the end 360*e4b17023SJohn Marino of the code to which they apply; but mixed EH and non-EH 361*e4b17023SJohn Marino shared objects should return an unwind failure at the 362*e4b17023SJohn Marino entry of a non-EH shared object. */ 363*e4b17023SJohn Marino action |= _US_END_OF_STACK; 364*e4b17023SJohn Marino 365*e4b17023SJohn Marino saved_vrs.prev_sp = VRS_SP (&saved_vrs); 366*e4b17023SJohn Marino } 367*e4b17023SJohn Marino 368*e4b17023SJohn Marino stop_code = stop_fn (1, action, ucbp->exception_class, ucbp, 369*e4b17023SJohn Marino (void *)&saved_vrs, stop_arg); 370*e4b17023SJohn Marino if (stop_code != _URC_NO_REASON) 371*e4b17023SJohn Marino return _URC_FAILURE; 372*e4b17023SJohn Marino 373*e4b17023SJohn Marino if (entry_code != _URC_OK) 374*e4b17023SJohn Marino return entry_code; 375*e4b17023SJohn Marino 376*e4b17023SJohn Marino saved_vrs = next_vrs; 377*e4b17023SJohn Marino } 378*e4b17023SJohn Marino while (pr_result == _URC_CONTINUE_UNWIND); 379*e4b17023SJohn Marino 380*e4b17023SJohn Marino if (pr_result != _URC_INSTALL_CONTEXT) 381*e4b17023SJohn Marino { 382*e4b17023SJohn Marino /* Some sort of failure has occurred in the pr and probably the 383*e4b17023SJohn Marino pr returned _URC_FAILURE. */ 384*e4b17023SJohn Marino return _URC_FAILURE; 385*e4b17023SJohn Marino } 386*e4b17023SJohn Marino 387*e4b17023SJohn Marino uw_restore_core_regs (&saved_vrs, &saved_vrs.core); 388*e4b17023SJohn Marino} 389*e4b17023SJohn Marino 390*e4b17023SJohn Marino/* This is a very limited implementation of _Unwind_GetCFA. It returns 391*e4b17023SJohn Marino the stack pointer as it is about to be unwound, and is only valid 392*e4b17023SJohn Marino while calling the stop function during forced unwinding. If the 393*e4b17023SJohn Marino current personality routine result is going to run a cleanup, this 394*e4b17023SJohn Marino will not be the CFA; but when the frame is really unwound, it will 395*e4b17023SJohn Marino be. */ 396*e4b17023SJohn Marino 397*e4b17023SJohn Marino_Unwind_Word 398*e4b17023SJohn Marino_Unwind_GetCFA (_Unwind_Context *context) 399*e4b17023SJohn Marino{ 400*e4b17023SJohn Marino return ((phase1_vrs *) context)->prev_sp; 401*e4b17023SJohn Marino} 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino/* Perform phase1 unwinding. UCBP is the exception being thrown, and 404*e4b17023SJohn Marino entry_VRS is the register state on entry to _Unwind_RaiseException. */ 405*e4b17023SJohn Marino 406*e4b17023SJohn Marino_Unwind_Reason_Code 407*e4b17023SJohn Marino__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *); 408*e4b17023SJohn Marino 409*e4b17023SJohn Marino_Unwind_Reason_Code 410*e4b17023SJohn Marino__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp, 411*e4b17023SJohn Marino phase2_vrs * entry_vrs) 412*e4b17023SJohn Marino{ 413*e4b17023SJohn Marino phase1_vrs saved_vrs; 414*e4b17023SJohn Marino _Unwind_Reason_Code pr_result; 415*e4b17023SJohn Marino 416*e4b17023SJohn Marino /* Set the pc to the call site. */ 417*e4b17023SJohn Marino VRS_PC (entry_vrs) = VRS_RETURN(entry_vrs); 418*e4b17023SJohn Marino 419*e4b17023SJohn Marino /* Save the core registers. */ 420*e4b17023SJohn Marino saved_vrs.core = entry_vrs->core; 421*e4b17023SJohn Marino /* Set demand-save flags. */ 422*e4b17023SJohn Marino saved_vrs.demand_save_flags = ~(_uw) 0; 423*e4b17023SJohn Marino 424*e4b17023SJohn Marino /* Unwind until we reach a propagation barrier. */ 425*e4b17023SJohn Marino do 426*e4b17023SJohn Marino { 427*e4b17023SJohn Marino /* Find the entry for this routine. */ 428*e4b17023SJohn Marino if (get_eit_entry (ucbp, VRS_PC (&saved_vrs)) != _URC_OK) 429*e4b17023SJohn Marino return _URC_FAILURE; 430*e4b17023SJohn Marino 431*e4b17023SJohn Marino /* Call the pr to decide what to do. */ 432*e4b17023SJohn Marino pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) 433*e4b17023SJohn Marino (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs); 434*e4b17023SJohn Marino } 435*e4b17023SJohn Marino while (pr_result == _URC_CONTINUE_UNWIND); 436*e4b17023SJohn Marino 437*e4b17023SJohn Marino /* We've unwound as far as we want to go, so restore the original 438*e4b17023SJohn Marino register state. */ 439*e4b17023SJohn Marino restore_non_core_regs (&saved_vrs); 440*e4b17023SJohn Marino if (pr_result != _URC_HANDLER_FOUND) 441*e4b17023SJohn Marino { 442*e4b17023SJohn Marino /* Some sort of failure has occurred in the pr and probably the 443*e4b17023SJohn Marino pr returned _URC_FAILURE. */ 444*e4b17023SJohn Marino return _URC_FAILURE; 445*e4b17023SJohn Marino } 446*e4b17023SJohn Marino 447*e4b17023SJohn Marino unwind_phase2 (ucbp, entry_vrs); 448*e4b17023SJohn Marino} 449*e4b17023SJohn Marino 450*e4b17023SJohn Marino/* Resume unwinding after a cleanup has been run. UCBP is the exception 451*e4b17023SJohn Marino being thrown and ENTRY_VRS is the register state on entry to 452*e4b17023SJohn Marino _Unwind_Resume. */ 453*e4b17023SJohn Marino_Unwind_Reason_Code 454*e4b17023SJohn Marino__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *, 455*e4b17023SJohn Marino _Unwind_Stop_Fn, void *, phase2_vrs *); 456*e4b17023SJohn Marino 457*e4b17023SJohn Marino_Unwind_Reason_Code 458*e4b17023SJohn Marino__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp, 459*e4b17023SJohn Marino _Unwind_Stop_Fn stop_fn, void *stop_arg, 460*e4b17023SJohn Marino phase2_vrs *entry_vrs) 461*e4b17023SJohn Marino{ 462*e4b17023SJohn Marino UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn; 463*e4b17023SJohn Marino UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg; 464*e4b17023SJohn Marino 465*e4b17023SJohn Marino /* Set the pc to the call site. */ 466*e4b17023SJohn Marino VRS_PC (entry_vrs) = VRS_RETURN(entry_vrs); 467*e4b17023SJohn Marino 468*e4b17023SJohn Marino return unwind_phase2_forced (ucbp, entry_vrs, 0); 469*e4b17023SJohn Marino} 470*e4b17023SJohn Marino 471*e4b17023SJohn Marino_Unwind_Reason_Code 472*e4b17023SJohn Marino__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *); 473*e4b17023SJohn Marino 474*e4b17023SJohn Marino_Unwind_Reason_Code 475*e4b17023SJohn Marino__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs) 476*e4b17023SJohn Marino{ 477*e4b17023SJohn Marino _Unwind_Reason_Code pr_result; 478*e4b17023SJohn Marino 479*e4b17023SJohn Marino /* Recover the saved address. */ 480*e4b17023SJohn Marino VRS_PC (entry_vrs) = UCB_SAVED_CALLSITE_ADDR (ucbp); 481*e4b17023SJohn Marino 482*e4b17023SJohn Marino if (UCB_FORCED_STOP_FN (ucbp)) 483*e4b17023SJohn Marino { 484*e4b17023SJohn Marino unwind_phase2_forced (ucbp, entry_vrs, 1); 485*e4b17023SJohn Marino 486*e4b17023SJohn Marino /* We can't return failure at this point. */ 487*e4b17023SJohn Marino abort (); 488*e4b17023SJohn Marino } 489*e4b17023SJohn Marino 490*e4b17023SJohn Marino /* Call the cached PR. */ 491*e4b17023SJohn Marino pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) 492*e4b17023SJohn Marino (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs); 493*e4b17023SJohn Marino 494*e4b17023SJohn Marino switch (pr_result) 495*e4b17023SJohn Marino { 496*e4b17023SJohn Marino case _URC_INSTALL_CONTEXT: 497*e4b17023SJohn Marino /* Upload the registers to enter the landing pad. */ 498*e4b17023SJohn Marino uw_restore_core_regs (entry_vrs, &entry_vrs->core); 499*e4b17023SJohn Marino 500*e4b17023SJohn Marino case _URC_CONTINUE_UNWIND: 501*e4b17023SJohn Marino /* Continue unwinding the next frame. */ 502*e4b17023SJohn Marino unwind_phase2 (ucbp, entry_vrs); 503*e4b17023SJohn Marino 504*e4b17023SJohn Marino default: 505*e4b17023SJohn Marino abort (); 506*e4b17023SJohn Marino } 507*e4b17023SJohn Marino} 508*e4b17023SJohn Marino 509*e4b17023SJohn Marino_Unwind_Reason_Code 510*e4b17023SJohn Marino__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *); 511*e4b17023SJohn Marino 512*e4b17023SJohn Marino_Unwind_Reason_Code 513*e4b17023SJohn Marino__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp, 514*e4b17023SJohn Marino phase2_vrs * entry_vrs) 515*e4b17023SJohn Marino{ 516*e4b17023SJohn Marino if (!UCB_FORCED_STOP_FN (ucbp)) 517*e4b17023SJohn Marino return __gnu_Unwind_RaiseException (ucbp, entry_vrs); 518*e4b17023SJohn Marino 519*e4b17023SJohn Marino /* Set the pc to the call site. */ 520*e4b17023SJohn Marino VRS_PC (entry_vrs) = VRS_RETURN (entry_vrs); 521*e4b17023SJohn Marino /* Continue unwinding the next frame. */ 522*e4b17023SJohn Marino return unwind_phase2_forced (ucbp, entry_vrs, 0); 523*e4b17023SJohn Marino} 524*e4b17023SJohn Marino 525*e4b17023SJohn Marino/* Clean up an exception object when unwinding is complete. */ 526*e4b17023SJohn Marinovoid 527*e4b17023SJohn Marino_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused))) 528*e4b17023SJohn Marino{ 529*e4b17023SJohn Marino} 530*e4b17023SJohn Marino 531*e4b17023SJohn Marino 532*e4b17023SJohn Marino/* Free an exception. */ 533*e4b17023SJohn Marino 534*e4b17023SJohn Marinovoid 535*e4b17023SJohn Marino_Unwind_DeleteException (_Unwind_Exception * exc) 536*e4b17023SJohn Marino{ 537*e4b17023SJohn Marino if (exc->exception_cleanup) 538*e4b17023SJohn Marino (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); 539*e4b17023SJohn Marino} 540*e4b17023SJohn Marino 541*e4b17023SJohn Marino 542*e4b17023SJohn Marino/* Perform stack backtrace through unwind data. */ 543*e4b17023SJohn Marino_Unwind_Reason_Code 544*e4b17023SJohn Marino__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, 545*e4b17023SJohn Marino phase2_vrs * entry_vrs); 546*e4b17023SJohn Marino_Unwind_Reason_Code 547*e4b17023SJohn Marino__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, 548*e4b17023SJohn Marino phase2_vrs * entry_vrs) 549*e4b17023SJohn Marino{ 550*e4b17023SJohn Marino phase1_vrs saved_vrs; 551*e4b17023SJohn Marino _Unwind_Reason_Code code; 552*e4b17023SJohn Marino 553*e4b17023SJohn Marino _Unwind_Control_Block ucb; 554*e4b17023SJohn Marino _Unwind_Control_Block *ucbp = &ucb; 555*e4b17023SJohn Marino 556*e4b17023SJohn Marino /* Set the pc to the call site. */ 557*e4b17023SJohn Marino VRS_PC (entry_vrs) = VRS_RETURN (entry_vrs); 558*e4b17023SJohn Marino 559*e4b17023SJohn Marino /* Save the core registers. */ 560*e4b17023SJohn Marino saved_vrs.core = entry_vrs->core; 561*e4b17023SJohn Marino /* Set demand-save flags. */ 562*e4b17023SJohn Marino saved_vrs.demand_save_flags = ~(_uw) 0; 563*e4b17023SJohn Marino 564*e4b17023SJohn Marino do 565*e4b17023SJohn Marino { 566*e4b17023SJohn Marino /* Find the entry for this routine. */ 567*e4b17023SJohn Marino if (get_eit_entry (ucbp, VRS_PC (&saved_vrs)) != _URC_OK) 568*e4b17023SJohn Marino { 569*e4b17023SJohn Marino code = _URC_FAILURE; 570*e4b17023SJohn Marino break; 571*e4b17023SJohn Marino } 572*e4b17023SJohn Marino 573*e4b17023SJohn Marino /* The dwarf unwinder assumes the context structure holds things 574*e4b17023SJohn Marino like the function and LSDA pointers. The ARM implementation 575*e4b17023SJohn Marino caches these in the exception header (UCB). To avoid 576*e4b17023SJohn Marino rewriting everything we make the virtual IP register point at 577*e4b17023SJohn Marino the UCB. */ 578*e4b17023SJohn Marino _Unwind_SetGR((_Unwind_Context *)&saved_vrs, UNWIND_POINTER_REG, (_Unwind_Ptr) ucbp); 579*e4b17023SJohn Marino 580*e4b17023SJohn Marino /* Call trace function. */ 581*e4b17023SJohn Marino if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument) 582*e4b17023SJohn Marino != _URC_NO_REASON) 583*e4b17023SJohn Marino { 584*e4b17023SJohn Marino code = _URC_FAILURE; 585*e4b17023SJohn Marino break; 586*e4b17023SJohn Marino } 587*e4b17023SJohn Marino 588*e4b17023SJohn Marino /* Call the pr to decide what to do. */ 589*e4b17023SJohn Marino code = ((personality_routine) UCB_PR_ADDR (ucbp)) 590*e4b17023SJohn Marino (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, 591*e4b17023SJohn Marino ucbp, (void *) &saved_vrs); 592*e4b17023SJohn Marino } 593*e4b17023SJohn Marino while (code != _URC_END_OF_STACK 594*e4b17023SJohn Marino && code != _URC_FAILURE); 595*e4b17023SJohn Marino 596*e4b17023SJohn Marino restore_non_core_regs (&saved_vrs); 597*e4b17023SJohn Marino return code; 598*e4b17023SJohn Marino} 599*e4b17023SJohn Marino 600*e4b17023SJohn Marino 601*e4b17023SJohn Marino/* Common implementation for ARM ABI defined personality routines. 602*e4b17023SJohn Marino ID is the index of the personality routine, other arguments are as defined 603*e4b17023SJohn Marino by __aeabi_unwind_cpp_pr{0,1,2}. */ 604*e4b17023SJohn Marino 605*e4b17023SJohn Marinostatic _Unwind_Reason_Code 606*e4b17023SJohn Marino__gnu_unwind_pr_common (_Unwind_State state, 607*e4b17023SJohn Marino _Unwind_Control_Block *ucbp, 608*e4b17023SJohn Marino _Unwind_Context *context, 609*e4b17023SJohn Marino int id) 610*e4b17023SJohn Marino{ 611*e4b17023SJohn Marino __gnu_unwind_state uws; 612*e4b17023SJohn Marino _uw *data; 613*e4b17023SJohn Marino _uw offset; 614*e4b17023SJohn Marino _uw len; 615*e4b17023SJohn Marino _uw rtti_count; 616*e4b17023SJohn Marino int phase2_call_unexpected_after_unwind = 0; 617*e4b17023SJohn Marino int in_range = 0; 618*e4b17023SJohn Marino int forced_unwind = state & _US_FORCE_UNWIND; 619*e4b17023SJohn Marino 620*e4b17023SJohn Marino state &= _US_ACTION_MASK; 621*e4b17023SJohn Marino 622*e4b17023SJohn Marino data = (_uw *) ucbp->pr_cache.ehtp; 623*e4b17023SJohn Marino uws.data = *(data++); 624*e4b17023SJohn Marino uws.next = data; 625*e4b17023SJohn Marino if (id == 0) 626*e4b17023SJohn Marino { 627*e4b17023SJohn Marino uws.data <<= 8; 628*e4b17023SJohn Marino uws.words_left = 0; 629*e4b17023SJohn Marino uws.bytes_left = 3; 630*e4b17023SJohn Marino } 631*e4b17023SJohn Marino else if (id < 3) 632*e4b17023SJohn Marino { 633*e4b17023SJohn Marino uws.words_left = (uws.data >> 16) & 0xff; 634*e4b17023SJohn Marino uws.data <<= 16; 635*e4b17023SJohn Marino uws.bytes_left = 2; 636*e4b17023SJohn Marino data += uws.words_left; 637*e4b17023SJohn Marino } 638*e4b17023SJohn Marino 639*e4b17023SJohn Marino /* Restore the saved pointer. */ 640*e4b17023SJohn Marino if (state == _US_UNWIND_FRAME_RESUME) 641*e4b17023SJohn Marino data = (_uw *) ucbp->cleanup_cache.bitpattern[0]; 642*e4b17023SJohn Marino 643*e4b17023SJohn Marino if ((ucbp->pr_cache.additional & 1) == 0) 644*e4b17023SJohn Marino { 645*e4b17023SJohn Marino /* Process descriptors. */ 646*e4b17023SJohn Marino while (*data) 647*e4b17023SJohn Marino { 648*e4b17023SJohn Marino _uw addr; 649*e4b17023SJohn Marino _uw fnstart; 650*e4b17023SJohn Marino 651*e4b17023SJohn Marino if (id == 2) 652*e4b17023SJohn Marino { 653*e4b17023SJohn Marino len = ((EHT32 *) data)->length; 654*e4b17023SJohn Marino offset = ((EHT32 *) data)->offset; 655*e4b17023SJohn Marino data += 2; 656*e4b17023SJohn Marino } 657*e4b17023SJohn Marino else 658*e4b17023SJohn Marino { 659*e4b17023SJohn Marino len = ((EHT16 *) data)->length; 660*e4b17023SJohn Marino offset = ((EHT16 *) data)->offset; 661*e4b17023SJohn Marino data++; 662*e4b17023SJohn Marino } 663*e4b17023SJohn Marino 664*e4b17023SJohn Marino fnstart = ucbp->pr_cache.fnstart + (offset & ~1); 665*e4b17023SJohn Marino addr = _Unwind_GetGR (context, R_PC); 666*e4b17023SJohn Marino in_range = (fnstart <= addr && addr < fnstart + (len & ~1)); 667*e4b17023SJohn Marino 668*e4b17023SJohn Marino switch (((offset & 1) << 1) | (len & 1)) 669*e4b17023SJohn Marino { 670*e4b17023SJohn Marino case 0: 671*e4b17023SJohn Marino /* Cleanup. */ 672*e4b17023SJohn Marino if (state != _US_VIRTUAL_UNWIND_FRAME 673*e4b17023SJohn Marino && in_range) 674*e4b17023SJohn Marino { 675*e4b17023SJohn Marino /* Cleanup in range, and we are running cleanups. */ 676*e4b17023SJohn Marino _uw lp; 677*e4b17023SJohn Marino 678*e4b17023SJohn Marino /* Landing pad address is 31-bit pc-relative offset. */ 679*e4b17023SJohn Marino lp = selfrel_offset31 (data); 680*e4b17023SJohn Marino data++; 681*e4b17023SJohn Marino /* Save the exception data pointer. */ 682*e4b17023SJohn Marino ucbp->cleanup_cache.bitpattern[0] = (_uw) data; 683*e4b17023SJohn Marino if (!__cxa_begin_cleanup (ucbp)) 684*e4b17023SJohn Marino return _URC_FAILURE; 685*e4b17023SJohn Marino /* Setup the VRS to enter the landing pad. */ 686*e4b17023SJohn Marino _Unwind_SetGR (context, R_PC, lp); 687*e4b17023SJohn Marino return _URC_INSTALL_CONTEXT; 688*e4b17023SJohn Marino } 689*e4b17023SJohn Marino /* Cleanup not in range, or we are in stage 1. */ 690*e4b17023SJohn Marino data++; 691*e4b17023SJohn Marino break; 692*e4b17023SJohn Marino 693*e4b17023SJohn Marino case 1: 694*e4b17023SJohn Marino /* Catch handler. */ 695*e4b17023SJohn Marino if (state == _US_VIRTUAL_UNWIND_FRAME) 696*e4b17023SJohn Marino { 697*e4b17023SJohn Marino if (in_range) 698*e4b17023SJohn Marino { 699*e4b17023SJohn Marino /* Check for a barrier. */ 700*e4b17023SJohn Marino _uw rtti; 701*e4b17023SJohn Marino bool is_reference = (data[0] & uint32_highbit) != 0; 702*e4b17023SJohn Marino void *matched; 703*e4b17023SJohn Marino enum __cxa_type_match_result match_type; 704*e4b17023SJohn Marino 705*e4b17023SJohn Marino /* Check for no-throw areas. */ 706*e4b17023SJohn Marino if (data[1] == (_uw) -2) 707*e4b17023SJohn Marino return _URC_FAILURE; 708*e4b17023SJohn Marino 709*e4b17023SJohn Marino /* The thrown object immediately follows the ECB. */ 710*e4b17023SJohn Marino matched = (void *)(ucbp + 1); 711*e4b17023SJohn Marino if (data[1] != (_uw) -1) 712*e4b17023SJohn Marino { 713*e4b17023SJohn Marino /* Match a catch specification. */ 714*e4b17023SJohn Marino rtti = _Unwind_decode_typeinfo_ptr (0, 715*e4b17023SJohn Marino (_uw) &data[1]); 716*e4b17023SJohn Marino match_type = __cxa_type_match (ucbp, 717*e4b17023SJohn Marino (type_info *) rtti, 718*e4b17023SJohn Marino is_reference, 719*e4b17023SJohn Marino &matched); 720*e4b17023SJohn Marino } 721*e4b17023SJohn Marino else 722*e4b17023SJohn Marino match_type = ctm_succeeded; 723*e4b17023SJohn Marino 724*e4b17023SJohn Marino if (match_type) 725*e4b17023SJohn Marino { 726*e4b17023SJohn Marino ucbp->barrier_cache.sp = 727*e4b17023SJohn Marino _Unwind_GetGR (context, R_SP); 728*e4b17023SJohn Marino // ctm_succeeded_with_ptr_to_base really 729*e4b17023SJohn Marino // means _c_t_m indirected the pointer 730*e4b17023SJohn Marino // object. We have to reconstruct the 731*e4b17023SJohn Marino // additional pointer layer by using a temporary. 732*e4b17023SJohn Marino if (match_type == ctm_succeeded_with_ptr_to_base) 733*e4b17023SJohn Marino { 734*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[2] 735*e4b17023SJohn Marino = (_uw) matched; 736*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[0] 737*e4b17023SJohn Marino = (_uw) &ucbp->barrier_cache.bitpattern[2]; 738*e4b17023SJohn Marino } 739*e4b17023SJohn Marino else 740*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[0] = (_uw) matched; 741*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[1] = (_uw) data; 742*e4b17023SJohn Marino return _URC_HANDLER_FOUND; 743*e4b17023SJohn Marino } 744*e4b17023SJohn Marino } 745*e4b17023SJohn Marino /* Handler out of range, or not matched. */ 746*e4b17023SJohn Marino } 747*e4b17023SJohn Marino else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP) 748*e4b17023SJohn Marino && ucbp->barrier_cache.bitpattern[1] == (_uw) data) 749*e4b17023SJohn Marino { 750*e4b17023SJohn Marino /* Matched a previous propagation barrier. */ 751*e4b17023SJohn Marino _uw lp; 752*e4b17023SJohn Marino 753*e4b17023SJohn Marino /* Setup for entry to the handler. */ 754*e4b17023SJohn Marino lp = selfrel_offset31 (data); 755*e4b17023SJohn Marino _Unwind_SetGR (context, R_PC, lp); 756*e4b17023SJohn Marino _Unwind_SetGR (context, 0, (_uw) ucbp); 757*e4b17023SJohn Marino return _URC_INSTALL_CONTEXT; 758*e4b17023SJohn Marino } 759*e4b17023SJohn Marino /* Catch handler not matched. Advance to the next descriptor. */ 760*e4b17023SJohn Marino data += 2; 761*e4b17023SJohn Marino break; 762*e4b17023SJohn Marino 763*e4b17023SJohn Marino case 2: 764*e4b17023SJohn Marino rtti_count = data[0] & 0x7fffffff; 765*e4b17023SJohn Marino /* Exception specification. */ 766*e4b17023SJohn Marino if (state == _US_VIRTUAL_UNWIND_FRAME) 767*e4b17023SJohn Marino { 768*e4b17023SJohn Marino if (in_range && (!forced_unwind || !rtti_count)) 769*e4b17023SJohn Marino { 770*e4b17023SJohn Marino /* Match against the exception specification. */ 771*e4b17023SJohn Marino _uw i; 772*e4b17023SJohn Marino _uw rtti; 773*e4b17023SJohn Marino void *matched; 774*e4b17023SJohn Marino 775*e4b17023SJohn Marino for (i = 0; i < rtti_count; i++) 776*e4b17023SJohn Marino { 777*e4b17023SJohn Marino matched = (void *)(ucbp + 1); 778*e4b17023SJohn Marino rtti = _Unwind_decode_typeinfo_ptr (0, 779*e4b17023SJohn Marino (_uw) &data[i + 1]); 780*e4b17023SJohn Marino if (__cxa_type_match (ucbp, (type_info *) rtti, 0, 781*e4b17023SJohn Marino &matched)) 782*e4b17023SJohn Marino break; 783*e4b17023SJohn Marino } 784*e4b17023SJohn Marino 785*e4b17023SJohn Marino if (i == rtti_count) 786*e4b17023SJohn Marino { 787*e4b17023SJohn Marino /* Exception does not match the spec. */ 788*e4b17023SJohn Marino ucbp->barrier_cache.sp = 789*e4b17023SJohn Marino _Unwind_GetGR (context, R_SP); 790*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[0] = (_uw) matched; 791*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[1] = (_uw) data; 792*e4b17023SJohn Marino return _URC_HANDLER_FOUND; 793*e4b17023SJohn Marino } 794*e4b17023SJohn Marino } 795*e4b17023SJohn Marino /* Handler out of range, or exception is permitted. */ 796*e4b17023SJohn Marino } 797*e4b17023SJohn Marino else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP) 798*e4b17023SJohn Marino && ucbp->barrier_cache.bitpattern[1] == (_uw) data) 799*e4b17023SJohn Marino { 800*e4b17023SJohn Marino /* Matched a previous propagation barrier. */ 801*e4b17023SJohn Marino _uw lp; 802*e4b17023SJohn Marino /* Record the RTTI list for __cxa_call_unexpected. */ 803*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[1] = rtti_count; 804*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[2] = 0; 805*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[3] = 4; 806*e4b17023SJohn Marino ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1]; 807*e4b17023SJohn Marino 808*e4b17023SJohn Marino if (data[0] & uint32_highbit) 809*e4b17023SJohn Marino { 810*e4b17023SJohn Marino data += rtti_count + 1; 811*e4b17023SJohn Marino /* Setup for entry to the handler. */ 812*e4b17023SJohn Marino lp = selfrel_offset31 (data); 813*e4b17023SJohn Marino data++; 814*e4b17023SJohn Marino _Unwind_SetGR (context, R_PC, lp); 815*e4b17023SJohn Marino _Unwind_SetGR (context, 0, (_uw) ucbp); 816*e4b17023SJohn Marino return _URC_INSTALL_CONTEXT; 817*e4b17023SJohn Marino } 818*e4b17023SJohn Marino else 819*e4b17023SJohn Marino phase2_call_unexpected_after_unwind = 1; 820*e4b17023SJohn Marino } 821*e4b17023SJohn Marino if (data[0] & uint32_highbit) 822*e4b17023SJohn Marino data++; 823*e4b17023SJohn Marino data += rtti_count + 1; 824*e4b17023SJohn Marino break; 825*e4b17023SJohn Marino 826*e4b17023SJohn Marino default: 827*e4b17023SJohn Marino /* Should never happen. */ 828*e4b17023SJohn Marino return _URC_FAILURE; 829*e4b17023SJohn Marino } 830*e4b17023SJohn Marino /* Finished processing this descriptor. */ 831*e4b17023SJohn Marino } 832*e4b17023SJohn Marino } 833*e4b17023SJohn Marino 834*e4b17023SJohn Marino if (id >= 3) 835*e4b17023SJohn Marino { 836*e4b17023SJohn Marino /* 24-bit ecoding */ 837*e4b17023SJohn Marino if (__gnu_unwind_24bit (context, uws.data, id == 4) != _URC_OK) 838*e4b17023SJohn Marino return _URC_FAILURE; 839*e4b17023SJohn Marino } 840*e4b17023SJohn Marino else 841*e4b17023SJohn Marino { 842*e4b17023SJohn Marino if (__gnu_unwind_execute (context, &uws) != _URC_OK) 843*e4b17023SJohn Marino return _URC_FAILURE; 844*e4b17023SJohn Marino } 845*e4b17023SJohn Marino 846*e4b17023SJohn Marino if (phase2_call_unexpected_after_unwind) 847*e4b17023SJohn Marino { 848*e4b17023SJohn Marino /* Enter __cxa_unexpected as if called from the call site. */ 849*e4b17023SJohn Marino _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC)); 850*e4b17023SJohn Marino _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected); 851*e4b17023SJohn Marino return _URC_INSTALL_CONTEXT; 852*e4b17023SJohn Marino } 853*e4b17023SJohn Marino 854*e4b17023SJohn Marino return _URC_CONTINUE_UNWIND; 855*e4b17023SJohn Marino} 856