kernel/eka/compsupp/symaehabi/symbian_support.cpp
changeset 43 96e5fb8b040d
child 44 36bfc973b146
equal deleted inserted replaced
-1:000000000000 43: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.cpp
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /* Environment: */
       
    21 #include "unwind_env.h"
       
    22 /* Language-independent unwinder declarations: */
       
    23 #include "unwinder.h"
       
    24 
       
    25 /* Symbian specific support */
       
    26 #include "symbian_support.h"
       
    27 
       
    28 #include <e32def.h>
       
    29 #include <e32def_private.h>
       
    30 #include <e32rom.h>
       
    31 #include <e32svr.h>
       
    32 #include <e32debug.h>
       
    33 
       
    34 static void __default_terminate_handler(void)
       
    35 	{
       
    36 	abort();
       
    37 	}
       
    38 
       
    39 #define NAMES __ARM
       
    40 namespace NAMES { void default_unexpected_handler(void); }
       
    41 
       
    42 EXPORT_C TCppRTExceptionsGlobals::TCppRTExceptionsGlobals()
       
    43 	{
       
    44 	buffer.inuse = false;
       
    45 	thread_globals.uncaughtExceptions = 0;
       
    46 	thread_globals.unexpectedHandler = NAMES::default_unexpected_handler;
       
    47 	thread_globals.terminateHandler = __default_terminate_handler;
       
    48 	thread_globals.implementation_ever_called_terminate = false;
       
    49 	thread_globals.call_hook = NULL;
       
    50 	thread_globals.caughtExceptions = NULL;
       
    51 	thread_globals.propagatingExceptions = NULL;
       
    52 	thread_globals.emergency_buffer = &buffer;
       
    53 	Dll::SetTls(this);
       
    54 	}
       
    55 #if __ARMCC_VERSION < 220000
       
    56 extern "C" 
       
    57 {
       
    58   /*
       
    59     we have to dummy up the following for 2.1. The names changed in the def file
       
    60     since in 2.2 catch handlers should be able to deal with imported RTTI
       
    61 
       
    62 	_ZTI15XLeaveException @ 206 NONAME ; Typeinfo for XLeaveException
       
    63 	_ZTV15XLeaveException @ 207 NONAME ; vtable for XLeaveException
       
    64 	_ZN15XLeaveException16ForceKeyFunctionEv @ 208 NONAME ; the key function for XLeaveException
       
    65   */
       
    66 
       
    67 EXPORT_C void _ZTI15XLeaveException()
       
    68 	{
       
    69 	// reserve a DEF file slot for key function
       
    70 	}
       
    71 
       
    72 EXPORT_C void _ZTV15XLeaveException()
       
    73 	{
       
    74 	// reserve a DEF file slot for vtable
       
    75 	}
       
    76 
       
    77 EXPORT_C void _ZN15XLeaveException16ForceKeyFunctionEv()
       
    78 	{
       
    79 	// reserve a DEF file slot for RTTI
       
    80 	}
       
    81 }
       
    82 
       
    83 #else 
       
    84 // This is the key function that forces the class impedimenta to be get exported in RVCT 2.2 and later.
       
    85 EXPORT_C void XLeaveException::ForceKeyFunction(){}
       
    86 #endif
       
    87 
       
    88 #if 0
       
    89 #pragma push
       
    90 #pragma arm
       
    91 // If the strings were word aligned we could do something like this.
       
    92 // We could even do this if we checked the alignment of the strings.
       
    93 // Unfortunately the chances of them both being word aligned are
       
    94 // sufficiently slim (1/16) that the test for alignment will be carried out
       
    95 // most of time for no good purpose.
       
    96 static inline int typenameeq(const char* n1, const char* n2)
       
    97 	{
       
    98 	if (n1 == n2)
       
    99 		return 1;
       
   100 	int* i1 = (int*)n1;
       
   101 	int* i2 = (int*)n2;
       
   102 	int w1=0;
       
   103 	int w2=0;
       
   104 	int x1, x2;
       
   105 	for (int i = 0, w1=i1[i], w2=i2[i]; w1 == w2; i++, w1=i1[i], w2=i2[i])
       
   106 		{
       
   107 		// they're the same but they might contain the terminator
       
   108 		if (!(w1 & 0xffffff00))
       
   109 			return 1;
       
   110 		if (!(w1 & 0xffff00ff))
       
   111 			return 1;
       
   112 		if (!(w1 & 0xff00ffff))
       
   113 			return 1;
       
   114 		if (!(w1 & 0x00ffffff))
       
   115 			return 1;
       
   116 		}
       
   117 	// they're not the same but they might contain the terminator in the same place
       
   118 	x1 = w1 & 0x000000ff;
       
   119 	x2 = w2 & 0x000000ff;
       
   120 	if (!x1 && !x2)
       
   121 		return 1;
       
   122 	if (x1 != x2)
       
   123 		return 0;
       
   124 
       
   125 	x1 = w1 & 0x0000ff00;
       
   126 	x2 = w2 & 0x0000ff00;
       
   127 	if (!x1 && !x2)
       
   128 		return 1;
       
   129 	if (x1 != x2)
       
   130 		return 0;
       
   131 
       
   132 	x1 = w1 & 0x00ff0000;
       
   133 	x2 = w2 & 0x00ff0000;
       
   134 	if (!x1 && !x2)
       
   135 		return 1;
       
   136 	if (x1 != x2)
       
   137 		return 0;
       
   138 
       
   139 	x1 = w1 & 0xff000000;
       
   140 	x2 = w2 & 0xff000000;
       
   141 	if (!x1 && !x2)
       
   142 		return 1;
       
   143 	if (x1 != x2)
       
   144 		return 0;
       
   145 
       
   146 	// just to keep the compiler quiet
       
   147 	return 0;
       
   148 	}
       
   149 #pragma pop
       
   150 #endif
       
   151 
       
   152 extern "C" {
       
   153 
       
   154 IMPORT_C void abort();
       
   155 
       
   156 TRomExceptionSearchTable * GetROMExceptionSearchTable(void)
       
   157 	{
       
   158 	return (TRomExceptionSearchTable *)((TRomHeader *)UserSvr::RomHeaderAddress())->iRomExceptionSearchTable;
       
   159 	}
       
   160 
       
   161 TExceptionDescriptor* SearchEST(uint32_t addr, TRomExceptionSearchTable* aESTp)
       
   162 	{
       
   163 	uint32_t l = 0;
       
   164 	uint32_t nelems = aESTp->iNumEntries;
       
   165 	uint32_t r = nelems;
       
   166 	uint32_t m = 0;
       
   167 	uint32_t val;
       
   168 	uint32_t* base = (uint32_t*)&aESTp->iEntries[0];
       
   169 	while (r > l)
       
   170 		{
       
   171 		m = (l + r) >> 1;
       
   172 		val = base[m];
       
   173 		if (val > addr)
       
   174 			r = m;
       
   175 		else
       
   176 			l = m + 1;
       
   177 		}
       
   178 	val = base[l-1];
       
   179 	if (addr >= val && addr < base[l])	/* relies on presence of fencepost at the end */
       
   180 		{
       
   181 		const TRomImageHeader* rih = (const TRomImageHeader*)val;
       
   182 		return (TExceptionDescriptor*)rih[-1].iExceptionDescriptor;
       
   183 		}
       
   184 	return 0;
       
   185 	}
       
   186 
       
   187 
       
   188 TExceptionDescriptor * GetRAMLoadedExceptionDescriptor(uint32_t addr)
       
   189 	{
       
   190 	TLinAddr aEDp = UserSvr::ExceptionDescriptor(addr);
       
   191 
       
   192 	SYMBIAN_EH_SUPPORT_PRINTF("UserSvr::ExceptionDescriptor for %08x returned %08x\n", addr, aEDp);
       
   193 
       
   194 	return (TExceptionDescriptor *)(aEDp & 0xfffffffe);
       
   195 	}
       
   196 
       
   197 void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp)
       
   198 	{
       
   199 	SET_ROM_EST(ucbp, GetROMExceptionSearchTable());
       
   200 	if (!ReLoadExceptionDescriptor(addr, ucbp))
       
   201 		{
       
   202 		SYMBIAN_EH_SUPPORT_PRINTF("EH ERROR: no exception descriptor for address 0x%08x\n", addr);
       
   203 		abort();
       
   204 		}
       
   205 	}
       
   206 
       
   207 TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp)
       
   208 	{
       
   209 	/* Check to see if address is in range covered by ROM EST. If
       
   210 	   it is find the exception descriptor for the address,
       
   211 	   checking that the address is in the range covered by the
       
   212 	   descriptor.  Otherwise it comes from a RAM loaded
       
   213 	   executable so get the kernel to find the exception
       
   214 	   descriptor for us.
       
   215 	*/
       
   216 	TRomExceptionSearchTable * aESTp = GET_ROM_EST(ucbp);
       
   217 	TExceptionDescriptor * aEDp = NULL;
       
   218 	if (aESTp && addr >= aESTp->iEntries[0] && addr < GET_EST_FENCEPOST(aESTp))
       
   219 		{
       
   220 		aEDp = SearchEST(addr, aESTp);
       
   221 		goto jobdone;
       
   222 		}
       
   223 	aEDp = GetRAMLoadedExceptionDescriptor(addr);
       
   224 	if (!aEDp)
       
   225 		{
       
   226 		// look in extension ROM if there is one
       
   227 		TUint main_start = UserSvr::RomHeaderAddress();
       
   228 		TUint main_end = main_start + ((TRomHeader*)main_start)->iUncompressedSize;
       
   229 		
       
   230 		TUint rda = UserSvr::RomRootDirectoryAddress();
       
   231 		
       
   232 		// Assume rom starts on multiple of 4k
       
   233 		if (rda > main_end)
       
   234 			{
       
   235 			// ASSUMPTIONS HERE
       
   236 			// 1. root directory is past the end of the main ROM so there must be an extension ROM
       
   237 			// 2. the ROM file system in the extension ROM is at the beginning of the ROM (similar to the
       
   238 			//    main ROM)
       
   239 			// 3. the extension ROM is mapped starting at a megabyte boundary
       
   240 			// Thus the address of the extension ROM header may be obtained by rounding the root directory
       
   241 			// address down to the next megabyte boundary.
       
   242          
       
   243  			TUint ext_start = rda &~ 0x000fffffu;
       
   244 			TRomExceptionSearchTable* extrom_exctab = (TRomExceptionSearchTable*)(((TExtensionRomHeader*)ext_start)->iRomExceptionSearchTable);
       
   245 			if (extrom_exctab && addr >= extrom_exctab->iEntries[0] && addr < GET_EST_FENCEPOST(extrom_exctab))
       
   246 				aEDp = SearchEST(addr, extrom_exctab);
       
   247 			}
       
   248 		}
       
   249 
       
   250 jobdone:
       
   251 	SYMBIAN_EH_SUPPORT_PRINTF("ReLoadExceptionDescriptor: Exception descriptor for address 0x%08x = 0x%08x\n\r", addr, aEDp);
       
   252 
       
   253 	if (aEDp && ADDRESS_IN_EXCEPTION_DESCRIPTOR_RANGE(addr, aEDp))
       
   254 		return SET_EXCEPTION_DESCRIPTOR(ucbp, aEDp);
       
   255 	else
       
   256 	  	return NULL;
       
   257 	}
       
   258 
       
   259 
       
   260 const __EIT_entry* SearchEITV1(uint32_t return_address_offset, const __EIT_entry* base, unsigned int nelems)
       
   261 	{
       
   262 	uint32_t l = 0;
       
   263 	uint32_t r = nelems;
       
   264 	uint32_t m=0;
       
   265 	uint32_t val;
       
   266 	while (r>l)
       
   267 		{
       
   268 		m = (l + r) >> 1;
       
   269 		val = base[m].fnoffset;
       
   270 		if (val > return_address_offset)
       
   271 			r = m;
       
   272 		else
       
   273 			l = m + 1;
       
   274 		}
       
   275 #ifdef _DEBUG
       
   276 	val = base[l-1].fnoffset;
       
   277 	SYMBIAN_EH_SUPPORT_PRINTF("SearchEITV1: Located IDX with fnoffset = %08x\n\r", val);
       
   278 #endif
       
   279 	return base + l - 1;
       
   280 	}
       
   281 
       
   282 /* R_ARM_PREL31 is a place-relative 31-bit signed relocation.  The
       
   283  * routine takes the address of a location that was relocated by
       
   284  * R_ARM_PREL31, and returns an absolute address.
       
   285  */
       
   286 static FORCEINLINE uint32_t __ARM_resolve_prel31(void *p)
       
   287 {
       
   288   return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
       
   289 }
       
   290 
       
   291 __EIT_entry* SearchEITV2(uint32_t return_address, const __EIT_entry* base, unsigned int nelems)
       
   292 	{
       
   293 	uint32_t l = 0;
       
   294 	uint32_t r = nelems;
       
   295 	uint32_t m=0;
       
   296 	uint32_t val;
       
   297 	while (r>l)
       
   298 		{
       
   299 		m = (l + r) >> 1;
       
   300 		val = __ARM_resolve_prel31((void *)&base[m].fnoffset);
       
   301 		if (val > return_address)
       
   302 			r = m;
       
   303 		else
       
   304 			l = m + 1;
       
   305 		}
       
   306 #ifdef _DEBUG
       
   307 	val = __ARM_resolve_prel31((void *)&base[l-1].fnoffset);
       
   308 	SYMBIAN_EH_SUPPORT_PRINTF("SearchEITV2: Located IDX with fn address = %08x\n\r", val);
       
   309 #endif
       
   310 	return ((__EIT_entry *)base) + l - 1;
       
   311 	}
       
   312 
       
   313 
       
   314 #ifdef _DEBUG
       
   315 class TestOverflowTruncate8 : public TDes8Overflow
       
   316 	{
       
   317 public:
       
   318 	virtual void Overflow(TDes8& /*aDes*/) {}
       
   319 	};
       
   320 	
       
   321 #endif
       
   322 
       
   323 void DebugPrintf(const char * aFmt, ...)
       
   324 	{
       
   325 #ifdef _DEBUG
       
   326 	TestOverflowTruncate8 overflow;
       
   327 	VA_LIST list;
       
   328 	VA_START(list,aFmt);
       
   329 	TPtrC8 fmt((const TUint8 *)aFmt);
       
   330 	TBuf8<0x100> buf;
       
   331 	buf.AppendFormatList(fmt,list,&overflow);
       
   332 	TBuf<0x100> buf2;
       
   333 	buf2.Copy(buf);
       
   334 	if (buf2[buf2.Length()-1]=='\n') buf2.Append('\r');
       
   335 	RDebug::RawPrint(buf2);
       
   336 #else
       
   337 	(void)aFmt;
       
   338 #endif		
       
   339 	}
       
   340 
       
   341 } // extern "C"