0
|
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 |
|