First public contribution.
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "ARM EABI LICENCE.txt"
5 // which accompanies this distribution, and is available
6 // in kernel/eka/compsupp.
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32/compsupp/symaehabi/symbian_support.h
19 #ifndef SYMBIAN_SUPPORT_H
20 #define SYMBIAN_SUPPORT_H
22 #include <e32def_private.h>
25 typedef _Unwind_Control_Block UCB;
27 using std::terminate_handler;
28 using std::unexpected_handler;
30 using std::unexpected;
33 /* --------- Exception control object: --------- */
35 // Type __cxa_exception is the combined C++ housekeeping (LEO) and UCB.
36 // It will be followed by the user exception object, hence must ensure
37 // the latter is aligned on an 8 byte boundary.
39 struct __cxa_exception {
40 const type_info *exceptionType; // RTTI object describing the type of the exception
41 void *(*exceptionDestructor)(void *); // Destructor for the exception object (may be NULL)
42 unexpected_handler unexpectedHandler; // Handler in force after evaluating throw expr
43 terminate_handler terminateHandler; // Handler in force after evaluating throw expr
44 __cxa_exception *nextCaughtException; // Chain of "currently caught" c++ exception objects
45 uint32_t handlerCount; // Count of how many handlers this EO is "caught" in
46 __cxa_exception *nextPropagatingException; // Chain of objects saved over cleanup
47 uint32_t propagationCount; // Count of live propagations (throws) of this EO
48 UCB ucb; // Forces alignment of next item to 8-byte boundary
52 // Exceptions global support
53 typedef void (*handler)(void);
55 struct __cxa_eh_globals {
56 uint32_t uncaughtExceptions; // counter
57 unexpected_handler unexpectedHandler; // per-thread handler
58 terminate_handler terminateHandler; // per-thread handler
59 bool implementation_ever_called_terminate; // true if it ever did
60 handler call_hook; // transient field to tell terminate/unexpected which hook to call
61 __cxa_exception *caughtExceptions; // chain of "caught" exceptions
62 __cxa_exception *propagatingExceptions; // chain of "propagating" (in cleanup) exceptions
63 void *emergency_buffer; // emergency buffer for when rest of heap full
66 // emergency storage reserve primarily for throwing OOM exceptions
67 struct emergency_eco {
69 XLeaveException aUserLeaveException;
72 struct emergency_buffer {
74 struct emergency_eco eco;
78 class TCppRTExceptionsGlobals
81 IMPORT_C TCppRTExceptionsGlobals();
83 __cxa_eh_globals thread_globals;
84 emergency_buffer buffer;
89 // Support for finding ROM resident ExIdx tables
90 #define GET_ROM_EST(u) ((TRomExceptionSearchTable *)((u)->unwinder_cache.reserved4))
91 #define SET_ROM_EST(u,e) ((TRomExceptionSearchTable *)((u)->unwinder_cache.reserved4=(uint32_t)e))
92 #define GET_EXCEPTION_DESCRIPTOR(u) ((TExceptionDescriptor *)((u)->unwinder_cache.reserved5))
93 #define SET_EXCEPTION_DESCRIPTOR(u,e) ((TExceptionDescriptor *)((u)->unwinder_cache.reserved5=(uint32_t)e))
95 // Support for checking which version of EHABI is in play
96 #define EHABI_MASK 0xfffffffc
97 // Checks if image implements V2 of EHABI
98 #define EHABI_V2(u) ((GET_EXCEPTION_DESCRIPTOR(u)->iROSegmentBase) & 1)
99 #define GET_RO_BASE(u) (((u)->iROSegmentBase) & EHABI_MASK)
100 #define ADDRESS_IN_EXCEPTION_DESCRIPTOR_RANGE(addr, aEDp) (((addr) >= GET_RO_BASE(aEDp)) && ((addr) < (aEDp)->iROSegmentLimit))
101 #define GET_EST_FENCEPOST(aESTp) ((aESTp)->iEntries[(aESTp)->iNumEntries])
102 #define ADDRESS_IN_ROM_EST(addr, aESTp) (((addr) >= (aESTp)->iEntries[0]) && ((addr) < GET_EST_FENCEPOST((aESTp))))
105 // Non __EPOC32__ versions defined in unwinder.c
106 #define EIT_base(u) \
107 ((const __EIT_entry *)((GET_EXCEPTION_DESCRIPTOR(u))->iExIdxBase))
108 #define EIT_limit(u) \
109 ((const __EIT_entry *)((GET_EXCEPTION_DESCRIPTOR(u))->iExIdxLimit))
116 typedef unsigned int size_t;
117 IMPORT_C void abort(void);
118 int typenameeq(const char * n1, const char * n2);
120 #define malloc User::Alloc
121 #define free User::Free
125 // uncomment this for diagnostic output in UDEB build
126 //#define _DEBUG_SYMBIAN_EH_SUPPORT
129 #ifdef _DEBUG_SYMBIAN_EH_SUPPORT
130 #define VRS_DIAGNOSTICS
131 #define UNWIND_ACTIVITY_DIAGNOSTICS
132 #define PR_DIAGNOSTICS
133 #define PRINTED_DIAGNOSTICS
134 #define CPP_DIAGNOSTICS
136 #define printf DebugPrintf
137 extern void DebugPrintf(const char *, ...);
139 #ifdef _DEBUG_SYMBIAN_EH_SUPPORT
140 #define SYMBIAN_EH_SUPPORT_PRINTF DebugPrintf
142 #define SYMBIAN_EH_SUPPORT_PRINTF (void)
143 #pragma diag_suppress 174
146 void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp);
147 TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr,_Unwind_Control_Block * ucbp);
149 /* Functions used to convert between segment-relative offsets
150 * and absolute addresses. These are only used in unwinder.c and must be
151 * compilable by a C compiler.
154 static __inline void ValidateExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp)
156 // On entry assume ROM exception search table and exception descriptor for current frame cached in ucbp
158 // see if addr is in current exception descriptor range
159 TExceptionDescriptor * aEDp = GET_EXCEPTION_DESCRIPTOR(ucbp);
160 if (!ADDRESS_IN_EXCEPTION_DESCRIPTOR_RANGE(addr, aEDp)) {
161 aEDp = ReLoadExceptionDescriptor(addr, ucbp);
162 // If there's no valid exception descriptor abort.
165 DebugPrintf("EH ERROR: no exception descriptor for address 0x%08x\n", addr);
166 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_UNWINDER, _UAACT_ENDING, _UAARG_ENDING_UNWINDER_LOOKUPFAILED);
173 static __inline uint32_t addr_to_ER_RO_offset(uint32_t addr, _Unwind_Control_Block * ucbp)
175 TExceptionDescriptor * aEDp = GET_EXCEPTION_DESCRIPTOR(ucbp);
176 // assume ucbp has the correct exception descriptor for this offset
177 return addr - GET_RO_BASE(aEDp);
180 static __inline uint32_t ER_RO_offset_to_addr(uint32_t offset, _Unwind_Control_Block * ucbp)
182 TExceptionDescriptor * aEDp = GET_EXCEPTION_DESCRIPTOR(ucbp);
183 // assume ucbp has the correct exception descriptor for this offset
184 return offset + GET_RO_BASE(aEDp);
187 // This must be the same as the version in unwinder.c. However its structure is
188 // governed by the EHABI and so it shouldn't change anytime soon.
189 typedef struct __EIT_entry {
190 uint32_t fnoffset; /* Place-relative */
194 // The Symbian unwinder uses these specific search functions rather than the generic bsearch
195 // to find entries in the exception index table
196 const __EIT_entry *SearchEITV1(uint32_t return_address_offset, const __EIT_entry *base, unsigned int nelems);
197 __EIT_entry *SearchEITV2(uint32_t return_address, const __EIT_entry *base, unsigned int nelems);
204 #endif // SYMBIAN_SUPPORT_H