Update contrib.
3 * Copyright 2002-2003 ARM Limited.
8 1. Subject to the provisions of clause 2, ARM hereby grants to LICENSEE a
9 perpetual, non-exclusive, nontransferable, royalty free, worldwide licence
10 to use this Example Implementation of Exception Handling solely for the
11 purpose of developing, having developed, manufacturing, having
12 manufactured, offering to sell, selling, supplying or otherwise
13 distributing products which comply with the Exception Handling ABI for the
14 ARM Architecture specification. All other rights are reserved to ARM or its
17 2. THIS EXAMPLE IMPLEMENTATION OF EXCEPTION HANDLING IS PROVIDED "AS IS"
18 WITH NO WARRANTIES EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED
19 TO ANY WARRANTY OF SATISFACTORY QUALITY, MERCHANTABILITY, NONINFRINGEMENT
20 OR FITNESS FOR A PARTICULAR PURPOSE.
23 * RCS $Revision: 1.16 $
24 * Checkin $Date: 2003/10/23 13:57:39 $
25 * Revising $Author: agrant $
28 /* Language-independent unwinder implementation */
30 /* This source file is compiled automatically by ARM's make system into
31 * multiple object files. The source regions constituting object file
32 * xxx.o are delimited by ifdef xxx_c / endif directives.
34 * The source regions currently marked are:
42 #include "unwind_env.h"
43 /* Language-independent unwinder declarations: */
46 /* Define UNWIND_ACTIVITY_DIAGNOSTICS for printed information from _Unwind_Activity */
47 /* Define VRS_DIAGNOSTICS for printed diagnostics about VRS operations */
49 #if defined(VRS_DIAGNOSTICS) || defined(UNWIND_ACTIVITY_DIAGNOSTICS)
50 extern int printf(const char *, ...);
56 /* ========================= ========================= */
57 /* ========================= Virtual register set ========================= */
58 /* ========================= ========================= */
60 /* The approach taken by this implementation is to use the real machine
61 * registers to hold all but the values of core (integer)
62 * registers. Consequently the implementation must use only the core
63 * registers except when manipulating the virtual register set. Non-core
64 * registers are saved only on first use, so the single implementation can
65 * cope with execution on processors which lack certain registers. The
66 * registers as they were at the start of the propagation must be preserved
67 * over phase 1 so that the machine state is correct at the start of phase
68 * 2. This requires a copy to be taken (which can be stack allocated). During
69 * a stack unwind (phase 1 or phase 2), the "current" virtual register set is
70 * implemented as core register values held in a data structure, and non-core
71 * register values held in the registers themselves. To ensure that all
72 * original register values are available at the beginning of phase 2, the
73 * core registers are saved in a second structure at the start of phase 1 and
74 * the non-core registers are demand-saved into another part of the data
75 * structure that holds the current core registers during the phase 1 stack
78 /* Extent to which the access routines are implemented:
79 * _Unwind_VRS_Get and _Unwind_VRS_Set implement only access to the core registers.
80 * _Unwind_VRS_Pop implements only popping of core, vfp and fpa registers.
81 * There is no support here for the Intel WMMX registers, but space is nevertheless
82 * reserved in the virtual register set structure to indicate whether demand-saving
83 * of those registers is required (as they are unsupported, it never is). The space
84 * costs nothing as it is required for alignment.
85 * The level of supported functionality is compliant with the requirements of the
89 typedef unsigned char bool;
90 struct core_s { uint32_t r[16]; }; /* core integer regs */
91 struct vfp_s { uint64_t vfp[16+1]; }; /* VFP registers saved in FSTMX format */
92 /* Extra 2 words for the format word + unused */
93 struct fpa_reg { uint32_t word[3]; };
94 struct fpa_s { struct fpa_reg fpa[8]; }; /* FPA registers saved in SFM format */
96 /* Phase 1 virtual register set includes demand-save areas */
97 /* The phase 2 virtual register set must be a prefix of the phase 1 set */
98 typedef struct phase1_virtual_register_set_s {
99 /* demand_save flag == 1 means save the registers in the demand-save area */
100 bool demand_save_vfp;
101 bool demand_save_fpa;
102 bool demand_save_wmmxd;
103 bool demand_save_wmmxc;
104 struct core_s core; /* current core registers */
105 struct vfp_s vfp; /* demand-saved vfp registers */
106 struct fpa_s fpa; /* demand-saved fpa registers */
107 } phase1_virtual_register_set;
109 /* Phase 2 virtual register set has no demand-save areas */
110 /* The phase 2 virtual register set must be a prefix of the phase 1 set */
111 /* The assembly fragments for _Unwind_RaiseException and _Unwind_Resume create
112 * a phase2_virtual_register_set_s by hand so be careful.
114 typedef struct phase2_virtual_register_set_s {
115 /* demand_save flag == 1 means save the registers in the demand-save area */
116 /* Always 0 in phase 2 */
117 bool demand_save_vfp;
118 bool demand_save_fpa;
119 bool demand_save_wmmxd;
120 bool demand_save_wmmxc;
121 struct core_s core; /* current core registers */
122 } phase2_virtual_register_set;
124 /* -- Helper macros for the embedded assembly */
126 #if defined(__TARGET_ARCH_5T) || defined(__TARGET_ARCH_5TXM) || defined(__TARGET_ARCH_5TE) || \
127 defined(__TARGET_ARCH_6) /* || ... */
128 #define ARCH_5T_OR_LATER 1
130 #define ARCH_5T_OR_LATER 0
133 #if defined(__APCS_INTERWORK) && !ARCH_5T_OR_LATER
134 #define OLD_STYLE_INTERWORKING 1
136 #define OLD_STYLE_INTERWORKING 0
139 #if defined(__TARGET_ARCH_4T) || defined(__TARGET_ARCH_4TXM) || ARCH_5T_OR_LATER
148 #define RET_LR mov pc,lr
151 /* ----- Routines: ----- */
153 /* ----- Helper routines, private but external ----- */
154 /* Note '%0' refers to local label '0' */
156 __asm void __ARM_Unwind_VRS_VFPpreserve(void *vfpp)
158 /* Preserve the vfp registers in the passed memory */
160 #define MAYBE_SWITCH_TO_ARM_STATE SWITCH_TO_ARM_STATE
161 #define MAYBE_CODE16 code16
167 assert (%2 - %1) = 0;
173 #define MAYBE_SWITCH_TO_ARM_STATE /* nothing */
174 #define MAYBE_CODE16 /* nothing */
178 MAYBE_SWITCH_TO_ARM_STATE;
179 stc p11,vfp_d0,[r0],{0x21}; /* 0xec800b21 FSTMIAX r0,{d0-d15} */
184 __asm void __ARM_Unwind_VRS_VFPrestore(void *vfpp)
186 /* Restore the vfp registers from the passed memory */
188 MAYBE_SWITCH_TO_ARM_STATE;
189 ldc p11,vfp_d0,[r0],{0x21}; /* 0xec900b21 FLDMIAX r0,{d0-d15} */
194 __asm void __ARM_Unwind_VRS_FPApreserve(void *vfpp)
196 /* Preserve the fpa registers in the passed memory */
199 MAYBE_SWITCH_TO_ARM_STATE;
200 stc p2, fpa_f0, [r0]; /* 0xed800200 SFM f0,4,[r0,#0] */
201 stc p2, fpa_f4, [r0, #48]; /* 0xed80420c SFM f4,4,[r0,#0x30] */
206 __asm void __ARM_Unwind_VRS_FPArestore(void *vfpp)
208 /* Restore the fpa registers from the passed memory */
211 MAYBE_SWITCH_TO_ARM_STATE;
212 ldc p2, fpa_f0, [r0]; /* 0xed900200 LFM f0,4,[r0,#0] */
213 ldc p2, fpa_f4, [r0, #48]; /* 0xed90020c LFM f4,4,[r0,#0x30] */
218 __asm NORETURNDECL void __ARM_Unwind_VRS_corerestore(void *corep)
220 /* By hypothesis this is preserve8 but the load of sp means the
221 * assembler can't infer that.
224 MAYBE_SWITCH_TO_ARM_STATE;
225 #if OLD_STYLE_INTERWORKING
228 ldr r12,[r14, #4*2]; /* pc */
238 /* ----- Development support ----- */
240 #ifdef VRS_DIAGNOSTICS
241 static void debug_print_vrs_vfp(struct vfp_s *vfpp)
243 uint64_t *lp = (uint64_t *)vfpp;
246 for (i = 0; i < 16; i++) {
247 printf("D%-2d 0x%16.16llx ", i, *lp);
256 static void debug_print_vrs_fpa(struct fpa_s *fpap)
258 uint32_t *lp = (uint32_t *)fpap;
261 for (i = 0; i < 8; i++) {
262 printf("F%-2d 0x%8.8x%8.8x%8.8x ", i, *lp, *(lp+1), *(lp+2));
271 static void debug_print_vrs(_Unwind_Context *context)
273 phase1_virtual_register_set *vrsp = (phase1_virtual_register_set *)context;
276 printf("------------------------------------------------------------------------\n");
278 for (i = 0; i < 16; i++) {
279 printf("r%-2d 0x%8.8x ", i, vrsp->core.r[i]);
287 if (vrsp->demand_save_vfp == 1)
288 printf("VFP is not saved\n");
290 debug_print_vrs_vfp(&vrsp->vfp);
292 if (vrsp->demand_save_fpa == 1)
293 printf("FPA is not saved\n");
295 debug_print_vrs_fpa(&vrsp->fpa);
296 printf("------------------------------------------------------------------------\n");
301 /* ----- Public routines ----- */
303 _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context,
304 _Unwind_VRS_RegClass regclass,
306 _Unwind_VRS_DataRepresentation representation,
309 phase1_virtual_register_set *vrsp = (phase1_virtual_register_set *)context;
313 if (representation != _UVRSD_UINT32 || regno > 15)
314 return _UVRSR_FAILED;
315 vrsp->core.r[regno] = *(uint32_t *)valuep;
322 return _UVRSR_NOT_IMPLEMENTED;
326 return _UVRSR_FAILED;
330 _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context,
331 _Unwind_VRS_RegClass regclass,
333 _Unwind_VRS_DataRepresentation representation,
336 phase1_virtual_register_set *vrsp = (phase1_virtual_register_set *)context;
340 if (representation != _UVRSD_UINT32 || regno > 15)
341 return _UVRSR_FAILED;
342 *(uint32_t *)valuep = vrsp->core.r[regno];
349 return _UVRSR_NOT_IMPLEMENTED;
353 return _UVRSR_FAILED;
359 _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context,
360 _Unwind_VRS_RegClass regclass,
361 uint32_t descriminator,
362 _Unwind_VRS_DataRepresentation representation)
364 phase1_virtual_register_set *vrsp = (phase1_virtual_register_set *)context;
368 /* If SP is included in the mask, the loaded value is used in preference to
369 * the writeback value, but only on completion of the loading.
371 uint32_t mask, *vsp, *rp, sp_loaded;
372 if (representation != _UVRSD_UINT32)
373 return _UVRSR_FAILED;
374 vsp = (uint32_t *)vrsp->core.r[R_SP];
375 rp = (uint32_t *)&vrsp->core;
376 mask = descriminator & 0xffff;
377 sp_loaded = mask & (1 << R_SP);
380 #ifdef VRS_DIAGNOSTICS
381 printf("VRS Pop r%d\n", rp - &vrsp->core.r[0]);
389 vrsp->core.r[R_SP] = (uint32_t)vsp;
394 uint32_t start = descriminator >> 16;
395 uint32_t count = descriminator & 0xffff;
396 if (representation != _UVRSD_VFPX || start + count > 16)
397 return _UVRSR_FAILED;
398 if (vrsp->demand_save_vfp == 1) { /* Demand-save over phase 1 */
399 vrsp->demand_save_vfp = 0;
400 __ARM_Unwind_VRS_VFPpreserve(&vrsp->vfp);
402 /* Now recover from the stack into the real machine registers.
403 * Note we assume FSTMX standard format 1.
404 * Do this by saving the current VFP registers to a memory area,
405 * moving the in-memory values over that area, and
406 * restoring from the whole area.
409 struct vfp_s temp_vfp;
411 __ARM_Unwind_VRS_VFPpreserve(&temp_vfp);
412 vsp = (uint64_t *)vrsp->core.r[R_SP];
414 #ifdef VRS_DIAGNOSTICS
415 printf("VRS Pop D%d = 0x%llx\n", start, *vsp);
417 temp_vfp.vfp[start++] = *vsp++;
419 vrsp->core.r[R_SP] = (uint32_t)((uint32_t *)vsp + 1); /* +1 to skip the format word */
420 __ARM_Unwind_VRS_VFPrestore(&temp_vfp);
426 uint32_t start = descriminator >> 16;
427 uint32_t count = descriminator & 0xffff;
428 if (representation != _UVRSD_FPAX || start > 7 || count > 4)
429 return _UVRSR_FAILED;
430 if (vrsp->demand_save_fpa == 1) { /* Demand-save over phase 1 */
431 vrsp->demand_save_fpa = 0;
432 __ARM_Unwind_VRS_FPApreserve(&vrsp->fpa);
434 /* Now recover from the stack into the real machine registers.
435 * Do this by saving the current FPA registers to a memory area,
436 * moving the in-memory values over that area, and
437 * restoring from the whole area.
438 * Unlike VFP, here the range is allowed to wrap round.
441 struct fpa_s temp_fpa;
443 __ARM_Unwind_VRS_FPApreserve(&temp_fpa);
444 vsp = (struct fpa_reg *)vrsp->core.r[R_SP];
446 #ifdef VRS_DIAGNOSTICS
447 printf("VRS Pop F%d = 0x%-8.8x%-8.8x%-8.8x\n", start, *(uint32_t *)vsp,
448 *((uint32_t *)vsp + 1), *((uint32_t *)vsp + 2));
450 temp_fpa.fpa[start++] = *vsp++;
453 vrsp->core.r[R_SP] = (uint32_t)vsp;
454 __ARM_Unwind_VRS_FPArestore(&temp_fpa);
460 return _UVRSR_NOT_IMPLEMENTED;
464 return _UVRSR_FAILED;
469 /* ========================= ========================= */
470 /* ========================= The unwinder ========================= */
471 /* ========================= ========================= */
474 /* This implementation uses the UCB unwinder_cache as follows:
475 * reserved1 is documented in the EABI as requiring initialisation to 0.
476 * It is used to manage nested simultaneous propagation. If the value is 0,
477 * the UCB is participating in no propagations. If the value is 1, the UCB
478 * is participating in one propagation. Otherwise the value is a pointer to
479 * a structure holding saved UCB state from the next propagation out.
480 * The structure used is simply a mallocated UCB.
481 * reserved2 is used to preserve the call-site address over calls to a
482 * personality routine and cleanup.
483 * reserved3 is used to cache the PR address.
484 * reserved4 is not used.
485 * reserved5 is not used.
488 #define NESTED_CONTEXT unwinder_cache.reserved1
489 #define SAVED_CALLSITE_ADDR unwinder_cache.reserved2
490 #define PR_ADDR unwinder_cache.reserved3
492 /* Index table entry: */
494 typedef struct __EIT_entry {
495 uint32_t fnoffset; /* Relative to base of execution region */
500 /* Private defines etc: */
502 static const uint32_t EXIDX_CANTUNWIND = 1;
503 static const uint32_t uint32_highbit = 0x80000000;
505 /* ARM C++ personality routines: */
507 typedef _Unwind_Reason_Code (*personality_routine)(_Unwind_State,
508 _Unwind_Control_Block *,
511 WEAKDECL _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *,
512 _Unwind_Context *context);
513 WEAKDECL _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *,
514 _Unwind_Context *context);
515 WEAKDECL _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *,
516 _Unwind_Context *context);
519 /* Various image symbols: */
521 struct ExceptionTableInfo {
525 /* We define __ARM_ETInfo to allow access to some linker-generated
526 names that are not legal C identifiers. __ARM_ETInfo is extern only
527 because of scope limitations of the embedded assembler */
528 extern const struct ExceptionTableInfo __ARM_ETInfo;
530 ((const __EIT_entry *)(__ARM_ETInfo.EIT_base + (const char *)&__ARM_ETInfo))
532 ((const __EIT_entry *)(__ARM_ETInfo.EIT_limit + (const char *)&__ARM_ETInfo))
535 /* ----- Address manipulation: ----- */
537 /* The following helper function is never called and is present simply
538 * for ease of packaging. The constant word within is used by
539 * ER_RO_offset_to_addr to compute the RO segment base.
540 * The zero word named W is relocated relative to the base B of the
541 * segment which includes it, hence B is recoverable at runtime by
545 extern const uint32_t __ARM_unwind_ROSegBase_SelfOffset;
547 __asm void __ARM_unwind_basehelper(void)
549 export __ARM_unwind_ROSegBase_SelfOffset;
550 R_ARM_ROSEGREL32 EQU 39
551 __ARM_unwind_ROSegBase_SelfOffset;
553 __RELOC R_ARM_ROSEGREL32,__ARM_unwind_ROSegBase_SelfOffset;
556 #define ER_RO_SegBase ((uint32_t)&__ARM_unwind_ROSegBase_SelfOffset - \
557 __ARM_unwind_ROSegBase_SelfOffset)
559 /* And now functions used to convert between segment-relative offsets
560 * and absolute addresses.
563 static __inline uint32_t addr_to_ER_RO_offset(uint32_t addr)
565 return addr - ER_RO_SegBase;
568 static __inline uint32_t ER_RO_offset_to_addr(uint32_t offset)
570 extern const uint32_t __ARM_unwind_ROSegBase_SelfOffset;
571 return offset + ER_RO_SegBase;
575 /* ----- Index table processing ----- */
577 /* find_and_expand_eit_entry is a support function used in both phases to set
578 * ucb.pr_cache and internal cache.
579 * Call with a pointer to the ucb and the return address to look up.
581 * The table is contained in the half-open interval
582 * [EIT_base, EIT_limit) and is an ordered array of __EIT_entrys.
583 * Perform a binary search via C library routine bsearch.
584 * The table contains only function start addresses (encoded as offsets), so
585 * we need to special-case the end table entry in the comparison function,
586 * which we do by assuming the function it describes extends to end of memory.
587 * This causes us problems indirectly in that we would like to fault as
588 * many attempts as possible to look up an invalid return address. There are
589 * several ways an invalid return address can be obtained from a broken
590 * program, such as someone corrupting the stack or broken unwind instructions
591 * recovered the wrong value. It is plausible that many bad return addresses
592 * will be either small integers or will point into the heap or stack, hence
593 * it's desirable to get the length of that final function roughly right.
594 * Here we make no attempt to do it. Code exclusively for use in toolchains
595 * which define a suitable limit symbol could make use of that symbol.
596 * Alternatively (QoI) a smart linker could augment the index table with a
597 * dummy EXIDX_CANTUNWIND entry pointing just past the last real function.
600 static int EIT_comparator(const void *ck, const void *ce)
602 uint32_t return_address_offset = *(const uint32_t *)ck;
603 const __EIT_entry *eitp = (const __EIT_entry *)ce;
604 const __EIT_entry *next_eitp = eitp + 1;
606 if (next_eitp != EIT_limit)
607 next_fn = next_eitp->fnoffset;
609 next_fn = addr_to_ER_RO_offset(0); /* address 0 is 'just past' the end of memory */
610 if (return_address_offset < eitp->fnoffset) return -1;
611 if (return_address_offset >= next_fn) return 1;
616 static _Unwind_Reason_Code find_and_expand_eit_entry(_Unwind_Control_Block *ucbp,
617 uint32_t return_address)
619 /* Search the index table for an entry containing the specified return
620 * address. The EIT contains function offsets relative to the base of the
621 * execute region so adjust the return address accordingly.
624 uint32_t return_address_offset = addr_to_ER_RO_offset(return_address);
625 const __EIT_entry *base = EIT_base;
626 size_t nelems = EIT_limit - EIT_base;
628 const __EIT_entry *eitp =
629 (const __EIT_entry *) bsearch(&return_address_offset, base, nelems,
630 sizeof(__EIT_entry), EIT_comparator);
633 /* The return address we have was not found in the EIT.
634 * This breaks the scan and we have to indicate failure.
636 ucbp->PR_ADDR = NULL;
637 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_UNWINDER, _UAACT_ENDING, _UAARG_ENDING_UNWINDER_LOOKUPFAILED);
641 /* Cache the function offset */
643 ucbp->pr_cache.fnstart = ER_RO_offset_to_addr(eitp->fnoffset);
645 /* Can this frame be unwound at all? */
647 if (eitp->content == EXIDX_CANTUNWIND) {
648 ucbp->PR_ADDR = NULL;
649 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_UNWINDER, _UAACT_ENDING, _UAARG_ENDING_NOUNWIND);
653 /* Obtain the address of the "real" __EHT_Header word */
655 if (eitp->content & uint32_highbit) {
656 /* It is immediate data */
657 ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
658 ucbp->pr_cache.additional = 1;
660 /* The content field is a segment relative offset to an _Unwind_EHT_Entry structure */
661 ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)ER_RO_offset_to_addr(eitp->content);
662 ucbp->pr_cache.additional = 0;
665 /* Discover the personality routine address */
667 if (*(uint32_t *)(ucbp->pr_cache.ehtp) & uint32_highbit) {
668 /* It is immediate data - compute matching pr */
669 uint32_t idx = ((*(uint32_t *)(ucbp->pr_cache.ehtp)) >> 24) & 0xf;
670 if (idx == 0) ucbp->PR_ADDR = (uint32_t)&__aeabi_unwind_cpp_pr0;
671 else if (idx == 1) ucbp->PR_ADDR = (uint32_t)&__aeabi_unwind_cpp_pr1;
672 else if (idx == 2) ucbp->PR_ADDR = (uint32_t)&__aeabi_unwind_cpp_pr2;
674 ucbp->PR_ADDR = NULL;
675 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_UNWINDER, _UAACT_ENDING, _UAARG_ENDING_TABLECORRUPT);
679 /* Execute region offset to PR */
680 ucbp->PR_ADDR = ER_RO_offset_to_addr(*(uint32_t *)(ucbp->pr_cache.ehtp));
688 /* ----- Unwinding: ----- */
691 static NORETURNDECL void unwind_next_frame(_Unwind_Control_Block *ucbp, phase2_virtual_register_set *vrsp);
693 /* Helper fn: If the demand_save flag in a phase1_virtual_register_set was
694 * zeroed, the registers were demand-saved. This function restores from
697 static void restore_non_core_regs(phase1_virtual_register_set *vrsp)
699 if (vrsp->demand_save_vfp == 0)
700 __ARM_Unwind_VRS_VFPrestore(&vrsp->vfp);
701 if (vrsp->demand_save_fpa == 0)
702 __ARM_Unwind_VRS_FPArestore(&vrsp->fpa);
705 /* _Unwind_RaiseException is the external entry point to begin unwinding */
707 __asm _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp)
709 extern __ARM_Unwind_RaiseException;
711 MAYBE_SWITCH_TO_ARM_STATE;
713 /* Create a phase2_virtual_register_set on the stack */
714 /* Save the core registers, carefully writing the original sp value */
715 stmfd sp!,{r13-r15}; /* pushed 3 words => 3 words */
716 stmfd sp!,{r0-r12}; /* pushed 13 words => 16 words */
717 /* Write zeroes for the demand_save bytes so no saving occurs in phase 2 */
719 str r1,[sp,#-4]!; /* pushed 1 word => 17 words */
721 sub sp,sp,#4; /* preserve 8 byte alignment => 18 words */
723 /* Now pass to C (with r0 still valid) to do the real work.
724 * r0 = ucbp, r1 = phase2_virtual_register_set.
725 * If we get control back, pop the stack and return preserving r0.
728 #if OLD_STYLE_INTERWORKING
729 ldr r2,Unwind_RaiseException_Offset;
735 /* on arch 5T and later the linker will fix 'bl' => 'blx' as
737 bl __ARM_Unwind_RaiseException;
742 #if OLD_STYLE_INTERWORKING
743 Unwind_RaiseException_Offset dcd __ARM_Unwind_RaiseException - Offset_Base;
747 /* Alternate symbol names for difficult symbols.
748 * It is possible no functions included in the image require
749 * a handler table. Therefore make only a weak reference to
750 * the handler table base symbol, which may be absent.
752 extern |.ARM.exidx$$Base|;
753 extern |.ARM.exidx$$Limit|;
754 extern |.ARM.extab$$Base| WEAKASMDECL;
756 /* these are offsets for /ropi */
757 __ARM_ETInfo /* layout must match struct ExceptionTableInfo */
758 eit_base dcd |.ARM.exidx$$Base| - __ARM_ETInfo; /* index table base */
759 eit_limit dcd |.ARM.exidx$$Limit| - __ARM_ETInfo; /* index table limit */
763 /* __ARM_Unwind_RaiseException performs phase 1 unwinding */
765 _Unwind_Reason_Code __ARM_Unwind_RaiseException(_Unwind_Control_Block *ucbp,
766 phase2_virtual_register_set *entry_VRSp)
768 phase1_virtual_register_set phase1_VRS;
770 /* Is this a nested simultaneous propagation?
771 * (see comments with _Unwind_Complete)
773 if (ucbp->NESTED_CONTEXT == 0) {
774 /* No - this is only propagation */
775 ucbp->NESTED_CONTEXT = 1;
777 /* Yes - cache the state elsewhere and restore it when the propagation ends */
778 /* This representation wastes space and uses malloc; do better?
779 * On the other hand will it ever be used in practice?
781 _Unwind_Control_Block *saved_ucbp =
782 (_Unwind_Control_Block *)malloc(sizeof(_Unwind_Control_Block));
784 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_UNWINDER, _UAACT_ENDING, _UAARG_ENDING_UNWINDER_BUFFERFAILED);
787 saved_ucbp->unwinder_cache = ucbp->unwinder_cache;
788 saved_ucbp->barrier_cache = ucbp->barrier_cache;
789 saved_ucbp->cleanup_cache = ucbp->cleanup_cache;
790 ucbp->NESTED_CONTEXT = (uint32_t)saved_ucbp;
793 /* entry_VRSp contains the core registers as they were when
794 * _Unwind_RaiseException was called. Copy the call-site address to r15
795 * then copy all the registers to phase1_VRS for the phase 1 stack scan.
798 entry_VRSp->core.r[15] = entry_VRSp->core.r[14];
799 phase1_VRS.core = entry_VRSp->core;
801 /* For phase 1 only ensure non-core registers are saved before use.
802 * If WMMX registers are supported, initialise their flags here and
803 * take appropriate action elsewhere.
806 phase1_VRS.demand_save_vfp = 1;
807 phase1_VRS.demand_save_fpa = 1;
809 /* Now perform a virtual unwind until a propagation barrier is met, or
810 * until something goes wrong. If something does go wrong, we ought (I
811 * suppose) to restore registers we may have destroyed.
816 _Unwind_Reason_Code pr_result;
818 /* Search the index table for the required entry. Cache the index table
819 * pointer, and obtain and cache the addresses of the "real" __EHT_Header
820 * word and the personality routine.
823 if (find_and_expand_eit_entry(ucbp, phase1_VRS.core.r[15]) != _URC_OK) {
824 restore_non_core_regs(&phase1_VRS);
825 /* Debugger bottleneck fn called during lookup */
829 /* Call the pr to decide what to do */
831 pr_result = ((personality_routine)ucbp->PR_ADDR)(_US_VIRTUAL_UNWIND_FRAME,
833 (_Unwind_Context *)&phase1_VRS);
835 if (pr_result == _URC_HANDLER_FOUND) break;
836 if (pr_result == _URC_CONTINUE_UNWIND) continue;
838 /* If we get here some sort of failure has occurred in the
839 * pr and probably the pr returned _URC_FAILURE
841 restore_non_core_regs(&phase1_VRS);
845 /* Propagation barrier located... restore entry register state of non-core regs */
847 restore_non_core_regs(&phase1_VRS);
849 /* Initiate real unwinding */
850 unwind_next_frame(ucbp, entry_VRSp);
851 /* Unreached, but keep compiler quiet: */
856 /* unwind_next_frame performs phase 2 unwinding */
858 static NORETURNDECL void unwind_next_frame(_Unwind_Control_Block *ucbp, phase2_virtual_register_set *vrsp)
862 _Unwind_Reason_Code pr_result;
864 /* Search the index table for the required entry. Cache the index table
865 * pointer, and obtain and cache the addresses of the "real" __EHT_Header
866 * word and the personality routine.
869 if (find_and_expand_eit_entry(ucbp, vrsp->core.r[15]) != _URC_OK)
872 /* Save the call-site address and call the pr to do whatever it
873 * wants to do on this new frame.
876 ucbp->SAVED_CALLSITE_ADDR = vrsp->core.r[15];
877 pr_result = ((personality_routine)ucbp->PR_ADDR)(_US_UNWIND_FRAME_STARTING, ucbp,
878 (_Unwind_Context *)vrsp);
880 if (pr_result == _URC_INSTALL_CONTEXT) {
881 /* Upload the registers */
882 __ARM_Unwind_VRS_corerestore(&vrsp->core);
883 } else if (pr_result == _URC_CONTINUE_UNWIND)
891 /* _Unwind_Resume is the external entry point called after a cleanup
892 * to resume unwinding. It tail-calls a helper function,
893 * __ARM_Unwind_Resume, which never returns.
895 __asm NORETURNDECL void _Unwind_Resume(_Unwind_Control_Block *ucbp)
897 extern __ARM_Unwind_Resume;
899 MAYBE_SWITCH_TO_ARM_STATE;
901 /* Create a phase2_virtual_register_set on the stack */
902 /* Save the core registers, carefully writing the original sp value */
904 stmfd sp!,{r13-r15}; /* pushed 3 words => 3 words */
905 stmfd sp!,{r0-r12}; /* pushed 13 words => 16 words */
906 /* Write zeroes for the demand_save bytes so no saving occurs in phase 2 */
908 str r1,[sp,#-4]!; /* pushed 1 word => 17 words */
910 sub sp,sp,#4; /* preserve 8 byte alignment => 18 words */
912 /* Now pass to C (with r0 still valid) to do the real work.
913 * r0 = ucbp, r1 = phase2_virtual_register_set.
914 * This call never returns.
917 #ifdef __APCS_INTERWORK
918 ldr r2,Unwind_Resume_Offset;
921 Unwind_Resume_Offset dcd __ARM_Unwind_Resume - .;
923 b __ARM_Unwind_Resume;
929 /* Helper function for _Unwind_Resume */
931 NORETURNDECL void __ARM_Unwind_Resume(_Unwind_Control_Block *ucbp,
932 phase2_virtual_register_set *entry_VRSp)
934 _Unwind_Reason_Code pr_result;
936 /* Recover saved state */
938 entry_VRSp->core.r[15] = ucbp->SAVED_CALLSITE_ADDR;
940 /* Call the cached PR and dispatch */
942 pr_result = ((personality_routine)ucbp->PR_ADDR)(_US_UNWIND_FRAME_RESUME, ucbp,
943 (_Unwind_Context *)entry_VRSp);
945 if (pr_result == _URC_INSTALL_CONTEXT) {
946 /* Upload the registers */
947 __ARM_Unwind_VRS_corerestore(&entry_VRSp->core);
948 } else if (pr_result == _URC_CONTINUE_UNWIND)
949 unwind_next_frame(ucbp, entry_VRSp);
955 /* _Unwind_Complete is called at the end of a propagation.
956 * If we support multiple simultaneous propagations, restore the cached state
957 * of the previous propagation here.
960 void _Unwind_Complete(_Unwind_Control_Block *ucbp)
962 _Unwind_Control_Block *context = (_Unwind_Control_Block *)ucbp->NESTED_CONTEXT;
963 if ((uint32_t)context == 0) abort(); /* should be impossible */
964 if ((uint32_t)context == 1) {
965 /* This was the only ongoing propagation of this object */
966 ucbp->NESTED_CONTEXT--;
969 /* Otherwise we copy the state back from the cache structure pointed to
970 * by ucbp->NESTED_CONTEXT.
972 /* This first one updates ucbp->NESTED_CONTEXT */
973 ucbp->unwinder_cache = context->unwinder_cache;
974 ucbp->barrier_cache = context->barrier_cache;
975 ucbp->cleanup_cache = context->cleanup_cache;
979 #endif /* unwinder_c */
980 #ifdef unwind_activity_c
982 /* Runtime debug "bottleneck function": */
983 /* (not in the current Exceptions EABI document) */
985 void _Unwind_Activity(_Unwind_Control_Block *ucbp, uint32_t reason, uint32_t arg)
987 #ifdef UNWIND_ACTIVITY_DIAGNOSTICS
988 uint32_t who = reason >> 24;
989 uint32_t activity = reason & 0xffffff;
990 printf("_Unwind_Activity: UCB=0x%8.8x Reason=(", (uint32_t)ucbp);
992 case _UASUBSYS_UNWINDER:
994 if (activity >= 0x80)
995 printf("%x) Arg=0x%8.8x\n", activity, arg);
999 if (activity >= 0x80) {
1000 if (activity == _UAACT_CPP_TYPEINFO)
1001 printf("typeinfo) Typeinfo=0x%8.8x\n", arg);
1003 printf("%x) Arg=0x%8.8x\n", activity, arg);
1008 if (activity >= 0x80)
1009 printf("%x) Arg=0x%8.8x\n", activity, arg);
1012 if (activity < 0x80) {
1014 case _UAACT_STARTING:
1015 printf("starting) Typeinfo=0x%8.8x\n", arg);
1018 printf("ending) Cause=%d\n", arg);
1020 case _UAACT_BARRIERFOUND:
1021 printf("barrierfound) Pad=0x%8.8x\n", arg);
1023 case _UAACT_PADENTRY:
1024 printf("padentry) Pad=0x%8.8x\n", arg);
1027 printf("%x) Arg=0x%8.8x\n", activity, arg);
1034 #endif /* unwind_activity_c */