sl@0: /* unwind_env.h sl@0: * sl@0: * Copyright 2003-2005 ARM Limited. All rights reserved. sl@0: */ sl@0: /* sl@0: Licence sl@0: sl@0: 1. Subject to the provisions of clause 2, ARM hereby grants to LICENSEE a sl@0: perpetual, non-exclusive, nontransferable, royalty free, worldwide licence sl@0: to use this Example Implementation of Exception Handling solely for the sl@0: purpose of developing, having developed, manufacturing, having sl@0: manufactured, offering to sell, selling, supplying or otherwise sl@0: distributing products which comply with the Exception Handling ABI for the sl@0: ARM Architecture specification. All other rights are reserved to ARM or its sl@0: licensors. sl@0: sl@0: 2. THIS EXAMPLE IMPLEMENTATION OF EXCEPTION HANDLING IS PROVIDED "AS IS" sl@0: WITH NO WARRANTIES EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED sl@0: TO ANY WARRANTY OF SATISFACTORY QUALITY, MERCHANTABILITY, NONINFRINGEMENT sl@0: OR FITNESS FOR A PARTICULAR PURPOSE. sl@0: */ sl@0: sl@0: /* Portions copyright Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). */ sl@0: sl@0: /* sl@0: * RCS $Revision: 92949 $ sl@0: * Checkin $Date: 2005-10-12 11:07:03 +0100 (Wed, 12 Oct 2005) $ sl@0: * Revising $Author: achapman $ sl@0: */ sl@0: sl@0: /* Environment definition - abstractions and requirements - to aid sl@0: * portability of the ARM exceptions code. sl@0: */ sl@0: sl@0: #ifndef UNWINDENV_H sl@0: #define UNWINDENV_H sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Source language sl@0: * sl@0: * The compiler is expected to define preprocessor symbols as follows: sl@0: * __cplusplus when compiling in C++ mode. sl@0: * __thumb when compiling to Thumb code. sl@0: * sl@0: * Some use is made of embedded assembly language, introduced by __asm. sl@0: * This is described in ARM's toolchain documentation. Some edits may be sl@0: * required for other compilers. The compiler should define one or more of: sl@0: * __TARGET_ARCH_4T __TARGET_ARCH_4TXM __TARGET_ARCH_5T __TARGET_ARCH_5TXM sl@0: * __TARGET_ARCH_5TE __TARGET_ARCH_6 sl@0: * so the correct assembly wrappers are generated for certain functions. sl@0: * sl@0: * __APCS_INTERWORK should be defined if ARM/Thumb interworking is required. sl@0: * sl@0: * For all the above symbols, if your compiler does not provide appropriate sl@0: * definitions, add them here. sl@0: * sl@0: * Some source language extensions are also used. sl@0: */ sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Library structure sl@0: * sl@0: * ARM's private make system contains an automated facility for compiling sl@0: * source files multiple times to create multiple object files. The source sl@0: * regions intended to constitute object file xxx.o are delimited by sl@0: * #ifdef xxx_c / #endif directives. The exact preprocessor symbols used sl@0: * for this conditionalisation are described in a comment at the start of sl@0: * each file. When porting to a different system, compilations must be sl@0: * performed with these preprocessor symbols appropriately defined sl@0: * (or remove the conditionalisation). sl@0: * sl@0: */ sl@0: #ifdef __EPOC32__ sl@0: sl@0: #define ARM_EXCEPTIONS_ENABLED sl@0: sl@0: // turn on the source regions in unwinder.c sl@0: #define unwinder_c sl@0: #define unwind_activity_c sl@0: sl@0: // turn on the source regions in unwind_pr.c sl@0: #define pr0_c sl@0: #define pr1_c sl@0: #define pr2_c sl@0: #define prcommon_c sl@0: sl@0: // turn on the source regions in cppsemantics.cpp sl@0: #define arm_exceptions_globs_c sl@0: #define arm_exceptions_mem_c sl@0: #define arm_exceptions_uncaught_c sl@0: #define arm_exceptions_terminate_c sl@0: #define arm_exceptions_setterminate_c sl@0: #define arm_exceptions_unexpected_c sl@0: #define arm_exceptions_setunexpected_c sl@0: #define arm_exceptions_support_c sl@0: #define arm_exceptions_callterm_c sl@0: #define arm_exceptions_callunex_c sl@0: #define arm_exceptions_currenttype_c sl@0: #define arm_exceptions_alloc_c sl@0: #define arm_exceptions_free_c sl@0: #define arm_exceptions_throw_c sl@0: #define arm_exceptions_rethrow_c sl@0: #define arm_exceptions_foreign_c sl@0: #define arm_exceptions_cleanup_c sl@0: #define arm_exceptions_getexceptionptr_c sl@0: #define arm_exceptions_catchsemantics_c sl@0: #define arm_exceptions_begincatch_c sl@0: #define arm_exceptions_endcatch_c sl@0: #define arm_exceptions_bad_typeid_c sl@0: #define arm_exceptions_bad_cast_c sl@0: #endif sl@0: sl@0: /* ARM declares (or redeclares) some routines as weak in order that sl@0: * references to them are weak, so that the static linker will not load sl@0: * unwanted code. This is achieved by decorating routine declarations sl@0: * with appropriate language extensions. Note that compilers supporting sl@0: * similar features but via a different syntax may require edits to sl@0: * the library source. sl@0: * sl@0: * Define those decorations here (define as empty if not required): sl@0: */ sl@0: sl@0: #ifndef __EPOC32__ sl@0: #define WEAKDECL __weak /* token in C and C++ */ sl@0: #define WEAKASMDECL [WEAK] /* token in assembler */ sl@0: #else sl@0: // The symbian version needs all of these in the DLL, so don't make them weak sl@0: #define WEAKDECL sl@0: #define WEAKASMDECL sl@0: #endif sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Source language support and language extensions */ sl@0: sl@0: /* It is possible to compile the C++ semantics code using a compiler sl@0: * which does not support C++ exceptions; this was useful to ARM whilst sl@0: * ARM's compiler was being developed, and the facility has not been sl@0: * removed. C++ exceptions syntax is conditionalised by sl@0: * #ifdef ARM_EXCEPTIONS_ENABLED / #endif. Define ARM_EXCEPTIONS_ENABLED sl@0: * by some means here if you want a usable library: sl@0: */ sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" { sl@0: /* For conditionalisation, specifically on ARM_EXCEPTIONS_ENABLED */ sl@0: #include "basics.h" sl@0: } sl@0: #endif sl@0: sl@0: /* The following definitions of syntax decoration may be empty if the sl@0: * facility is not required. Note that compilers supporting similar sl@0: * features but via a different syntax may require edits to the library sl@0: * source. sl@0: * sl@0: * Define the decorations here (define as empty if not required): sl@0: */ sl@0: sl@0: /* If the compiler understands noreturn functions: */ sl@0: #define NORETURNDECL __declspec(noreturn) sl@0: /* Inlining when compiling C */ sl@0: #define INLINE __inline sl@0: /* Stronger encouragement to inline */ sl@0: #define FORCEINLINE __forceinline sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Types */ sl@0: sl@0: /* The implementation requires types uint8_t, uint16_t, uint32_t and sl@0: * uint64_t to be defined as unsigned integers of the appropriate number sl@0: * of bits. sl@0: * sl@0: * Do that here: sl@0: */ sl@0: sl@0: #ifndef __EPOC32__ sl@0: #include <stdint.h> sl@0: #else sl@0: #include <e32def.h> sl@0: typedef TUint8 uint8_t; sl@0: typedef TUint16 uint16_t; sl@0: typedef TInt32 int32_t; sl@0: typedef TUint32 uint32_t; sl@0: typedef Uint64 uint64_t; sl@0: #endif sl@0: sl@0: /* The C++ semantics support requires definition of the RTTI object sl@0: * layout. We use the same structures and names as the generic C++ sl@0: * ABI for Itanium. sl@0: * sl@0: * Define those structures here: sl@0: */ sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" { sl@0: #include "cxxabi.h" sl@0: } sl@0: #endif sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* External requirements */ sl@0: sl@0: /* The C++ exception-handling 'globals' should be allocated per-thread. sl@0: * The Exceptions ABI does not specify how this happens, but it is sl@0: * intended that the details are localised to __cxa_get_globals. sl@0: * sl@0: * In the ARM implementation of __cxa_get_globals, it is assumed that a sl@0: * zero-initialised location in a known per-thread place is somehow sl@0: * obtainable, and can be assigned (by __cxa_get_globals) a pointer to sl@0: * the allocated globals data structure. The macro EH_GLOBALS should be sl@0: * defined here to yield a suitable address of type void*. This is used sl@0: * only in __cxa_get_globals. sl@0: * sl@0: * Define it here: sl@0: */ sl@0: sl@0: #ifdef __cplusplus sl@0: #ifndef __EPOC32__ sl@0: extern "C" { sl@0: /* for __user_libspace() machinery */ sl@0: #include <interns.h> sl@0: #define EH_GLOBALS libspace.eh_globals sl@0: } sl@0: #else sl@0: #include <e32std.h> sl@0: #define EH_GLOBALS (Dll::Tls()) sl@0: #endif sl@0: #endif sl@0: sl@0: /* A routine is required for C++ derived class to base class conversion. sl@0: * This is used once, in __cxa_type_match. It is likely that suitable sl@0: * code exists as part of the RTTI support code. Therefore access it sl@0: * via a macro: sl@0: * DERIVED_TO_BASE_CONVERSION(PTR, P_NEW_PTR, CLASS_INFO, BASE_INFO) sl@0: * Convert PTR from a pointer to a derived class (described by sl@0: * CLASS_INFO) to a pointer to a base class (described by BASE_INFO) sl@0: * and store the resulting pointer in P_NEW_PTR. Return true (or sl@0: * non-zero) if the base class was found and the conversion was done, sl@0: * otherwise return false (or zero). sl@0: * sl@0: * Define the macro here: sl@0: */ sl@0: sl@0: #ifdef __cplusplus sl@0: /* In the ARM implementation, a suitable routine exists elsewhere in the sl@0: * C++ runtime library, where it is part of the dynamic_cast mechanism. sl@0: */ sl@0: #if !defined(__EPOC32__) || (__ARMCC_VERSION > 310000) sl@0: extern "C" int __derived_to_base_conversion(void** p_ptr, void** p_new_ptr, sl@0: const std::type_info * class_info, sl@0: const std::type_info * base_info, sl@0: char** access_flags, int use_access_flags); sl@0: sl@0: #define DERIVED_TO_BASE_CONVERSION(PTR, P_NEW_PTR, CLASS_INFO, BASE_INFO) \ sl@0: __derived_to_base_conversion(&(PTR), (P_NEW_PTR), (CLASS_INFO), (BASE_INFO), NULL, 0) sl@0: #else sl@0: extern "C" TBool _DoDerivedToBaseConversion(const std::type_info* aDerivedType, sl@0: const std::type_info* aBaseType, sl@0: TAny** aDerivedObj, sl@0: TAny** aBaseObj); sl@0: sl@0: #define DERIVED_TO_BASE_CONVERSION(PTR, P_NEW_PTR, CLASS_INFO, BASE_INFO) \ sl@0: _DoDerivedToBaseConversion(CLASS_INFO, BASE_INFO, &(PTR), P_NEW_PTR) sl@0: #endif sl@0: sl@0: #endif sl@0: sl@0: /* The effect of R_ARM_TARGET2 relocations is platform-specific. A sl@0: * routine is required for handling references created via such sl@0: * relocations. The routine takes the address of a location that was sl@0: * relocated by R_ARM_TARGET2, and returns a pointer to the absolute sl@0: * address of the referenced entity. sl@0: */ sl@0: sl@0: static FORCEINLINE void *__ARM_resolve_target2(void *p) sl@0: { sl@0: #ifdef __APCS_FPIC sl@0: /* SVr4: R_ARM_TARGET2 is equivalent to R_ARM_GOT_PREL (placerel32 indirect) */ sl@0: return *(void **)(*(uint32_t *)p + (uint32_t)p); sl@0: #else sl@0: /* Bare metal: R_ARM_TARGET2 is equivalent to R_ARM_ABS32 */ sl@0: return *(void **)p; sl@0: #endif sl@0: } sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Runtime debug support sl@0: * sl@0: * Here we define the interface to a "bottleneck function" to be called sl@0: * by exception handling code at 'interesting' points during execution, sl@0: * and breakpointable by a debugger. sl@0: * sl@0: * This is not part of the Exceptions ABI but is expected to be sl@0: * standardised elsewhere, probably in a Debug ABI. sl@0: * sl@0: * If you don't want this, define DEBUGGER_BOTTLENECK as a dummy, e.g. sl@0: * #define DEBUGGER_BOTTLENECK(UCBP,LANG,ACTIVITY,ARG) (void)0 sl@0: */ sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" { sl@0: #endif sl@0: sl@0: struct _Unwind_Control_Block; sl@0: sl@0: typedef enum { sl@0: _UASUBSYS_CPP = 0x00, sl@0: _UASUBSYS_UNWINDER = 0xff sl@0: } _Unwind_Activity_subsystem; sl@0: sl@0: typedef enum { sl@0: _UAACT_STARTING = 0x0, sl@0: _UAACT_ENDING = 0x1, sl@0: _UAACT_BARRIERFOUND = 0x2, sl@0: _UAACT_PADENTRY = 0x3, sl@0: _UAACT_CPP_TYPEINFO = 0x80 sl@0: } _Unwind_Activity_activity; sl@0: sl@0: typedef enum { sl@0: _UAARG_ENDING_UNSPECIFIED = 0x0, sl@0: _UAARG_ENDING_TABLECORRUPT = 0x1, sl@0: _UAARG_ENDING_NOUNWIND = 0x2, sl@0: _UAARG_ENDING_VRSFAILED = 0x3, sl@0: /* C++ only: */ sl@0: _UAARG_ENDING_CPP_BADOPCODE = 0x4, sl@0: /* Unwinder only: */ sl@0: _UAARG_ENDING_UNWINDER_LOOKUPFAILED = 0x4, sl@0: _UAARG_ENDING_UNWINDER_BUFFERFAILED = 0x5 sl@0: } _Unwind_Activity_arg; sl@0: sl@0: void _Unwind_Activity(struct _Unwind_Control_Block *ucbp, uint32_t reason, uint32_t arg); sl@0: #define DEBUGGER_BOTTLENECK(UCBP,LANG,ACTIVITY,ARG) \ sl@0: _Unwind_Activity((UCBP),((((uint32_t)(LANG))<<24)|ACTIVITY),(uint32_t)(ARG)) sl@0: sl@0: #ifdef __cplusplus sl@0: } sl@0: #endif sl@0: sl@0: sl@0: /* ---------------------------------------------------------------------- */ sl@0: sl@0: /* Printed diagnostics sl@0: * sl@0: * These may be useful for debugging purposes during development, provided sl@0: * the execution environment supports diagnostics via printf. sl@0: * sl@0: * #define PR_DIAGNOSTICS for printed diagnostics from the personality routine. sl@0: * #define VRS_DIAGNOSTICS for printed diagnostics about VRS operations. sl@0: * #define UNWIND_ACTIVITY_DIAGNOSTICS for printed information from _Unwind_Activity. sl@0: * #define CPP_DIAGNOSTICS for printed diagnostics from the C++ semantics routines. sl@0: */ sl@0: sl@0: /* ---------------------------------------------------------------------- sl@0: * Abstractions added for SymbianOS. A process is contructed from multiple sl@0: * executables each with their own RO segment and exception data structures. sl@0: * SymbianOS caches pointers to two data structures in the UCB which it then sl@0: * uses to speed up the retrieval of certain information including values returned sl@0: * by the functions below. sl@0: * ---------------------------------------------------------------------- */ sl@0: #ifndef __EPOC32__ sl@0: #define ADDR_TO_ER_RO_OFFSET(addr, ucbp) addr_to_ER_RO_offset(addr) sl@0: #define ER_RO_OFFSET_TO_ADDR(addr, ucbp) ER_RO_offset_to_addr(addr) sl@0: #else sl@0: #define ADDR_TO_ER_RO_OFFSET(addr, ucbp) addr_to_ER_RO_offset(addr, ucbp) sl@0: #define ER_RO_OFFSET_TO_ADDR(addr, ucbp) ER_RO_offset_to_addr(addr, ucbp) sl@0: #endif sl@0: sl@0: sl@0: #endif /* defined UNWINDENV_H */ sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: