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