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