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