os/kernelhwsrv/kernel/eka/compsupp/symaehabi/symbian_rtti.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/compsupp/symaehabi/symbian_rtti.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,159 @@
     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_rtti.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "cxxabi.h"
    1.22 +#include "unwind_env.h"
    1.23 +#include "unwinder.h"
    1.24 +#include "symbian_support.h"
    1.25 +
    1.26 +// For information about these classes, se
    1.27 +// www.codesourcery.com/public/cxx-abi/abi.html#rtti. 
    1.28 +using abi::__class_type_info;
    1.29 +using abi::__si_class_type_info;
    1.30 +using abi::__vmi_class_type_info;
    1.31 +using abi::__base_class_type_info;
    1.32 +
    1.33 +
    1.34 +// Given base class info (aBaseInfo) and a derived object pointer (aDerivedObj),
    1.35 +// this function implements "cast to base" and stores result in aBaseObj. This
    1.36 +// essentially sets aBaseObj to point to a memory location that represents
    1.37 +// aDerivedObj as the given base class. This function requires that aBaseInfo
    1.38 +// describes a base class of the aDerivedObj's class.
    1.39 +static void _CastUp(const __base_class_type_info& aBaseInfo, TAny** aDerivedObj, TAny** aBaseObj)
    1.40 +	{
    1.41 +	// Guard against a null pointer for aDerivedObj
    1.42 +	if ( ! (*aDerivedObj) ) 
    1.43 +		{
    1.44 +		*aBaseObj = NULL;
    1.45 +		return;
    1.46 +		}
    1.47 +
    1.48 +	TInt offset = aBaseInfo.__offset_flags >> aBaseInfo.__offset_shift;
    1.49 +
    1.50 +	if (aBaseInfo.__offset_flags & aBaseInfo.__virtual_mask)
    1.51 +		{
    1.52 +		// For virtual bases, look up offset in vtable + offset.
    1.53 +
    1.54 +		// Get vtbl pointer as the first 4 bytes of **aDerivedObj
    1.55 +		TUint32* vptr = (TUint32*) ( *( (TUint32*) (*aDerivedObj) ) );
    1.56 +
    1.57 +		offset = *( vptr + offset / sizeof(TUint32) );
    1.58 +		}
    1.59 +
    1.60 +	// Apply the offset.
    1.61 +	*aBaseObj = (TAny*) ( ( (TUint8*) *aDerivedObj ) + offset );
    1.62 +	}
    1.63 +
    1.64 +
    1.65 +// For a description of this function, see comments in unwind_env.h.
    1.66 +extern "C" TBool _DoDerivedToBaseConversion(const std::type_info* aDerivedType,
    1.67 +		                                    const std::type_info* aBaseType,
    1.68 +		                                    TAny**                aDerivedObj,
    1.69 +		                                    TAny**                aBaseObj)
    1.70 +	{
    1.71 +
    1.72 +	const std::type_info& type_base_type = typeid(*aBaseType);
    1.73 +	const std::type_info& type_derived_type = typeid(*aDerivedType);
    1.74 +
    1.75 +	// We must proceed depending on the type of the type_info objects for derived
    1.76 +	// class.  
    1.77 +	if ( type_derived_type == typeid(__si_class_type_info) )
    1.78 +		{
    1.79 +		// The __si_class_type_info means that the derived type has a single,
    1.80 +		// public, non-virtual base, and that the base is at offset zero. We should
    1.81 +		// be able to simply compare the base type from __si_class_type_info with
    1.82 +		// aBaseType
    1.83 +
    1.84 +		const __si_class_type_info* derived = (const __si_class_type_info*) aDerivedType;
    1.85 +
    1.86 +		if ( *(derived->__base_type) == *aBaseType ) 
    1.87 +			{
    1.88 +			// The types match, work done.
    1.89 +			*aBaseObj = *aDerivedObj;
    1.90 +			return true;
    1.91 +			} 
    1.92 +		else 
    1.93 +			{
    1.94 +			// The types don't match. We should proceed to comparison with the any
    1.95 +			// classes. In this case there is a single base as follows:
    1.96 +			const __class_type_info* bType = derived->__base_type;
    1.97 +
    1.98 +			// No pointer adjustment required for __si_class_type_info. 
    1.99 +			return _DoDerivedToBaseConversion(bType, aBaseType, aDerivedObj, aBaseObj);
   1.100 +			}
   1.101 +		}
   1.102 +	else if ( type_derived_type == typeid(__vmi_class_type_info) ) 
   1.103 +		{
   1.104 +		// The __vmi_class_type_info is for all other scenarios. We get an array of
   1.105 +		// bases which we need to traverse and do comparison on.
   1.106 +
   1.107 +		const __vmi_class_type_info* derived = (const __vmi_class_type_info*)aDerivedType;
   1.108 +
   1.109 +		const unsigned count = derived->__base_count;
   1.110 +
   1.111 +		for ( unsigned i = 0; i < count; i++ ) 
   1.112 +			{
   1.113 +			// Get the base info for this base class
   1.114 +			const __base_class_type_info bInfo = derived->__base_info[i];
   1.115 +
   1.116 +			if ( ! ( bInfo.__offset_flags & bInfo.__public_mask) )
   1.117 +				{
   1.118 +				// The base is non-public base, so the remainder of the hierarchy
   1.119 +				// above this base is of no interest
   1.120 +				continue;
   1.121 +				} 
   1.122 +
   1.123 +			// Get the class type info for this base
   1.124 +			const __class_type_info* bType = bInfo.__base_type;
   1.125 +
   1.126 +			// First check if the type from the list corresponds to requested base
   1.127 +			// type.  
   1.128 +			if ( (*bType) == (*aBaseType) ) 
   1.129 +				{
   1.130 +				// Match! Convert the pointer to point to the base.
   1.131 +				_CastUp(bInfo, aDerivedObj, aBaseObj);
   1.132 +				return true;
   1.133 +				}
   1.134 +
   1.135 +			// No match, we must now recursively delve into superclasses of bType.
   1.136 +			// To do that, we need to advance the derived class pointer to point to
   1.137 +			// the current base class as in bInfo.
   1.138 +			TAny* newDerivedPtr;
   1.139 +			_CastUp(bInfo, aDerivedObj, &newDerivedPtr);
   1.140 +
   1.141 +			// Now go recursive, substituting aDerivedObj with adjusted pointer and bType instead of aDerivedType 
   1.142 +			TBool result = _DoDerivedToBaseConversion(bType, aBaseType, (TAny**)(&newDerivedPtr), aBaseObj);
   1.143 +
   1.144 +			// Return only if the match is found, otherwise continue with the loop
   1.145 +			if ( result ) 
   1.146 +				{
   1.147 +				// Match came back from recursion, pass up.
   1.148 +				return true;
   1.149 +				}
   1.150 +
   1.151 +			// No match from recursion, advance to next base.
   1.152 +			}
   1.153 +		}
   1.154 +	else
   1.155 +		{
   1.156 +		// assert(0);
   1.157 +		}
   1.158 +
   1.159 +	// No match was found for aBaseType in the aDerivedType's ancestry.
   1.160 +	return false;
   1.161 +	}
   1.162 +