0
|
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.
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
// e32/compsupp/symaehabi/symbian_support.h
|
|
15 |
//
|
|
16 |
//
|
|
17 |
|
|
18 |
|
|
19 |
#ifndef SYMBIAN_SUPPORT_H
|
|
20 |
#define SYMBIAN_SUPPORT_H
|
|
21 |
|
|
22 |
#include <e32def_private.h>
|
|
23 |
|
|
24 |
#ifdef __cplusplus
|
|
25 |
typedef _Unwind_Control_Block UCB;
|
|
26 |
|
|
27 |
using std::terminate_handler;
|
|
28 |
using std::unexpected_handler;
|
|
29 |
using std::terminate;
|
|
30 |
using std::unexpected;
|
|
31 |
using std::type_info;
|
|
32 |
|
|
33 |
/* --------- Exception control object: --------- */
|
|
34 |
|
|
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.
|
|
38 |
|
|
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
|
|
49 |
};
|
|
50 |
|
|
51 |
|
|
52 |
// Exceptions global support
|
|
53 |
typedef void (*handler)(void);
|
|
54 |
|
|
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
|
|
64 |
};
|
|
65 |
|
|
66 |
// emergency storage reserve primarily for throwing OOM exceptions
|
|
67 |
struct emergency_eco {
|
|
68 |
__cxa_exception ep;
|
|
69 |
XLeaveException aUserLeaveException;
|
|
70 |
};
|
|
71 |
|
|
72 |
struct emergency_buffer {
|
|
73 |
bool inuse;
|
|
74 |
struct emergency_eco eco;
|
|
75 |
};
|
|
76 |
|
|
77 |
|
|
78 |
class TCppRTExceptionsGlobals
|
|
79 |
{
|
|
80 |
public:
|
|
81 |
IMPORT_C TCppRTExceptionsGlobals();
|
|
82 |
private:
|
|
83 |
__cxa_eh_globals thread_globals;
|
|
84 |
emergency_buffer buffer;
|
|
85 |
};
|
|
86 |
|
|
87 |
#endif
|
|
88 |
|
|
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))
|
|
94 |
|
|
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))))
|
|
103 |
|
|
104 |
|
|
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))
|
|
110 |
|
|
111 |
|
|
112 |
#ifdef __cplusplus
|
|
113 |
extern "C" {
|
|
114 |
#endif
|
|
115 |
|
|
116 |
typedef unsigned int size_t;
|
|
117 |
IMPORT_C void abort(void);
|
|
118 |
int typenameeq(const char * n1, const char * n2);
|
|
119 |
|
|
120 |
#define malloc User::Alloc
|
|
121 |
#define free User::Free
|
|
122 |
|
|
123 |
|
|
124 |
#ifdef _DEBUG
|
|
125 |
// uncomment this for diagnostic output in UDEB build
|
|
126 |
//#define _DEBUG_SYMBIAN_EH_SUPPORT
|
|
127 |
#endif
|
|
128 |
|
|
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
|
|
135 |
#endif
|
|
136 |
#define printf DebugPrintf
|
|
137 |
extern void DebugPrintf(const char *, ...);
|
|
138 |
|
|
139 |
#ifdef _DEBUG_SYMBIAN_EH_SUPPORT
|
|
140 |
#define SYMBIAN_EH_SUPPORT_PRINTF DebugPrintf
|
|
141 |
#else
|
|
142 |
#define SYMBIAN_EH_SUPPORT_PRINTF (void)
|
|
143 |
#pragma diag_suppress 174
|
|
144 |
#endif
|
|
145 |
|
|
146 |
void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp);
|
|
147 |
TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr,_Unwind_Control_Block * ucbp);
|
|
148 |
|
|
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.
|
|
152 |
*/
|
|
153 |
|
|
154 |
static __inline void ValidateExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp)
|
|
155 |
{
|
|
156 |
// On entry assume ROM exception search table and exception descriptor for current frame cached in ucbp
|
|
157 |
|
|
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.
|
|
163 |
if (!aEDp) {
|
|
164 |
#ifdef _DEBUG
|
|
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);
|
|
167 |
#endif
|
|
168 |
abort();
|
|
169 |
}
|
|
170 |
}
|
|
171 |
}
|
|
172 |
|
|
173 |
static __inline uint32_t addr_to_ER_RO_offset(uint32_t addr, _Unwind_Control_Block * ucbp)
|
|
174 |
{
|
|
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);
|
|
178 |
}
|
|
179 |
|
|
180 |
static __inline uint32_t ER_RO_offset_to_addr(uint32_t offset, _Unwind_Control_Block * ucbp)
|
|
181 |
{
|
|
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);
|
|
185 |
}
|
|
186 |
|
|
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 */
|
|
191 |
uint32_t content;
|
|
192 |
} __EIT_entry;
|
|
193 |
|
|
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);
|
|
198 |
|
|
199 |
|
|
200 |
#ifdef __cplusplus
|
|
201 |
}
|
|
202 |
#endif
|
|
203 |
|
|
204 |
#endif // SYMBIAN_SUPPORT_H
|
|
205 |
|