kernel/eka/compsupp/symaehabi/symbian_rtti.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 "ARM EABI LICENCE.txt"
       
     5 // which accompanies this distribution, and is available
       
     6 // in kernel/eka/compsupp.
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32/compsupp/symaehabi/symbian_rtti.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "cxxabi.h"
       
    19 #include "unwind_env.h"
       
    20 #include "unwinder.h"
       
    21 #include "symbian_support.h"
       
    22 
       
    23 // For information about these classes, se
       
    24 // www.codesourcery.com/public/cxx-abi/abi.html#rtti. 
       
    25 using abi::__class_type_info;
       
    26 using abi::__si_class_type_info;
       
    27 using abi::__vmi_class_type_info;
       
    28 using abi::__base_class_type_info;
       
    29 
       
    30 
       
    31 // Given base class info (aBaseInfo) and a derived object pointer (aDerivedObj),
       
    32 // this function implements "cast to base" and stores result in aBaseObj. This
       
    33 // essentially sets aBaseObj to point to a memory location that represents
       
    34 // aDerivedObj as the given base class. This function requires that aBaseInfo
       
    35 // describes a base class of the aDerivedObj's class.
       
    36 static void _CastUp(const __base_class_type_info& aBaseInfo, TAny** aDerivedObj, TAny** aBaseObj)
       
    37 	{
       
    38 	// Guard against a null pointer for aDerivedObj
       
    39 	if ( ! (*aDerivedObj) ) 
       
    40 		{
       
    41 		*aBaseObj = NULL;
       
    42 		return;
       
    43 		}
       
    44 
       
    45 	TInt offset = aBaseInfo.__offset_flags >> aBaseInfo.__offset_shift;
       
    46 
       
    47 	if (aBaseInfo.__offset_flags & aBaseInfo.__virtual_mask)
       
    48 		{
       
    49 		// For virtual bases, look up offset in vtable + offset.
       
    50 
       
    51 		// Get vtbl pointer as the first 4 bytes of **aDerivedObj
       
    52 		TUint32* vptr = (TUint32*) ( *( (TUint32*) (*aDerivedObj) ) );
       
    53 
       
    54 		offset = *( vptr + offset / sizeof(TUint32) );
       
    55 		}
       
    56 
       
    57 	// Apply the offset.
       
    58 	*aBaseObj = (TAny*) ( ( (TUint8*) *aDerivedObj ) + offset );
       
    59 	}
       
    60 
       
    61 
       
    62 // For a description of this function, see comments in unwind_env.h.
       
    63 extern "C" TBool _DoDerivedToBaseConversion(const std::type_info* aDerivedType,
       
    64 		                                    const std::type_info* aBaseType,
       
    65 		                                    TAny**                aDerivedObj,
       
    66 		                                    TAny**                aBaseObj)
       
    67 	{
       
    68 
       
    69 	const std::type_info& type_base_type = typeid(*aBaseType);
       
    70 	const std::type_info& type_derived_type = typeid(*aDerivedType);
       
    71 
       
    72 	// We must proceed depending on the type of the type_info objects for derived
       
    73 	// class.  
       
    74 	if ( type_derived_type == typeid(__si_class_type_info) )
       
    75 		{
       
    76 		// The __si_class_type_info means that the derived type has a single,
       
    77 		// public, non-virtual base, and that the base is at offset zero. We should
       
    78 		// be able to simply compare the base type from __si_class_type_info with
       
    79 		// aBaseType
       
    80 
       
    81 		const __si_class_type_info* derived = (const __si_class_type_info*) aDerivedType;
       
    82 
       
    83 		if ( *(derived->__base_type) == *aBaseType ) 
       
    84 			{
       
    85 			// The types match, work done.
       
    86 			*aBaseObj = *aDerivedObj;
       
    87 			return true;
       
    88 			} 
       
    89 		else 
       
    90 			{
       
    91 			// The types don't match. We should proceed to comparison with the any
       
    92 			// classes. In this case there is a single base as follows:
       
    93 			const __class_type_info* bType = derived->__base_type;
       
    94 
       
    95 			// No pointer adjustment required for __si_class_type_info. 
       
    96 			return _DoDerivedToBaseConversion(bType, aBaseType, aDerivedObj, aBaseObj);
       
    97 			}
       
    98 		}
       
    99 	else if ( type_derived_type == typeid(__vmi_class_type_info) ) 
       
   100 		{
       
   101 		// The __vmi_class_type_info is for all other scenarios. We get an array of
       
   102 		// bases which we need to traverse and do comparison on.
       
   103 
       
   104 		const __vmi_class_type_info* derived = (const __vmi_class_type_info*)aDerivedType;
       
   105 
       
   106 		const unsigned count = derived->__base_count;
       
   107 
       
   108 		for ( unsigned i = 0; i < count; i++ ) 
       
   109 			{
       
   110 			// Get the base info for this base class
       
   111 			const __base_class_type_info bInfo = derived->__base_info[i];
       
   112 
       
   113 			if ( ! ( bInfo.__offset_flags & bInfo.__public_mask) )
       
   114 				{
       
   115 				// The base is non-public base, so the remainder of the hierarchy
       
   116 				// above this base is of no interest
       
   117 				continue;
       
   118 				} 
       
   119 
       
   120 			// Get the class type info for this base
       
   121 			const __class_type_info* bType = bInfo.__base_type;
       
   122 
       
   123 			// First check if the type from the list corresponds to requested base
       
   124 			// type.  
       
   125 			if ( (*bType) == (*aBaseType) ) 
       
   126 				{
       
   127 				// Match! Convert the pointer to point to the base.
       
   128 				_CastUp(bInfo, aDerivedObj, aBaseObj);
       
   129 				return true;
       
   130 				}
       
   131 
       
   132 			// No match, we must now recursively delve into superclasses of bType.
       
   133 			// To do that, we need to advance the derived class pointer to point to
       
   134 			// the current base class as in bInfo.
       
   135 			TAny* newDerivedPtr;
       
   136 			_CastUp(bInfo, aDerivedObj, &newDerivedPtr);
       
   137 
       
   138 			// Now go recursive, substituting aDerivedObj with adjusted pointer and bType instead of aDerivedType 
       
   139 			TBool result = _DoDerivedToBaseConversion(bType, aBaseType, (TAny**)(&newDerivedPtr), aBaseObj);
       
   140 
       
   141 			// Return only if the match is found, otherwise continue with the loop
       
   142 			if ( result ) 
       
   143 				{
       
   144 				// Match came back from recursion, pass up.
       
   145 				return true;
       
   146 				}
       
   147 
       
   148 			// No match from recursion, advance to next base.
       
   149 			}
       
   150 		}
       
   151 	else
       
   152 		{
       
   153 		// assert(0);
       
   154 		}
       
   155 
       
   156 	// No match was found for aBaseType in the aDerivedType's ancestry.
       
   157 	return false;
       
   158 	}
       
   159