1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/compsupp/symaehabi/symbian_support.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,339 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "ARM EABI LICENCE.txt"
1.8 +// which accompanies this distribution, and is available
1.9 +// in kernel/eka/compsupp.
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32/compsupp/symaehabi/symbian_support.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +/* Environment: */
1.22 +#include "unwind_env.h"
1.23 +/* Language-independent unwinder declarations: */
1.24 +#include "unwinder.h"
1.25 +
1.26 +/* Symbian specific support */
1.27 +#include "symbian_support.h"
1.28 +
1.29 +#include <e32def.h>
1.30 +#include <e32def_private.h>
1.31 +#include <e32rom.h>
1.32 +#include <e32svr.h>
1.33 +#include <e32debug.h>
1.34 +
1.35 +static void __default_terminate_handler(void)
1.36 + {
1.37 + abort();
1.38 + }
1.39 +
1.40 +#define NAMES __ARM
1.41 +namespace NAMES { void default_unexpected_handler(void); }
1.42 +
1.43 +EXPORT_C TCppRTExceptionsGlobals::TCppRTExceptionsGlobals()
1.44 + {
1.45 + buffer.inuse = false;
1.46 + thread_globals.uncaughtExceptions = 0;
1.47 + thread_globals.unexpectedHandler = NAMES::default_unexpected_handler;
1.48 + thread_globals.terminateHandler = __default_terminate_handler;
1.49 + thread_globals.implementation_ever_called_terminate = false;
1.50 + thread_globals.call_hook = NULL;
1.51 + thread_globals.caughtExceptions = NULL;
1.52 + thread_globals.propagatingExceptions = NULL;
1.53 + thread_globals.emergency_buffer = &buffer;
1.54 + Dll::SetTls(this);
1.55 + }
1.56 +#if __ARMCC_VERSION < 220000
1.57 +extern "C"
1.58 +{
1.59 + /*
1.60 + we have to dummy up the following for 2.1. The names changed in the def file
1.61 + since in 2.2 catch handlers should be able to deal with imported RTTI
1.62 +
1.63 + _ZTI15XLeaveException @ 206 NONAME ; Typeinfo for XLeaveException
1.64 + _ZTV15XLeaveException @ 207 NONAME ; vtable for XLeaveException
1.65 + _ZN15XLeaveException16ForceKeyFunctionEv @ 208 NONAME ; the key function for XLeaveException
1.66 + */
1.67 +
1.68 +EXPORT_C void _ZTI15XLeaveException()
1.69 + {
1.70 + // reserve a DEF file slot for key function
1.71 + }
1.72 +
1.73 +EXPORT_C void _ZTV15XLeaveException()
1.74 + {
1.75 + // reserve a DEF file slot for vtable
1.76 + }
1.77 +
1.78 +EXPORT_C void _ZN15XLeaveException16ForceKeyFunctionEv()
1.79 + {
1.80 + // reserve a DEF file slot for RTTI
1.81 + }
1.82 +}
1.83 +
1.84 +#else
1.85 +// This is the key function that forces the class impedimenta to be get exported in RVCT 2.2 and later.
1.86 +EXPORT_C void XLeaveException::ForceKeyFunction(){}
1.87 +#endif
1.88 +
1.89 +#if 0
1.90 +#pragma push
1.91 +#pragma arm
1.92 +// If the strings were word aligned we could do something like this.
1.93 +// We could even do this if we checked the alignment of the strings.
1.94 +// Unfortunately the chances of them both being word aligned are
1.95 +// sufficiently slim (1/16) that the test for alignment will be carried out
1.96 +// most of time for no good purpose.
1.97 +static inline int typenameeq(const char* n1, const char* n2)
1.98 + {
1.99 + if (n1 == n2)
1.100 + return 1;
1.101 + int* i1 = (int*)n1;
1.102 + int* i2 = (int*)n2;
1.103 + int w1=0;
1.104 + int w2=0;
1.105 + int x1, x2;
1.106 + for (int i = 0, w1=i1[i], w2=i2[i]; w1 == w2; i++, w1=i1[i], w2=i2[i])
1.107 + {
1.108 + // they're the same but they might contain the terminator
1.109 + if (!(w1 & 0xffffff00))
1.110 + return 1;
1.111 + if (!(w1 & 0xffff00ff))
1.112 + return 1;
1.113 + if (!(w1 & 0xff00ffff))
1.114 + return 1;
1.115 + if (!(w1 & 0x00ffffff))
1.116 + return 1;
1.117 + }
1.118 + // they're not the same but they might contain the terminator in the same place
1.119 + x1 = w1 & 0x000000ff;
1.120 + x2 = w2 & 0x000000ff;
1.121 + if (!x1 && !x2)
1.122 + return 1;
1.123 + if (x1 != x2)
1.124 + return 0;
1.125 +
1.126 + x1 = w1 & 0x0000ff00;
1.127 + x2 = w2 & 0x0000ff00;
1.128 + if (!x1 && !x2)
1.129 + return 1;
1.130 + if (x1 != x2)
1.131 + return 0;
1.132 +
1.133 + x1 = w1 & 0x00ff0000;
1.134 + x2 = w2 & 0x00ff0000;
1.135 + if (!x1 && !x2)
1.136 + return 1;
1.137 + if (x1 != x2)
1.138 + return 0;
1.139 +
1.140 + x1 = w1 & 0xff000000;
1.141 + x2 = w2 & 0xff000000;
1.142 + if (!x1 && !x2)
1.143 + return 1;
1.144 + if (x1 != x2)
1.145 + return 0;
1.146 +
1.147 + // just to keep the compiler quiet
1.148 + return 0;
1.149 + }
1.150 +#pragma pop
1.151 +#endif
1.152 +
1.153 +extern "C" {
1.154 +
1.155 +IMPORT_C void abort();
1.156 +
1.157 +TRomExceptionSearchTable * GetROMExceptionSearchTable(void)
1.158 + {
1.159 + return (TRomExceptionSearchTable *)((TRomHeader *)UserSvr::RomHeaderAddress())->iRomExceptionSearchTable;
1.160 + }
1.161 +
1.162 +TExceptionDescriptor* SearchEST(uint32_t addr, TRomExceptionSearchTable* aESTp)
1.163 + {
1.164 + uint32_t l = 0;
1.165 + uint32_t nelems = aESTp->iNumEntries;
1.166 + uint32_t r = nelems;
1.167 + uint32_t m = 0;
1.168 + uint32_t val;
1.169 + uint32_t* base = (uint32_t*)&aESTp->iEntries[0];
1.170 + while (r > l)
1.171 + {
1.172 + m = (l + r) >> 1;
1.173 + val = base[m];
1.174 + if (val > addr)
1.175 + r = m;
1.176 + else
1.177 + l = m + 1;
1.178 + }
1.179 + val = base[l-1];
1.180 + if (addr >= val && addr < base[l]) /* relies on presence of fencepost at the end */
1.181 + {
1.182 + const TRomImageHeader* rih = (const TRomImageHeader*)val;
1.183 + return (TExceptionDescriptor*)rih[-1].iExceptionDescriptor;
1.184 + }
1.185 + return 0;
1.186 + }
1.187 +
1.188 +
1.189 +TExceptionDescriptor * GetRAMLoadedExceptionDescriptor(uint32_t addr)
1.190 + {
1.191 + TLinAddr aEDp = UserSvr::ExceptionDescriptor(addr);
1.192 +
1.193 + SYMBIAN_EH_SUPPORT_PRINTF("UserSvr::ExceptionDescriptor for %08x returned %08x\n", addr, aEDp);
1.194 +
1.195 + return (TExceptionDescriptor *)(aEDp & 0xfffffffe);
1.196 + }
1.197 +
1.198 +void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp)
1.199 + {
1.200 + SET_ROM_EST(ucbp, GetROMExceptionSearchTable());
1.201 + if (!ReLoadExceptionDescriptor(addr, ucbp))
1.202 + {
1.203 + SYMBIAN_EH_SUPPORT_PRINTF("EH ERROR: no exception descriptor for address 0x%08x\n", addr);
1.204 + abort();
1.205 + }
1.206 + }
1.207 +
1.208 +TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp)
1.209 + {
1.210 + /* Check to see if address is in range covered by ROM EST. If
1.211 + it is find the exception descriptor for the address,
1.212 + checking that the address is in the range covered by the
1.213 + descriptor. Otherwise it comes from a RAM loaded
1.214 + executable so get the kernel to find the exception
1.215 + descriptor for us.
1.216 + */
1.217 + TRomExceptionSearchTable * aESTp = GET_ROM_EST(ucbp);
1.218 + TExceptionDescriptor * aEDp = NULL;
1.219 + if (aESTp && addr >= aESTp->iEntries[0] && addr < GET_EST_FENCEPOST(aESTp))
1.220 + {
1.221 + aEDp = SearchEST(addr, aESTp);
1.222 + goto jobdone;
1.223 + }
1.224 + aEDp = GetRAMLoadedExceptionDescriptor(addr);
1.225 + if (!aEDp)
1.226 + {
1.227 + // look in extension ROM if there is one
1.228 + TUint main_start = UserSvr::RomHeaderAddress();
1.229 + TUint main_end = main_start + ((TRomHeader*)main_start)->iUncompressedSize;
1.230 +
1.231 + TUint rda = UserSvr::RomRootDirectoryAddress();
1.232 +
1.233 + // Assume rom starts on multiple of 4k
1.234 + if (rda > main_end)
1.235 + {
1.236 + // ASSUMPTIONS HERE
1.237 + // 1. root directory is past the end of the main ROM so there must be an extension ROM
1.238 + // 2. the ROM file system in the extension ROM is at the beginning of the ROM (similar to the
1.239 + // main ROM)
1.240 + // 3. the extension ROM is mapped starting at a megabyte boundary
1.241 + // Thus the address of the extension ROM header may be obtained by rounding the root directory
1.242 + // address down to the next megabyte boundary.
1.243 +
1.244 + TUint ext_start = rda &~ 0x000fffffu;
1.245 + TRomExceptionSearchTable* extrom_exctab = (TRomExceptionSearchTable*)(((TExtensionRomHeader*)ext_start)->iRomExceptionSearchTable);
1.246 + if (extrom_exctab && addr >= extrom_exctab->iEntries[0] && addr < GET_EST_FENCEPOST(extrom_exctab))
1.247 + aEDp = SearchEST(addr, extrom_exctab);
1.248 + }
1.249 + }
1.250 +
1.251 +jobdone:
1.252 + SYMBIAN_EH_SUPPORT_PRINTF("ReLoadExceptionDescriptor: Exception descriptor for address 0x%08x = 0x%08x\n\r", addr, aEDp);
1.253 +
1.254 + if (aEDp && ADDRESS_IN_EXCEPTION_DESCRIPTOR_RANGE(addr, aEDp))
1.255 + return SET_EXCEPTION_DESCRIPTOR(ucbp, aEDp);
1.256 + else
1.257 + return NULL;
1.258 + }
1.259 +
1.260 +
1.261 +const __EIT_entry* SearchEITV1(uint32_t return_address_offset, const __EIT_entry* base, unsigned int nelems)
1.262 + {
1.263 + uint32_t l = 0;
1.264 + uint32_t r = nelems;
1.265 + uint32_t m=0;
1.266 + uint32_t val;
1.267 + while (r>l)
1.268 + {
1.269 + m = (l + r) >> 1;
1.270 + val = base[m].fnoffset;
1.271 + if (val > return_address_offset)
1.272 + r = m;
1.273 + else
1.274 + l = m + 1;
1.275 + }
1.276 +#ifdef _DEBUG
1.277 + val = base[l-1].fnoffset;
1.278 + SYMBIAN_EH_SUPPORT_PRINTF("SearchEITV1: Located IDX with fnoffset = %08x\n\r", val);
1.279 +#endif
1.280 + return base + l - 1;
1.281 + }
1.282 +
1.283 +/* R_ARM_PREL31 is a place-relative 31-bit signed relocation. The
1.284 + * routine takes the address of a location that was relocated by
1.285 + * R_ARM_PREL31, and returns an absolute address.
1.286 + */
1.287 +static FORCEINLINE uint32_t __ARM_resolve_prel31(void *p)
1.288 +{
1.289 + return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
1.290 +}
1.291 +
1.292 +__EIT_entry* SearchEITV2(uint32_t return_address, const __EIT_entry* base, unsigned int nelems)
1.293 + {
1.294 + uint32_t l = 0;
1.295 + uint32_t r = nelems;
1.296 + uint32_t m=0;
1.297 + uint32_t val;
1.298 + while (r>l)
1.299 + {
1.300 + m = (l + r) >> 1;
1.301 + val = __ARM_resolve_prel31((void *)&base[m].fnoffset);
1.302 + if (val > return_address)
1.303 + r = m;
1.304 + else
1.305 + l = m + 1;
1.306 + }
1.307 +#ifdef _DEBUG
1.308 + val = __ARM_resolve_prel31((void *)&base[l-1].fnoffset);
1.309 + SYMBIAN_EH_SUPPORT_PRINTF("SearchEITV2: Located IDX with fn address = %08x\n\r", val);
1.310 +#endif
1.311 + return ((__EIT_entry *)base) + l - 1;
1.312 + }
1.313 +
1.314 +
1.315 +#ifdef _DEBUG
1.316 +class TestOverflowTruncate8 : public TDes8Overflow
1.317 + {
1.318 +public:
1.319 + virtual void Overflow(TDes8& /*aDes*/) {}
1.320 + };
1.321 +
1.322 +#endif
1.323 +
1.324 +void DebugPrintf(const char * aFmt, ...)
1.325 + {
1.326 +#ifdef _DEBUG
1.327 + TestOverflowTruncate8 overflow;
1.328 + VA_LIST list;
1.329 + VA_START(list,aFmt);
1.330 + TPtrC8 fmt((const TUint8 *)aFmt);
1.331 + TBuf8<0x100> buf;
1.332 + buf.AppendFormatList(fmt,list,&overflow);
1.333 + TBuf<0x100> buf2;
1.334 + buf2.Copy(buf);
1.335 + if (buf2[buf2.Length()-1]=='\n') buf2.Append('\r');
1.336 + RDebug::RawPrint(buf2);
1.337 +#else
1.338 + (void)aFmt;
1.339 +#endif
1.340 + }
1.341 +
1.342 +} // extern "C"