kerneltest/e32test/cppexceptions/t_romtable.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\cppexceptions\t_romtable.cpp
       
    15 // Overview:
       
    16 // Check accessibility and integrity of ROM exception search table.
       
    17 // API Information:
       
    18 // TRomHeader, TRomExceptionSearchTable, TExceptionDescriptor
       
    19 // Details:	
       
    20 // - Get the ROM exception search table, verify results are as expected.
       
    21 // - Check that the correct exception descriptor is returned by
       
    22 // GetExceptionDescriptor().
       
    23 // - Check that the correct index table entry can be found.
       
    24 // - Initialize the unwinder cache of a UCB with an exception descriptor
       
    25 // and check we get the right result.
       
    26 // - Throw and catch a variety of exceptions and verify results are as expected.
       
    27 // Platforms/Drives/Compatibility:
       
    28 // Hardware (Automatic).
       
    29 // Assumptions/Requirement/Pre-requisites:
       
    30 // Failures and causes:
       
    31 // Base Port information:
       
    32 // 
       
    33 //
       
    34 
       
    35 /* Environment: */
       
    36 #include "unwind_env.h"
       
    37 /* Language-independent unwinder declarations: */
       
    38 #include "unwinder.h"
       
    39 
       
    40 #include "symbian_support.h"
       
    41 
       
    42 #include <f32file.h>
       
    43 #include <e32test.h>
       
    44 #include <e32rom.h>
       
    45 #include <cpudefs.h>
       
    46 
       
    47 GLDEF_D RTest test(_L("T_ROMTABLE"));
       
    48 
       
    49 TRomHeader * pTheRomHeader;
       
    50 char * GetExceptionDescriptor(void);
       
    51 extern "C" {
       
    52   IMPORT_C TRomExceptionSearchTable * GetROMExceptionSearchTable(void);
       
    53   IMPORT_C TExceptionDescriptor * SearchEST(uint32_t addr, TRomExceptionSearchTable * aESTp);
       
    54   TExceptionDescriptor * GetRAMLoadedExceptionDescriptor(uint32_t addr);
       
    55   IMPORT_C const __EIT_entry *SearchEITV1(uint32_t return_address_offset, const __EIT_entry *base, unsigned int nelems);
       
    56   IMPORT_C __EIT_entry* SearchEITV2(uint32_t return_address, const __EIT_entry* base, unsigned int nelems);
       
    57   TExceptionDescriptor * ReLoadExceptionDescriptor(uint32_t addr, _Unwind_Control_Block * ucbp);
       
    58   IMPORT_C void InitialiseSymbianSpecificUnwinderCache(uint32_t addr, _Unwind_Control_Block * ucbp);
       
    59 
       
    60   void *__cxa_allocate_exception(size_t size);
       
    61   IMPORT_C __cxa_eh_globals *  __cxa_get_globals();
       
    62 
       
    63 #ifdef _DEBUG
       
    64   IMPORT_C void DebugPrintf(const char * aFmt, ...);
       
    65 #endif
       
    66 }
       
    67 
       
    68 int catcher(int x);
       
    69 int catcher2(int x);
       
    70 int catcher3(int x);
       
    71 int catcher4(int x);
       
    72 int catcher5(int x);
       
    73 void TestUncaught(void);
       
    74 const __EIT_entry * DumbGetEITV1(TUint32 offset, const __EIT_entry * base, TUint32 n);
       
    75 __EIT_entry * DumbGetEITV2(TUint32 addr, __EIT_entry * base, TUint32 n);
       
    76 
       
    77 GLDEF_C TInt E32Main()
       
    78     {
       
    79     test.Start(_L("Check accessibility and integrity of ROM exception search table"));
       
    80 
       
    81     TRomExceptionSearchTable * pEST = GetROMExceptionSearchTable();
       
    82     test.Printf(_L("ROM EST @ %08x\n"), pEST);
       
    83     test(pEST != 0);
       
    84 
       
    85     test.Printf(_L("ROM EST contains %d entries\n"), pEST->iNumEntries);
       
    86 
       
    87     for (int i=0; i<pEST->iNumEntries; i++)
       
    88         {
       
    89 	TRomImageHeader * pE = (TRomImageHeader *)pEST->iEntries[i];
       
    90 	TRomImageHeader * pH = pE -1;
       
    91 	TUint xd = pH->iExceptionDescriptor;
       
    92 	if ((xd&1)==0 || xd==0xffffffffu)
       
    93 		continue;
       
    94 	xd &= ~1;
       
    95 	TExceptionDescriptor * pED = (TExceptionDescriptor *) ((char *)pE + xd);
       
    96 	char * aExIdxBase = (char *)pED->iExIdxBase;
       
    97 	char * aExIdxLimit = (char *)pED->iExIdxLimit;
       
    98 	char * aROBase = (char *) pED->iROSegmentBase;
       
    99 	char * aROLimit = (char *)pED->iROSegmentLimit;
       
   100 
       
   101 	test.Printf(_L("%d\n"),i);
       
   102 
       
   103 	test(aExIdxBase <= aExIdxLimit);
       
   104 
       
   105 	test(aROBase <= aROLimit);
       
   106 
       
   107 	test(aROBase <= aExIdxBase);
       
   108 	test(aExIdxLimit <= aROLimit);
       
   109         }
       
   110     test.Printf(_L("\n"));
       
   111 
       
   112 #ifdef __SUPPORT_CPP_EXCEPTIONS__
       
   113     // Check we get the right Exception Descriptor
       
   114     char * myExcpDesc = GetExceptionDescriptor();
       
   115     uint32_t addr = (uint32_t)GetExceptionDescriptor;
       
   116 
       
   117     test.Printf(_L("Checking &GetExceptionDescriptor [%08x] in EST range: %08x - %08x\n"), 
       
   118 		addr, pEST->iEntries[0], GET_EST_FENCEPOST(pEST));
       
   119     test(addr >= pEST->iEntries[0] && addr < GET_EST_FENCEPOST(pEST));
       
   120     TExceptionDescriptor * aExcpDescP = SearchEST(addr, pEST);
       
   121     test.Printf(_L("Found entry %08x in EST\n"), aExcpDescP);
       
   122     test(aExcpDescP != NULL);
       
   123     test.Printf(_L("Check myExcpDesc[%08x] == aExcpDescP[%08x]\n"), myExcpDesc, aExcpDescP);
       
   124     test(myExcpDesc==(char*)aExcpDescP);
       
   125 
       
   126     // Now check we can find the right entry in the index table.
       
   127     __EIT_entry * aExIdxBase1 = (__EIT_entry *)aExcpDescP->iExIdxBase;
       
   128     __EIT_entry * aExIdxLimit1 = (__EIT_entry *)aExcpDescP->iExIdxLimit;
       
   129     unsigned int nelems = aExIdxLimit1 - aExIdxBase1;
       
   130     uint32_t aROBase1 = (uint32_t)aExcpDescP->iROSegmentBase;
       
   131     int ehabiv2 = aROBase1 & 1;
       
   132     aROBase1 = aROBase1 & EHABI_MASK;
       
   133     uint32_t aRetOffest = addr - aROBase1;
       
   134     test.Printf(_L("EHABI_V2= %d: Looking up %08x with base %08x in ExIdx @ %08x with %d entries\n"),
       
   135 		ehabiv2, addr, aROBase1, aExIdxBase1, nelems);
       
   136     if (ehabiv2) {
       
   137       __EIT_entry * aResult = SearchEITV2(addr, aExIdxBase1, nelems);
       
   138       __EIT_entry * aResult1 = DumbGetEITV2(addr, aExIdxBase1, nelems);
       
   139       test.Printf(_L("Check result %08x == %08x\n"), aResult, aResult1);
       
   140       test(aResult == aResult1);
       
   141     } else {
       
   142       const __EIT_entry * aResult = SearchEITV1(aRetOffest, aExIdxBase1, nelems);
       
   143       const __EIT_entry * aResult1 = DumbGetEITV1(aRetOffest, aExIdxBase1, nelems);
       
   144       test.Printf(_L("Check result %08x == %08x\n"), aResult, aResult1);
       
   145       test(aResult == aResult1);
       
   146     }
       
   147 #ifdef _DEBUG
       
   148     DebugPrintf("Exception diagnostic print support is working if you can see this!!\n\r");
       
   149 #else
       
   150     test.Printf(_L("Exception diagnostic print support only available in UDEB builds - not tested\n"));
       
   151 #endif
       
   152 
       
   153     //check we've got some eh_globals
       
   154     __cxa_eh_globals *g = __cxa_get_globals();
       
   155     test.Printf(_L("Exception Handling globals for this thread allocated @ %08x\n"), g);
       
   156     test(g != NULL);
       
   157     test.Printf(_L("Emergency Buffer @ %08x\n"), g->emergency_buffer);
       
   158 
       
   159     // now initialize a the unwinder cache of a ucbp with an exception descriptor
       
   160     // and check we get the right result.
       
   161     test.Printf(_L("Allocate an empty exception object\n"));
       
   162     __cxa_exception *ep = ((__cxa_exception *)__cxa_allocate_exception(0)) - 1;
       
   163     test.Printf(_L("Empty Exception Object @ %08x UCB @ %08x\n"), ep, &ep->ucb);
       
   164     test.Printf(_L("Initialize the UCB with the EST and the current exception descriptor\n"));
       
   165     InitialiseSymbianSpecificUnwinderCache(addr, &ep->ucb);
       
   166     test.Printf(_L("Check the EST in the UCB [%08x] == %08x and the Exception Desc [%08x] == %08x\n"),
       
   167 		GET_ROM_EST(&ep->ucb), pEST, GET_EXCEPTION_DESCRIPTOR(&ep->ucb), myExcpDesc);
       
   168     test(GET_ROM_EST(&ep->ucb)==pEST);
       
   169     test((char*)GET_EXCEPTION_DESCRIPTOR(&ep->ucb)== myExcpDesc);
       
   170     
       
   171     test.Printf(_L("Throwing first exception.\n"));
       
   172     int r = catcher(2);
       
   173     test.Printf(_L("Returned %d expected 2\n"), r);
       
   174     test(r==2);
       
   175 
       
   176     test.Printf(_L("Not throwing first exception.\n"));
       
   177     r = catcher(0);
       
   178     test.Printf(_L("Returned %d expected -1\n"), r);
       
   179     test(r==-1);
       
   180 
       
   181     test.Printf(_L("Throwing second exception.\n"));
       
   182     r = catcher2(3);
       
   183     test.Printf(_L("Returned %d expected 3\n"), r);
       
   184     test(r==3);
       
   185 
       
   186     test.Printf(_L("Not throwing second exception.\n"));
       
   187     r = catcher2(0);
       
   188     test.Printf(_L("Returned %d expected -1\n"), r);
       
   189     test(r==-1);
       
   190 
       
   191     test.Printf(_L("Throwing third exception.\n"));
       
   192     r = catcher3(4);
       
   193     test.Printf(_L("Returned %d expected 4\n"), r);
       
   194     test(r==4);
       
   195 
       
   196     test.Printf(_L("Not throwing third exception.\n"));
       
   197     r = catcher3(0);
       
   198     test.Printf(_L("Returned %d expected -1\n"), r);
       
   199     test(r==-1);
       
   200 
       
   201     test.Printf(_L("Throwing fourth exception.\n"));
       
   202     r = catcher4(5);
       
   203     test.Printf(_L("Returned %d expected 5\n"), r);
       
   204     test(r==5);
       
   205 
       
   206     test.Printf(_L("Not throwing fourth exception.\n"));
       
   207     r = catcher4(0);
       
   208     test.Printf(_L("Returned %d expected -1\n"), r);
       
   209     test(r==-1);
       
   210 
       
   211     test.Printf(_L("Throwing fifth exception.\n"));
       
   212     r = catcher5(6);
       
   213     test.Printf(_L("Returned %d expected 6\n"), r);
       
   214     test(r==6);
       
   215 
       
   216     test.Printf(_L("Not throwing fifth exception.\n"));
       
   217     r = catcher5(0);
       
   218     test.Printf(_L("Returned %d expected -1\n"), r);
       
   219     test(r==-1);
       
   220 
       
   221     test.Printf(_L("Testing std::uncaught_exception.\n"));
       
   222     TestUncaught();
       
   223 #endif
       
   224 
       
   225 	test.End();
       
   226 	test.Close();
       
   227     return 0;
       
   228     }
       
   229 
       
   230 #ifdef __ARMCC__
       
   231 // We rely on this immediately following E32main. DONT MOVE IT
       
   232 __asm char * GetExceptionDescriptor(void) {
       
   233   extern |Symbian$$CPP$$Exception$$Descriptor|
       
   234   ldr r0, theExceptionDesc
       
   235 
       
   236 #ifdef __SUPPORT_THUMB_INTERWORKING
       
   237   bx lr
       
   238 #else
       
   239   mov pc, lr
       
   240 #endif
       
   241 
       
   242 theExceptionDesc dcd |Symbian$$CPP$$Exception$$Descriptor|
       
   243 }
       
   244 #endif
       
   245 
       
   246 const __EIT_entry * DumbGetEITV1(TUint32 offset, const __EIT_entry * base, TUint32 n) {
       
   247   if (n && offset < base[0].fnoffset) return 0;
       
   248   for (int i=0; i<n; i++) {
       
   249     // check for last entry 
       
   250     if (i == n-1 && base[i].fnoffset <= offset) return &base[i];
       
   251     if (base[i].fnoffset <= offset && offset < base[i+1].fnoffset) return &base[i];
       
   252   }
       
   253   return 0;
       
   254 }
       
   255 
       
   256 static uint32_t __ARM_resolve_prel31(void *p)
       
   257 {
       
   258   return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
       
   259 }
       
   260 
       
   261 __EIT_entry * DumbGetEITV2(TUint32 addr, __EIT_entry * base, TUint32 n) {
       
   262   if (n && (addr < __ARM_resolve_prel31(&base[0].fnoffset)))
       
   263     return 0;
       
   264   for (int i=0; i<n; i++) {
       
   265     // check for last entry 
       
   266     if (i == n-1 && __ARM_resolve_prel31(&base[i].fnoffset) <= addr) 
       
   267       return &base[i];
       
   268     if ((__ARM_resolve_prel31(&base[i].fnoffset) <= addr) && 
       
   269 	(addr < __ARM_resolve_prel31(&base[i+1].fnoffset)))
       
   270       return &base[i];
       
   271   }
       
   272   return 0;
       
   273 }
       
   274     
       
   275 #ifdef __SUPPORT_CPP_EXCEPTIONS__
       
   276 
       
   277 class MyFirstException {
       
   278 public:
       
   279   MyFirstException(int x) { iVal = x; };
       
   280   virtual ~MyFirstException();
       
   281   int iVal;
       
   282 };
       
   283 
       
   284 MyFirstException::~MyFirstException(){}
       
   285 
       
   286 int thrower (int x) {
       
   287   if (x != 0) throw MyFirstException(x);
       
   288   return -1;
       
   289 }
       
   290 
       
   291 int catcher(int x) {
       
   292   try {
       
   293     return thrower(x);
       
   294   }
       
   295   catch(MyFirstException& e) 
       
   296     {
       
   297       return e.iVal;
       
   298     }
       
   299 }
       
   300 
       
   301 
       
   302 #include "second_excp.h"
       
   303 
       
   304 
       
   305 int catcher2(int x) {
       
   306   try {
       
   307     return thrower2(x);
       
   308   }
       
   309   catch(MySecondException& e) 
       
   310     {
       
   311       return e.iVal;
       
   312     }
       
   313 }
       
   314 
       
   315 int catcher3(int x) {
       
   316   try {
       
   317     return thrower3(x);
       
   318   }
       
   319   catch(MyThirdException& e) 
       
   320     {
       
   321       return e.iVal;
       
   322     }
       
   323 }
       
   324 
       
   325 int catcher4(int x) {
       
   326   try {
       
   327     return thrower4(x);
       
   328   }
       
   329   catch(MyFourthException& e) 
       
   330     {
       
   331       return e.iVal;
       
   332     }
       
   333 }
       
   334 
       
   335 int catcher5(int x) {
       
   336   try {
       
   337     return thrower5(x);
       
   338   }
       
   339   catch(MyFifthException& e) 
       
   340     {
       
   341       return e.iVal;
       
   342     }
       
   343 }
       
   344 
       
   345 void TestUncaught(void) {
       
   346   TInt x = 0;
       
   347   try {
       
   348     UncaughtTester aTester(x);
       
   349     test.Printf(_L("Check throw case\n"));
       
   350     thrower(0);
       
   351   }
       
   352   catch(MyFirstException& e) 
       
   353     {
       
   354       test.Printf(_L("~Check x == 0\n"));
       
   355       test(x == 0);
       
   356     }
       
   357   try {
       
   358     UncaughtTester aTester(x);
       
   359     test.Printf(_L("Check no throw case\n"));
       
   360   }
       
   361   catch(MyFirstException& e) 
       
   362     {
       
   363       test.Printf(_L("Whoops!!!\n"));
       
   364     }
       
   365   test(x==1);
       
   366 }
       
   367 
       
   368 
       
   369 #endif
       
   370 
       
   371 
       
   372 
       
   373 
       
   374 
       
   375 
       
   376