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