kernel/eka/compsupp/symaehabi/symbian_support.h
changeset 9 96e5fb8b040d
child 10 36bfc973b146
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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