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// ZapImport.h
6//
7
8//
9// Import is soft bound references to elements outside the current module
10//
11// ======================================================================================
12
13#ifndef __ZAPIMPORT_H__
14#define __ZAPIMPORT_H__
15
16class ZapImportTable;
17class ZapGCRefMapTable;
18class NibbleWriter;
19
20//---------------------------------------------------------------------------------------
21//
22// ZapImport is the import cell itself
23//
24// Every import cell is uniquely identified by its ZapNodeType and two handles
25// (the second handle is optional and is often NULL)
26//
27// Actual implementations inherits from this abstract base class.
28//
29class ZapImport : public ZapNode
30{
31 COUNT_T m_index;
32 DWORD m_offset;
33
34 PVOID m_handle;
35 PVOID m_handle2;
36
37 ZapBlob * m_pBlob;
38
39public:
40 void SetHandle(PVOID handle)
41 {
42 _ASSERTE(m_handle == NULL);
43 m_handle = handle;
44 }
45
46 void SetHandle2(PVOID handle2)
47 {
48 _ASSERTE(m_handle2 == NULL);
49 m_handle2 = handle2;
50 }
51
52 PVOID GetHandle()
53 {
54 return m_handle;
55 }
56
57 PVOID GetHandle2()
58 {
59 return m_handle2;
60 }
61
62 void SetBlob(ZapBlob * pBlob)
63 {
64 _ASSERTE(m_pBlob == NULL);
65 m_pBlob = pBlob;
66 }
67
68 ZapBlob * GetBlob()
69 {
70 _ASSERTE(m_pBlob != NULL);
71 return m_pBlob;
72 }
73
74 BOOL HasBlob()
75 {
76 return m_pBlob != NULL;
77 }
78
79 virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
80 {
81 *pfIsEager = FALSE;
82 *pfNeedsSignature = TRUE;
83 return ZapImportSectionType_Handle;
84 }
85
86 // All subtypes have to override
87 virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) = 0;
88
89 virtual DWORD GetSize()
90 {
91 return TARGET_POINTER_SIZE;
92 }
93
94 virtual UINT GetAlignment()
95 {
96 return TARGET_POINTER_SIZE;
97 }
98
99 virtual void Save(ZapWriter * pZapWriter);
100
101 //
102 // Offset of the fixup cell within its section
103 //
104
105 void SetSectionIndexAndOffset(COUNT_T index, DWORD offset)
106 {
107 m_index = index;
108 m_offset = offset;
109 }
110
111 DWORD GetSectionIndex()
112 {
113 return m_index;
114 }
115
116 DWORD GetOffset()
117 {
118 return m_offset;
119 }
120};
121
122//---------------------------------------------------------------------------------------
123//
124// ZapGenericSignature is signature of generic dictionary entry.
125//
126class ZapGenericSignature : public ZapBlob
127{
128public:
129 ZapGenericSignature(SIZE_T cbSize)
130 : ZapBlob(cbSize)
131 {
132 }
133
134 virtual ZapNodeType GetType()
135 {
136 return ZapNodeType_GenericSignature;
137 }
138};
139
140//---------------------------------------------------------------------------------------
141//
142// ZapImportTable is the main class that keeps track of all ZapImports.
143//
144// There is a single instance of it per image.
145//
146class ZapImportTable
147{
148 //
149 // Hashtable key of the import
150 // The same key is used for both ZapImport and ZapImportBlob
151 //
152 struct ImportKey
153 {
154 FORCEINLINE ImportKey(PVOID handle, ZapNodeType type)
155 : m_handle(handle), m_handle2(NULL), m_type(type)
156 {
157 }
158
159 FORCEINLINE ImportKey(PVOID handle, PVOID handle2, ZapNodeType type)
160 : m_handle(handle), m_handle2(handle2), m_type(type)
161 {
162 }
163
164 PVOID m_handle;
165 PVOID m_handle2;
166 ZapNodeType m_type;
167 };
168
169 //
170 // Hashtable of ZapImports
171 //
172 class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapImport *> >
173 {
174 public:
175 typedef ImportKey key_t;
176
177 static FORCEINLINE key_t GetKey(element_t e)
178 {
179 LIMITED_METHOD_CONTRACT;
180 return ImportKey(e->GetHandle(), e->GetHandle2(), e->GetType());
181 }
182 static FORCEINLINE BOOL Equals(key_t k1, key_t k2)
183 {
184 LIMITED_METHOD_CONTRACT;
185 return (k1.m_handle == k2.m_handle) && (k1.m_handle2 == k2.m_handle2) && (k1.m_type == k2.m_type);
186 }
187 static FORCEINLINE count_t Hash(key_t k)
188 {
189 LIMITED_METHOD_CONTRACT;
190 return (count_t)(size_t)k.m_handle ^ ((count_t)(size_t)k.m_handle2 << 1) ^ k.m_type;
191 }
192
193 static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
194 static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
195 };
196
197 typedef SHash< ImportTraits > ImportTable;
198
199 //
200 // Hashtable of module indices
201 //
202 struct ModuleReferenceEntry
203 {
204 CORINFO_MODULE_HANDLE m_module;
205 DWORD m_index;
206 };
207
208 class ModuleReferenceTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ModuleReferenceEntry *> >
209 {
210 public:
211 typedef CORINFO_MODULE_HANDLE key_t;
212
213 static key_t GetKey(element_t e)
214 {
215 LIMITED_METHOD_CONTRACT;
216 return e->m_module;
217 }
218 static BOOL Equals(key_t k1, key_t k2)
219 {
220 LIMITED_METHOD_CONTRACT;
221 return (k1 == k2);
222 }
223 static count_t Hash(key_t k)
224 {
225 LIMITED_METHOD_CONTRACT;
226 return (count_t)(size_t)k;
227 }
228
229 static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
230 static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
231 };
232
233 typedef SHash< ModuleReferenceTraits > ModuleReferenceTable;
234
235 //
236 // Helpers for inserting actual implementations of ZapImports into hashtable
237 //
238 template < typename impl, ZapNodeType type >
239 ZapImport * GetImport(PVOID handle)
240 {
241 ZapImport * pImport = m_imports.Lookup(ImportKey(handle, type));
242
243 if (pImport != NULL)
244 {
245 return pImport;
246 }
247
248 pImport = new (m_pImage->GetHeap()) impl();
249 _ASSERTE(pImport->GetType() == type);
250 pImport->SetHandle(handle);
251 m_imports.Add(pImport);
252 return pImport;
253 }
254
255 template < typename impl, ZapNodeType type >
256 ZapImport * GetImport(PVOID handle, PVOID handle2)
257 {
258 ZapImport * pImport = m_imports.Lookup(ImportKey(handle, handle2, type));
259
260 if (pImport != NULL)
261 {
262 return pImport;
263 }
264
265 pImport = new (m_pImage->GetHeap()) impl();
266 _ASSERTE(pImport->GetType() == type);
267 pImport->SetHandle(handle);
268 pImport->SetHandle2(handle2);
269 m_imports.Add(pImport);
270 return pImport;
271 }
272
273 template < typename impl, ZapNodeType type >
274 ZapImport * GetImportForSignature(PVOID handle, SigBuilder * pSigBuilder)
275 {
276 ZapBlob * pBlob = GetBlob(pSigBuilder);
277
278 ZapImport * pImport = m_imports.Lookup(ImportKey(handle, pBlob, type));
279
280 if (pImport != NULL)
281 {
282 return pImport;
283 }
284
285 pImport = new (m_pImage->GetHeap()) impl();
286 _ASSERTE(pImport->GetType() == type);
287 pImport->SetHandle(handle);
288 pImport->SetHandle2(pBlob);
289 pImport->SetBlob(pBlob);
290 m_imports.Add(pImport);
291 return pImport;
292 }
293
294 ZapImport * GetExistingImport(ZapNodeType type, PVOID handle)
295 {
296 return m_imports.Lookup(ImportKey(handle, type));
297 }
298
299 ModuleReferenceEntry * GetModuleReference(CORINFO_MODULE_HANDLE handle);
300
301 static DWORD EncodeModuleHelper(LPVOID referencingModule, CORINFO_MODULE_HANDLE referencedModule);
302
303 ImportTable m_imports; // Interned ZapImport *
304 SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; // Interned ZapBlos for signatures and fixups
305
306 ModuleReferenceTable m_moduleReferences;
307
308 SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_genericSignatures;
309
310 DWORD m_nImportSectionSizes[ZapImportSectionType_Total];
311 COUNT_T m_nImportSectionIndices[ZapImportSectionType_Total];
312
313 ZapImage * m_pImage;
314
315public:
316 ZapImportTable(ZapImage * pImage)
317 : m_pImage(pImage)
318 {
319 // Everything else is zero initialized by the allocator
320 }
321
322 void Preallocate(COUNT_T cbILImage)
323 {
324 PREALLOCATE_HASHTABLE(ZapImportTable::m_imports, 0.0030, cbILImage);
325 PREALLOCATE_HASHTABLE(ZapImportTable::m_blobs, 0.0025, cbILImage);
326
327 PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapImportTable::m_moduleReferences, cbILImage);
328 }
329
330 //
331 // Helpers for encoding import blobs
332 //
333
334 void EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder);
335 void EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder);
336 void EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder);
337 void EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder,
338 CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE);
339 void EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder,
340 CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL,
341 BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE);
342
343 // Encode module if the reference is within current version bubble. If not, return a suitable module within current version bubble.
344 CORINFO_MODULE_HANDLE TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder);
345
346 ICorDynamicInfo * GetJitInfo()
347 {
348 return m_pImage->GetJitInfo();
349 }
350
351 ICorCompileInfo * GetCompileInfo()
352 {
353 return m_pImage->GetCompileInfo();
354 }
355
356 ZapImage * GetImage()
357 {
358 return m_pImage;
359 }
360
361 // Returns index of module in the import table for encoding module fixups in EE datastructures.
362 DWORD GetIndexOfModule(CORINFO_MODULE_HANDLE handle)
363 {
364 ZapImportTable::ModuleReferenceEntry * pModuleReference = GetModuleReference(handle);
365 _ASSERTE(pModuleReference != NULL);
366 return pModuleReference->m_index;
367 }
368
369 // Get the import blob for given signature
370 ZapBlob * GetBlob(SigBuilder * pSigBuilder, BOOL fEager = FALSE);
371
372 // Place give import blob
373 void PlaceBlob(ZapBlob * pBlob, BOOL fEager = FALSE);
374
375 // Encodes the import blob and places it into the image
376 ZapBlob * PlaceImportBlob(ZapImport * pImport, BOOL fEager = FALSE);
377
378 // Places import cell into the image.
379 // This also encoded and places all the import blobs if they are not placed yet.
380 void PlaceImport(ZapImport * pImport);
381
382 // Encodes list of fixups and places it into the image.
383 // This also places all the import cells if they are not placed yet.
384 ZapFixupInfo * PlaceFixups(ZapImport ** pImports);
385 void PlaceFixups(ZapImport ** pImports, NibbleWriter& writer);
386
387 ZapGenericSignature * GetGenericSignature(PVOID signature, BOOL fMethod);
388
389 //
390 // The actual implementations of import cells
391 //
392 ZapImport * GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle);
393 ZapImport * GetModuleHandleImport(CORINFO_MODULE_HANDLE handle);
394 ZapImport * GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId = NULL);
395 ZapImport * GetMethodHandleImport(CORINFO_METHOD_HANDLE handle);
396 ZapImport * GetFieldHandleImport(CORINFO_FIELD_HANDLE handle);
397 ZapImport * GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok);
398 ZapImport * GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle);
399 ZapImport * GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle);
400 ZapImport * GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass);
401 ZapImport * GetSyncLockImport(CORINFO_CLASS_HANDLE handle);
402 ZapImport * GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle);
403 ZapImport * GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle);
404 ZapImport * GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef);
405 ZapImport * GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo);
406
407 ZapImport * GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle);
408 ZapImport * GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle);
409 ZapImport * GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle);
410
411 ZapImport * GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot);
412 void PlaceVirtualImportThunk(ZapImport * pImportThunk);
413
414 ZapImport * GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle);
415 ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle);
416 ZapImport * GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd);
417
418 //
419 // Ready-to-run imports
420 //
421 ZapImport * GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken);
422 ZapImport * GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL);
423 ZapImport * GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken);
424
425 ZapImport * GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle);
426 ZapImport * GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset);
427
428 ZapImport * GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken);
429 ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken);
430
431 ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle);
432 ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_CLASS_HANDLE delegateType = NULL);
433 ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken);
434
435 ZapImport * GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup);
436
437#ifdef FEATURE_READYTORUN_COMPILER
438 ZapNode * GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL, ZapNode * pCell = NULL);
439 ZapNode * GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL);
440 void PlaceIndirectHelperThunk(ZapNode * pImport);
441
442 ZapImport * GetPlacedHelperImport(ReadyToRunHelper helperNum);
443 ZapImport * GetHelperImport(ReadyToRunHelper helperNum);
444#endif
445};
446
447//
448// CORCOMPILE_CODE_IMPORT_SECTION
449//
450class ZapImportSectionsTable : public ZapNode
451{
452 struct ImportSection
453 {
454 ZapVirtualSection * m_pSection;
455 ZapNode * m_pSignatures;
456 ZapNode * m_pAuxiliaryData;
457 USHORT m_Flags;
458 BYTE m_Type;
459 BYTE m_EntrySize;
460 };
461
462 SArray<ImportSection> m_ImportSectionsTable;
463
464public:
465 ZapImportSectionsTable(ZapImage * pImage)
466 {
467 }
468
469 COUNT_T Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures = NULL, ZapNode * pAuxiliaryData = NULL);
470
471 virtual UINT GetAlignment()
472 {
473 return sizeof(DWORD);
474 }
475
476 virtual DWORD GetSize();
477
478 virtual ZapNodeType GetType()
479 {
480 return ZapNodeType_ImportSectionsTable;
481 }
482
483 virtual void Save(ZapWriter * pZapWriter);
484};
485
486//
487// ZapImportSectionSignatures contains an array of signature RVAs for given import section.
488//
489class ZapImportSectionSignatures : public ZapNode
490{
491 ZapVirtualSection * m_pImportSection;
492 ZapGCRefMapTable * m_pGCRefMapTable;
493
494 DWORD m_dwIndex;
495
496 ZapImage * m_pImage;
497
498public:
499 ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection = NULL);
500 ~ZapImportSectionSignatures();
501
502 void PlaceExternalMethodThunk(ZapImport * pImport);
503 void PlaceExternalMethodCell(ZapImport * pImport);
504 void PlaceStubDispatchCell(ZapImport * pImport);
505 void PlaceDynamicHelperCell(ZapImport * pImport);
506
507 virtual DWORD GetSize();
508
509 virtual UINT GetAlignment()
510 {
511 return sizeof(DWORD);
512 }
513
514 virtual ZapNodeType GetType()
515 {
516 return ZapNodeType_ImportSectionSignatures;
517 }
518
519 virtual void Save(ZapWriter * pZapWriter);
520};
521
522#include "gcrefmap.h"
523
524class ZapGCRefMapTable : public ZapNode
525{
526 ZapImage * m_pImage;
527 GCRefMapBuilder m_GCRefMapBuilder;
528 COUNT_T m_nCount;
529
530public:
531 ZapGCRefMapTable(ZapImage * pImage)
532 : m_pImage(pImage)
533 {
534 }
535
536 void Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell = false);
537
538 virtual DWORD GetSize();
539
540 virtual UINT GetAlignment()
541 {
542 return sizeof(DWORD);
543 }
544
545 virtual ZapNodeType GetType()
546 {
547 return ZapNodeType_GCRefMapTable;
548 }
549
550 virtual void Save(ZapWriter * pZapWriter);
551};
552
553#endif // __ZAPIMPORT_H__
554