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