os/kernelhwsrv/kerneltest/e32test/cppexceptions/t_romtable.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 "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