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