1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // File: memberload.h |
6 | // |
7 | |
8 | |
9 | // |
10 | |
11 | // |
12 | // ============================================================================ |
13 | |
14 | #ifndef _MEMBERLOAD_H |
15 | #define _MEMBERLOAD_H |
16 | |
17 | |
18 | /* |
19 | * Include Files |
20 | */ |
21 | #include "eecontract.h" |
22 | #include "argslot.h" |
23 | #include "vars.hpp" |
24 | #include "cor.h" |
25 | #include "clrex.h" |
26 | #include "hash.h" |
27 | #include "crst.h" |
28 | #include "declsec.h" |
29 | #include "slist.h" |
30 | #include "typehandle.h" |
31 | #include "methodtable.h" |
32 | #include "typectxt.h" |
33 | |
34 | // |
35 | // This enum represents the property methods that can be passed to FindPropertyMethod(). |
36 | // |
37 | |
38 | enum EnumPropertyMethods |
39 | { |
40 | PropertyGet = 0, |
41 | PropertySet = 1, |
42 | }; |
43 | |
44 | |
45 | // |
46 | // This enum represents the event methods that can be passed to FindEventMethod(). |
47 | // |
48 | |
49 | enum EnumEventMethods |
50 | { |
51 | EventAdd = 0, |
52 | EventRemove = 1, |
53 | EventRaise = 2, |
54 | }; |
55 | |
56 | // The MemberLoader logic is analogous to the ClassLoader logic, i.e. it turn |
57 | // tokens into internal EE descriptors. |
58 | // |
59 | // The implementations of these functions currently lies in class.cpp. |
60 | class MemberLoader |
61 | { |
62 | |
63 | |
64 | public: |
65 | static void DECLSPEC_NORETURN ThrowMissingMethodException(MethodTable* pMT, |
66 | LPCSTR szMember, |
67 | Module *pModule, |
68 | PCCOR_SIGNATURE pSig, |
69 | DWORD cSig, |
70 | const SigTypeContext *pTypeContext); |
71 | |
72 | static void DECLSPEC_NORETURN ThrowMissingFieldException( MethodTable *pMT, |
73 | LPCSTR szMember); |
74 | |
75 | static MethodDesc* GetMethodDescFromMemberDefOrRefOrSpec(Module *pModule, |
76 | mdToken MemberRefOrDefOrSpec, |
77 | const SigTypeContext *pTypeContext, // Context for type parameters in any parent TypeSpec and in the instantiation in a MethodSpec |
78 | BOOL strictMetadataChecks, // Normally true - the zapper is one exception. Throw an exception if no generic method args given for a generic method, otherwise return the 'generic' instantiation |
79 | BOOL allowInstParam); |
80 | |
81 | static FieldDesc* GetFieldDescFromMemberDefOrRef(Module *pModule, |
82 | mdMemberRef MemberDefOrRef, |
83 | const SigTypeContext *pTypeContext, |
84 | BOOL strictMetadataChecks); |
85 | |
86 | static MethodDesc *GetMethodDescFromMethodDef(Module *pModule, |
87 | mdMethodDef MethodDef, // MethodDef token |
88 | Instantiation classInst, // Generic arguments for declaring class |
89 | Instantiation methodInst, // Generic arguments for declaring method |
90 | BOOL forceRemotable = FALSE); // force remotable MethodDesc |
91 | // |
92 | // Methods that actually do the work |
93 | // |
94 | |
95 | static MethodDesc* GetMethodDescFromMethodDef(Module *pModule, |
96 | mdToken MethodDef, |
97 | BOOL strictMetadataChecks); |
98 | |
99 | static FieldDesc* GetFieldDescFromFieldDef(Module *pModule, |
100 | mdToken FieldDef, |
101 | BOOL strictMetadataChecks); |
102 | |
103 | static void GetDescFromMemberRef(Module * pModule, |
104 | mdToken MemberRef, |
105 | MethodDesc ** ppMD, |
106 | FieldDesc ** ppFD, |
107 | const SigTypeContext *pTypeContext, |
108 | BOOL strictMetadataChecks, |
109 | TypeHandle *ppTH, |
110 | // Because of inheritance, the actual type stored in metadata may be sub-class of the |
111 | // class that defines the member. The semantics (verification, security checks, etc.) is based on |
112 | // the actual type in metadata. This JIT-EE interface passes in TRUE here to get the actual type. |
113 | // If actualTypeRequired is false, returned *ppTH will be the MethodDesc::GetMethodTable/FieldDesc::GetEnclosingMethodTable |
114 | // except when generics are involved. The actual type will be still returned for generics since it is required |
115 | // for instantiation. |
116 | // If actualTypeRequired is true, returned *ppTH will always be the actual type defined in metadata. |
117 | BOOL actualTypeRequired = FALSE, |
118 | PCCOR_SIGNATURE * ppTypeSig = NULL, // Optionally, return generic signatures fetched from metadata during loading. |
119 | ULONG * pcbTypeSig = NULL); |
120 | |
121 | static MethodDesc * GetMethodDescFromMemberRefAndType(Module * pModule, |
122 | mdToken MemberRef, |
123 | MethodTable * pMT); |
124 | |
125 | static FieldDesc * GetFieldDescFromMemberRefAndType(Module * pModule, |
126 | mdToken MemberRef, |
127 | MethodTable * pMT); |
128 | |
129 | static MethodDesc * GetMethodDescFromMethodSpec(Module * pModule, |
130 | mdToken MethodSpec, |
131 | const SigTypeContext *pTypeContext, |
132 | BOOL strictMetadataChecks, |
133 | BOOL allowInstParam, |
134 | TypeHandle *ppTH, |
135 | BOOL actualTypeRequired = FALSE, // See comment for GetDescFromMemberRef |
136 | PCCOR_SIGNATURE * ppTypeSig = NULL, // Optionally, return generic signatures fetched from metadata during loading. |
137 | ULONG * pcbTypeSig = NULL, |
138 | PCCOR_SIGNATURE * ppMethodSig = NULL, |
139 | ULONG * pcbMethodSig = NULL); |
140 | |
141 | //------------------------------------------------------------------- |
142 | // METHOD AND FIELD LOOKUP BY NAME AND SIGNATURE |
143 | // |
144 | |
145 | // Used by FindMethod and varieties |
146 | enum FM_Flags |
147 | { |
148 | // Default behaviour is to scan all methods, virtual and non-virtual, of the current type |
149 | // and all non-virtual methods of all parent types. |
150 | |
151 | // Default set of flags - this must always be zero. |
152 | FM_Default = 0x0000, |
153 | |
154 | // Case sensitivity |
155 | FM_IgnoreCase = 0x0001, // Name matching is case insensitive |
156 | FM_IgnoreName = (FM_IgnoreCase << 1), // Ignore the name altogether |
157 | |
158 | // USE THE FOLLOWING WITH EXTREME CAUTION. We do not want to inadvertently |
159 | // change binding semantics by using this without a really good reason. |
160 | |
161 | // Virtuals |
162 | FM_ExcludeNonVirtual = (FM_IgnoreName << 1), // has mdVirtual set |
163 | FM_ExcludeVirtual = (FM_ExcludeNonVirtual << 1), // does not have mdVirtual set. |
164 | |
165 | // Accessibility. |
166 | // NOTE: These appear in the exact same order as mdPrivateScope ... mdPublic in corhdr.h. This enables some |
167 | // bit masking to quickly determine if a method qualifies in FM_ShouldSkipMethod. |
168 | FM_ExcludePrivateScope = (FM_ExcludeVirtual << 1), // Member not referenceable. |
169 | FM_ExcludePrivate = (FM_ExcludePrivateScope << 1), // Accessible only by the parent type. |
170 | FM_ExcludeFamANDAssem = (FM_ExcludePrivate << 1), // Accessible by sub-types only in this Assembly. |
171 | FM_ExcludeAssem = (FM_ExcludeFamANDAssem << 1), // Accessibly by anyone in the Assembly. |
172 | FM_ExcludeFamily = (FM_ExcludeAssem << 1), // Accessible only by type and sub-types. |
173 | FM_ExcludeFamORAssem = (FM_ExcludeFamily << 1), // Accessibly by sub-types anywhere, plus anyone in assembly. |
174 | FM_ExcludePublic = (FM_ExcludeFamORAssem << 1), // Accessibly by anyone who has visibility to this scope. |
175 | FM_Unique = (FM_ExcludePublic << 1), // Make sure the method is unique for the class |
176 | |
177 | // This means that FindMethod will only consider mdPublic mdVirtual methods. |
178 | // This is the only time when name/sig lookup will look past the first match. |
179 | FM_ForInterface = (FM_ExcludeNonVirtual | |
180 | FM_ExcludePrivateScope | |
181 | FM_ExcludePrivate | |
182 | FM_ExcludeFamANDAssem | |
183 | FM_ExcludeAssem | |
184 | FM_ExcludeFamily | |
185 | FM_ExcludeFamORAssem), |
186 | }; |
187 | |
188 | private: |
189 | // A mask to indicate that some filtering needs to be done. |
190 | static const FM_Flags FM_SpecialAccessMask = (FM_Flags) (FM_ExcludePrivateScope | |
191 | FM_ExcludePrivate | |
192 | FM_ExcludeFamANDAssem | |
193 | FM_ExcludeAssem | |
194 | FM_ExcludeFamily | |
195 | FM_ExcludeFamORAssem | |
196 | FM_ExcludePublic); |
197 | |
198 | static const FM_Flags FM_SpecialVirtualMask = (FM_Flags) (FM_ExcludeNonVirtual | |
199 | FM_ExcludeVirtual); |
200 | |
201 | // Typedef for string comparition functions. |
202 | typedef int (__cdecl *UTF8StringCompareFuncPtr)(const char *, const char *); |
203 | |
204 | static inline UTF8StringCompareFuncPtr FM_GetStrCompFunc(DWORD dwFlags) |
205 | { LIMITED_METHOD_CONTRACT; return (dwFlags & FM_IgnoreCase) ? stricmpUTF8 : strcmp; } |
206 | |
207 | static BOOL FM_PossibleToSkipMethod(FM_Flags flags); |
208 | static BOOL FM_ShouldSkipMethod(DWORD dwAttrs, FM_Flags flags); |
209 | |
210 | public: |
211 | static MethodDesc *FindMethod( |
212 | MethodTable * pMT, |
213 | LPCUTF8 pwzName, |
214 | LPHARDCODEDMETASIG pwzSignature, |
215 | FM_Flags flags = FM_Default); |
216 | |
217 | // typeHnd is the type handle associated with the class being looked up. |
218 | // It has additional information in the case of a domain neutral class (Arrays) |
219 | static MethodDesc *FindMethod( |
220 | MethodTable * pMT, |
221 | LPCUTF8 pszName, |
222 | PCCOR_SIGNATURE pSignature, |
223 | DWORD cSignature, |
224 | Module* pModule, |
225 | FM_Flags flags = FM_Default, |
226 | const Substitution *pDefSubst = NULL); |
227 | |
228 | static MethodDesc *FindMethod(MethodTable * pMT, mdMethodDef mb); |
229 | |
230 | static MethodDesc *FindMethodByName( |
231 | MethodTable * pMT, |
232 | LPCUTF8 pszName, |
233 | FM_Flags flags = FM_Default); |
234 | |
235 | static MethodDesc *FindPropertyMethod( |
236 | MethodTable * pMT, |
237 | LPCUTF8 pszName, |
238 | EnumPropertyMethods Method, |
239 | FM_Flags flags = FM_Default); |
240 | |
241 | static MethodDesc *FindEventMethod( |
242 | MethodTable * pMT, |
243 | LPCUTF8 pszName, |
244 | EnumEventMethods Method, |
245 | FM_Flags flags = FM_Default); |
246 | |
247 | static MethodDesc *FindMethodForInterfaceSlot( |
248 | MethodTable * pMT, |
249 | MethodTable *pInterface, |
250 | WORD slotNum); |
251 | |
252 | // pSignature can be NULL to find any field with the given name |
253 | static FieldDesc *FindField( |
254 | MethodTable * pMT, |
255 | LPCUTF8 pszName, |
256 | PCCOR_SIGNATURE pSignature, |
257 | DWORD cSignature, |
258 | Module* pModule, |
259 | BOOL bCaseSensitive = TRUE); |
260 | |
261 | static MethodDesc *FindConstructor(MethodTable * pMT, LPHARDCODEDMETASIG pwzSignature); |
262 | static MethodDesc *FindConstructor(MethodTable * pMT, PCCOR_SIGNATURE pSignature,DWORD cSignature, Module* pModule); |
263 | }; |
264 | |
265 | #endif // MEMBERLOAD_H |
266 | |