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.
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32/compsupp/symaehabi/symbian_support.cpp
19 #include "unwind_env.h"
20 /* Language-independent unwinder declarations: */
23 /* Symbian specific support */
24 #include "symbian_support.h"
27 #include <e32def_private.h>
32 static void __default_terminate_handler(void)
38 namespace NAMES { void default_unexpected_handler(void); }
40 EXPORT_C TCppRTExceptionsGlobals::TCppRTExceptionsGlobals()
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;
53 #if __ARMCC_VERSION < 220000
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
60 _ZTI15XLeaveException @ 206 NONAME ; Typeinfo for XLeaveException
61 _ZTV15XLeaveException @ 207 NONAME ; vtable for XLeaveException
62 _ZN15XLeaveException16ForceKeyFunctionEv @ 208 NONAME ; the key function for XLeaveException
65 EXPORT_C void _ZTI15XLeaveException()
67 // reserve a DEF file slot for key function
70 EXPORT_C void _ZTV15XLeaveException()
72 // reserve a DEF file slot for vtable
75 EXPORT_C void _ZN15XLeaveException16ForceKeyFunctionEv()
77 // reserve a DEF file slot for RTTI
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(){}
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)
103 for (int i = 0, w1=i1[i], w2=i2[i]; w1 == w2; i++, w1=i1[i], w2=i2[i])
105 // they're the same but they might contain the terminator
106 if (!(w1 & 0xffffff00))
108 if (!(w1 & 0xffff00ff))
110 if (!(w1 & 0xff00ffff))
112 if (!(w1 & 0x00ffffff))
115 // they're not the same but they might contain the terminator in the same place
116 x1 = w1 & 0x000000ff;
117 x2 = w2 & 0x000000ff;
123 x1 = w1 & 0x0000ff00;
124 x2 = w2 & 0x0000ff00;
130 x1 = w1 & 0x00ff0000;
131 x2 = w2 & 0x00ff0000;
137 x1 = w1 & 0xff000000;
138 x2 = w2 & 0xff000000;
144 // just to keep the compiler quiet
152 IMPORT_C void abort();
154 TRomExceptionSearchTable * GetROMExceptionSearchTable(void)
156 return (TRomExceptionSearchTable *)((TRomHeader *)UserSvr::RomHeaderAddress())->iRomExceptionSearchTable;
159 TExceptionDescriptor* SearchEST(uint32_t addr, TRomExceptionSearchTable* aESTp)
162 uint32_t nelems = aESTp->iNumEntries;
166 uint32_t* base = (uint32_t*)&aESTp->iEntries[0];
177 if (addr >= val && addr < base[l]) /* relies on presence of fencepost at the end */
179 const TRomImageHeader* rih = (const TRomImageHeader*)val;
180 return (TExceptionDescriptor*)rih[-1].iExceptionDescriptor;
186 TExceptionDescriptor * GetRAMLoadedExceptionDescriptor(uint32_t addr)
188 TLinAddr aEDp = UserSvr::ExceptionDescriptor(addr);
190 SYMBIAN_EH_SUPPORT_PRINTF("UserSvr::ExceptionDescriptor for %08x returned %08x\n", addr, aEDp);
192 return (TExceptionDescriptor *)(aEDp & 0xfffffffe);
195 void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp)
197 SET_ROM_EST(ucbp, GetROMExceptionSearchTable());
198 if (!ReLoadExceptionDescriptor(addr, ucbp))
200 SYMBIAN_EH_SUPPORT_PRINTF("EH ERROR: no exception descriptor for address 0x%08x\n", addr);
205 TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp)
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
214 TRomExceptionSearchTable * aESTp = GET_ROM_EST(ucbp);
215 TExceptionDescriptor * aEDp = NULL;
216 if (aESTp && addr >= aESTp->iEntries[0] && addr < GET_EST_FENCEPOST(aESTp))
218 aEDp = SearchEST(addr, aESTp);
221 aEDp = GetRAMLoadedExceptionDescriptor(addr);
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;
228 TUint rda = UserSvr::RomRootDirectoryAddress();
230 // Assume rom starts on multiple of 4k
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
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.
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);
249 SYMBIAN_EH_SUPPORT_PRINTF("ReLoadExceptionDescriptor: Exception descriptor for address 0x%08x = 0x%08x\n\r", addr, aEDp);
251 if (aEDp && ADDRESS_IN_EXCEPTION_DESCRIPTOR_RANGE(addr, aEDp))
252 return SET_EXCEPTION_DESCRIPTOR(ucbp, aEDp);
258 const __EIT_entry* SearchEITV1(uint32_t return_address_offset, const __EIT_entry* base, unsigned int nelems)
267 val = base[m].fnoffset;
268 if (val > return_address_offset)
274 val = base[l-1].fnoffset;
275 SYMBIAN_EH_SUPPORT_PRINTF("SearchEITV1: Located IDX with fnoffset = %08x\n\r", val);
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.
284 static FORCEINLINE uint32_t __ARM_resolve_prel31(void *p)
286 return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
289 __EIT_entry* SearchEITV2(uint32_t return_address, const __EIT_entry* base, unsigned int nelems)
298 val = __ARM_resolve_prel31((void *)&base[m].fnoffset);
299 if (val > return_address)
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);
308 return ((__EIT_entry *)base) + l - 1;
313 class TestOverflowTruncate8 : public TDes8Overflow
316 virtual void Overflow(TDes8& /*aDes*/) {}
321 void DebugPrintf(const char * aFmt, ...)
324 TestOverflowTruncate8 overflow;
327 TPtrC8 fmt((const TUint8 *)aFmt);
329 buf.AppendFormatList(fmt,list,&overflow);
332 if (buf2[buf2.Length()-1]=='\n') buf2.Append('\r');
333 RDebug::RawPrint(buf2);