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
6#ifndef _BINDERMODULE_H_
7#define _BINDERMODULE_H_
8
9class DataImage;
10class Module;
11class MethodTable;
12class MethodDesc;
13class FieldDesc;
14
15typedef const struct HardCodedMetaSig *LPHARDCODEDMETASIG;
16
17// As hard-coded metasigs are constant data ordinarily it
18// wouldn't be necessary to use PTR access. However, access
19// through the Binder class requires it.
20typedef DPTR(const struct HardCodedMetaSig) PTR_HARDCODEDMETASIG;
21
22struct HardCodedMetaSig
23{
24 const BYTE* m_pMetaSig; // metasig prefixed with INT8 length:
25 // length > 0 - resolved, lenght < 0 - has unresolved type references
26};
27
28#define DEFINE_METASIG(body) extern const body
29#define DEFINE_METASIG_T(body) extern body
30#define METASIG_BODY(varname, types) HardCodedMetaSig gsig_ ## varname;
31#include "metasig.h"
32
33//
34// Use the Binder objects to avoid doing unnecessary name lookup
35// (esp. in the prejit case)
36//
37// E.g. MscorlibBinder::GetClass(CLASS__APP_DOMAIN);
38//
39
40// BinderClassIDs are of the form CLASS__XXX
41
42enum BinderClassID
43{
44#define TYPEINFO(e,ns,c,s,g,ia,ip,if,im,gv) CLASS__ ## e,
45#include "cortypeinfo.h"
46#undef TYPEINFO
47
48#define DEFINE_CLASS(i,n,s) CLASS__ ## i,
49#include "mscorlib.h"
50
51 CLASS__MSCORLIB_COUNT,
52
53 // Aliases for element type classids
54 CLASS__NIL = CLASS__ELEMENT_TYPE_END,
55 CLASS__VOID = CLASS__ELEMENT_TYPE_VOID,
56 CLASS__BOOLEAN = CLASS__ELEMENT_TYPE_BOOLEAN,
57 CLASS__CHAR = CLASS__ELEMENT_TYPE_CHAR,
58 CLASS__BYTE = CLASS__ELEMENT_TYPE_U1,
59 CLASS__SBYTE = CLASS__ELEMENT_TYPE_I1,
60 CLASS__INT16 = CLASS__ELEMENT_TYPE_I2,
61 CLASS__UINT16 = CLASS__ELEMENT_TYPE_U2,
62 CLASS__INT32 = CLASS__ELEMENT_TYPE_I4,
63 CLASS__UINT32 = CLASS__ELEMENT_TYPE_U4,
64 CLASS__INT64 = CLASS__ELEMENT_TYPE_I8,
65 CLASS__UINT64 = CLASS__ELEMENT_TYPE_U8,
66 CLASS__SINGLE = CLASS__ELEMENT_TYPE_R4,
67 CLASS__DOUBLE = CLASS__ELEMENT_TYPE_R8,
68 CLASS__STRING = CLASS__ELEMENT_TYPE_STRING,
69 CLASS__TYPED_REFERENCE = CLASS__ELEMENT_TYPE_TYPEDBYREF,
70 CLASS__INTPTR = CLASS__ELEMENT_TYPE_I,
71 CLASS__UINTPTR = CLASS__ELEMENT_TYPE_U,
72 CLASS__OBJECT = CLASS__ELEMENT_TYPE_OBJECT
73};
74
75
76// BinderMethodIDs are of the form METHOD__XXX__YYY,
77// where X is the class and Y is the method
78
79enum BinderMethodID : int
80{
81 METHOD__NIL = 0,
82
83#define DEFINE_METHOD(c,i,s,g) METHOD__ ## c ## __ ## i,
84#include "mscorlib.h"
85
86 METHOD__MSCORLIB_COUNT,
87};
88
89// BinderFieldIDs are of the form FIELD__XXX__YYY,
90// where X is the class and Y is the field
91
92enum BinderFieldID
93{
94 FIELD__NIL = 0,
95
96#define DEFINE_FIELD(c,i,s) FIELD__ ## c ## __ ## i,
97#include "mscorlib.h"
98
99 FIELD__MSCORLIB_COUNT,
100};
101
102struct MscorlibClassDescription
103{
104 PTR_CSTR nameSpace;
105 PTR_CSTR name;
106};
107
108struct MscorlibMethodDescription
109{
110 BinderClassID classID;
111 PTR_CSTR name;
112 PTR_HARDCODEDMETASIG sig;
113};
114
115struct MscorlibFieldDescription
116{
117 BinderClassID classID;
118 PTR_CSTR name;
119};
120
121class MscorlibBinder
122{
123 public:
124#ifdef DACCESS_COMPILE
125 friend class NativeImageDumper;
126#endif
127
128 //
129 // Note that the frequently called methods are intentionally static to reduce code bloat.
130 // Instance methods would push the address of the global object at every callsite.
131 //
132
133 static PTR_Module GetModule();
134
135 //
136 // Retrieve structures from ID.
137 //
138 // Note that none of the MscorlibBinder methods trigger static
139 // constructors. The JITed code takes care of triggering them.
140 //
141 static PTR_MethodTable GetClass(BinderClassID id);
142 static MethodDesc * GetMethod(BinderMethodID id);
143 static FieldDesc * GetField(BinderFieldID id);
144
145 //
146 // A slighly faster version that assumes that the class was fetched
147 // by the binder earlier.
148 //
149 static PTR_MethodTable GetExistingClass(BinderClassID id);
150 static MethodDesc * GetExistingMethod(BinderMethodID id);
151 static FieldDesc * GetExistingField(BinderFieldID id);
152
153 //
154 // Utilities for classes
155 //
156 static FORCEINLINE BOOL IsClass(MethodTable *pMT, BinderClassID id)
157 {
158 return dac_cast<TADDR>(GetClass(id)) == dac_cast<TADDR>(pMT);
159 }
160
161 // Get the class only if it has been loaded already
162 static PTR_MethodTable GetClassIfExist(BinderClassID id);
163
164 static LPCUTF8 GetClassNameSpace(BinderClassID id);
165 static LPCUTF8 GetClassName(BinderClassID id);
166
167 //
168 // Utilities for methods
169 //
170 static LPCUTF8 GetMethodName(BinderMethodID id);
171 static LPHARDCODEDMETASIG GetMethodSig(BinderMethodID id);
172
173 static Signature GetMethodSignature(BinderMethodID id)
174 {
175 WRAPPER_NO_CONTRACT;
176 return GetSignature(GetMethodSig(id));
177 }
178
179 //
180 // Utilities for fields
181 //
182 static LPCUTF8 GetFieldName(BinderFieldID id);
183
184 static DWORD GetFieldOffset(BinderFieldID id);
185
186 //
187 // Utilities for exceptions
188 //
189
190 static MethodTable *GetException(RuntimeExceptionKind kind)
191 {
192 WRAPPER_NO_CONTRACT;
193 _ASSERTE(kind <= kLastExceptionInMscorlib); // Not supported for exceptions defined outside mscorlib.
194 BinderClassID id = (BinderClassID) (kind + CLASS__MSCORLIB_COUNT);
195 return GetClass(id);
196 }
197
198 static BOOL IsException(MethodTable *pMT, RuntimeExceptionKind kind)
199 {
200 WRAPPER_NO_CONTRACT;
201 _ASSERTE(kind <= kLastExceptionInMscorlib); // Not supported for exceptions defined outside mscorlib.
202 BinderClassID id = (BinderClassID) (kind + CLASS__MSCORLIB_COUNT);
203 return dac_cast<TADDR>(GetClassIfExist(id)) == dac_cast<TADDR>(pMT);
204 }
205
206 static LPCUTF8 GetExceptionName(RuntimeExceptionKind kind)
207 {
208 WRAPPER_NO_CONTRACT;
209 _ASSERTE(kind <= kLastExceptionInMscorlib); // Not supported for exceptions defined outside mscorlib.
210 BinderClassID id = (BinderClassID) (kind + CLASS__MSCORLIB_COUNT);
211 return GetClassName(id);
212 }
213
214 //
215 // Utilities for signature element types
216 //
217
218 static PTR_MethodTable GetElementType(CorElementType type)
219 {
220 LIMITED_METHOD_DAC_CONTRACT;
221 return GetExistingClass((BinderClassID) (type));
222 }
223
224 // This should be called during CLR initialization only
225 static PTR_MethodTable LoadPrimitiveType(CorElementType et);
226
227 // Get the metasig, do a one-time conversion if necessary
228 static Signature GetSignature(LPHARDCODEDMETASIG pHardcodedSig);
229 static Signature GetTargetSignature(LPHARDCODEDMETASIG pHardcodedSig);
230
231 //
232 // Static initialization
233 //
234 static void Startup();
235
236 //
237 // These are called by initialization code:
238 //
239 static void AttachModule(Module *pModule);
240
241#ifdef FEATURE_PREJIT
242 //
243 // Store the binding arrays to a prejit image
244 // so we don't have to do name lookup at runtime
245 //
246 void BindAll();
247 void Save(DataImage *image);
248 void Fixup(DataImage *image);
249#endif
250
251#ifdef _DEBUG
252 void Check();
253 void CheckExtended();
254#endif
255
256#ifdef DACCESS_COMPILE
257 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
258#endif
259
260private:
261
262 // We have two different instances of the binder in crossgen. The instance local methods
263 // are used when it is necessary to differentiate between them.
264 PTR_MethodTable LookupClassLocal(BinderClassID id);
265 MethodDesc * LookupMethodLocal(BinderMethodID id);
266 FieldDesc * LookupFieldLocal(BinderFieldID id);
267
268 PTR_MethodTable GetClassLocal(BinderClassID id);
269 MethodDesc * GetMethodLocal(BinderMethodID id);
270 FieldDesc * GetFieldLocal(BinderFieldID id);
271
272 static PTR_MethodTable LookupClass(BinderClassID id);
273 static MethodDesc * LookupMethod(BinderMethodID id);
274 static FieldDesc * LookupField(BinderFieldID id);
275
276 static PTR_MethodTable LookupClassIfExist(BinderClassID id);
277
278 Signature GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig);
279
280 bool ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder);
281 void BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSigBuilder);
282 const BYTE* ConvertSignature(LPHARDCODEDMETASIG pHardcodedSig, const BYTE* pSig);
283
284 void SetDescriptions(Module * pModule,
285 const MscorlibClassDescription * pClassDescriptions, USHORT nClasses,
286 const MscorlibMethodDescription * pMethodDescriptions, USHORT nMethods,
287 const MscorlibFieldDescription * pFieldDescriptions, USHORT nFields);
288
289 void AllocateTables();
290
291#ifdef _DEBUG
292 static void TriggerGCUnderStress();
293#endif
294
295 PTR_Module m_pModule;
296
297 DPTR(PTR_MethodTable) m_pClasses;
298 DPTR(PTR_MethodDesc) m_pMethods;
299 DPTR(PTR_FieldDesc) m_pFields;
300
301 // This is necessary to avoid embeding copy of the descriptions into mscordacwks
302 DPTR(const MscorlibClassDescription) m_classDescriptions;
303 DPTR(const MscorlibMethodDescription) m_methodDescriptions;
304 DPTR(const MscorlibFieldDescription) m_fieldDescriptions;
305
306 USHORT m_cClasses;
307 USHORT m_cMethods;
308 USHORT m_cFields;
309
310 static CrstStatic s_SigConvertCrst;
311
312#ifdef _DEBUG
313
314 struct OffsetAndSizeCheck
315 {
316 PTR_CSTR classNameSpace;
317 PTR_CSTR className;
318 SIZE_T expectedClassSize;
319
320 PTR_CSTR fieldName;
321 SIZE_T expectedFieldOffset;
322 SIZE_T expectedFieldSize;
323 };
324
325 static const OffsetAndSizeCheck OffsetsAndSizes[];
326
327#endif
328};
329
330//
331// Global bound modules:
332//
333
334GVAL_DECL(MscorlibBinder, g_Mscorlib);
335
336FORCEINLINE PTR_MethodTable MscorlibBinder::GetClass(BinderClassID id)
337{
338 CONTRACTL
339 {
340 THROWS;
341 GC_TRIGGERS;
342 INJECT_FAULT(ThrowOutOfMemory());
343
344 PRECONDITION(id != CLASS__NIL);
345 PRECONDITION((&g_Mscorlib)->m_cClasses > 0); // Make sure mscorlib has been loaded.
346 PRECONDITION(id <= (&g_Mscorlib)->m_cClasses);
347 }
348 CONTRACTL_END;
349
350 // Force a GC here under stress because type loading could trigger GC nondeterminsticly
351 INDEBUG(TriggerGCUnderStress());
352
353 PTR_MethodTable pMT = VolatileLoad(&((&g_Mscorlib)->m_pClasses[id]));
354 if (pMT == NULL)
355 return LookupClass(id);
356 return pMT;
357}
358
359FORCEINLINE MethodDesc * MscorlibBinder::GetMethod(BinderMethodID id)
360{
361 CONTRACTL
362 {
363 THROWS;
364 GC_TRIGGERS;
365 INJECT_FAULT(ThrowOutOfMemory());
366
367 PRECONDITION(id != METHOD__NIL);
368 PRECONDITION(id <= (&g_Mscorlib)->m_cMethods);
369 }
370 CONTRACTL_END;
371
372 // Force a GC here under stress because type loading could trigger GC nondeterminsticly
373 INDEBUG(TriggerGCUnderStress());
374
375 MethodDesc * pMD = VolatileLoad(&((&g_Mscorlib)->m_pMethods[id]));
376 if (pMD == NULL)
377 return LookupMethod(id);
378 return pMD;
379}
380
381FORCEINLINE FieldDesc * MscorlibBinder::GetField(BinderFieldID id)
382{
383 CONTRACTL
384 {
385 THROWS;
386 GC_TRIGGERS;
387 INJECT_FAULT(ThrowOutOfMemory());
388
389 PRECONDITION(id != FIELD__NIL);
390 PRECONDITION(id <= (&g_Mscorlib)->m_cFields);
391 }
392 CONTRACTL_END;
393
394 // Force a GC here under stress because type loading could trigger GC nondeterminsticly
395 INDEBUG(TriggerGCUnderStress());
396
397 FieldDesc * pFD = VolatileLoad(&((&g_Mscorlib)->m_pFields[id]));
398 if (pFD == NULL)
399 return LookupField(id);
400 return pFD;
401}
402
403FORCEINLINE PTR_MethodTable MscorlibBinder::GetExistingClass(BinderClassID id)
404{
405 LIMITED_METHOD_DAC_CONTRACT;
406 PTR_MethodTable pMT = (&g_Mscorlib)->m_pClasses[id];
407 _ASSERTE(pMT != NULL);
408 return pMT;
409}
410
411FORCEINLINE MethodDesc * MscorlibBinder::GetExistingMethod(BinderMethodID id)
412{
413 LIMITED_METHOD_DAC_CONTRACT;
414 MethodDesc * pMD = (&g_Mscorlib)->m_pMethods[id];
415 _ASSERTE(pMD != NULL);
416 return pMD;
417}
418
419FORCEINLINE FieldDesc * MscorlibBinder::GetExistingField(BinderFieldID id)
420{
421 LIMITED_METHOD_DAC_CONTRACT;
422 FieldDesc * pFD = (&g_Mscorlib)->m_pFields[id];
423 _ASSERTE(pFD != NULL);
424 return pFD;
425}
426
427FORCEINLINE PTR_MethodTable MscorlibBinder::GetClassIfExist(BinderClassID id)
428{
429 CONTRACTL
430 {
431 GC_NOTRIGGER;
432 NOTHROW;
433 FORBID_FAULT;
434 MODE_ANY;
435
436 PRECONDITION(id != CLASS__NIL);
437 PRECONDITION(id <= (&g_Mscorlib)->m_cClasses);
438 }
439 CONTRACTL_END;
440
441 PTR_MethodTable pMT = VolatileLoad(&((&g_Mscorlib)->m_pClasses[id]));
442 if (pMT == NULL)
443 return LookupClassIfExist(id);
444 return pMT;
445}
446
447
448FORCEINLINE PTR_Module MscorlibBinder::GetModule()
449{
450 LIMITED_METHOD_DAC_CONTRACT;
451 PTR_Module pModule = (&g_Mscorlib)->m_pModule;
452 _ASSERTE(pModule != NULL);
453 return pModule;
454}
455
456FORCEINLINE LPCUTF8 MscorlibBinder::GetClassNameSpace(BinderClassID id)
457{
458 LIMITED_METHOD_CONTRACT;
459
460 _ASSERTE(id != CLASS__NIL);
461 _ASSERTE(id <= (&g_Mscorlib)->m_cClasses);
462 return (&g_Mscorlib)->m_classDescriptions[id].nameSpace;
463}
464
465FORCEINLINE LPCUTF8 MscorlibBinder::GetClassName(BinderClassID id)
466{
467 LIMITED_METHOD_CONTRACT;
468
469 _ASSERTE(id != CLASS__NIL);
470 _ASSERTE(id <= (&g_Mscorlib)->m_cClasses);
471 return (&g_Mscorlib)->m_classDescriptions[id].name;
472}
473
474FORCEINLINE LPCUTF8 MscorlibBinder::GetMethodName(BinderMethodID id)
475{
476 LIMITED_METHOD_CONTRACT;
477
478 _ASSERTE(id != METHOD__NIL);
479 _ASSERTE(id <= (&g_Mscorlib)->m_cMethods);
480 return (&g_Mscorlib)->m_methodDescriptions[id-1].name;
481}
482
483FORCEINLINE LPHARDCODEDMETASIG MscorlibBinder::GetMethodSig(BinderMethodID id)
484{
485 LIMITED_METHOD_CONTRACT;
486
487 _ASSERTE(id != METHOD__NIL);
488 _ASSERTE(id <= (&g_Mscorlib)->m_cMethods);
489 return (&g_Mscorlib)->m_methodDescriptions[id-1].sig;
490}
491
492FORCEINLINE LPCUTF8 MscorlibBinder::GetFieldName(BinderFieldID id)
493{
494 LIMITED_METHOD_CONTRACT;
495
496 _ASSERTE(id != FIELD__NIL);
497 _ASSERTE(id <= (&g_Mscorlib)->m_cFields);
498 return (&g_Mscorlib)->m_fieldDescriptions[id-1].name;
499}
500
501#endif // _BINDERMODULE_H_
502