826f1bcf9bcaa5590c4d98834de30cb37e4cd83e
[platform/upstream/coreclr.git] / src / zap / zapimage.h
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 // ZapImage.h
6 //
7
8 //
9 // NGEN-specific infrastructure for writing PE files.
10 //
11 // ======================================================================================
12
13 #ifndef __ZAPIMAGE_H__
14 #define __ZAPIMAGE_H__
15
16 class ZapMetaData;
17 class ZapILMetaData;
18 class ZapCorHeader;
19 class ZapNativeHeader;
20 class ZapVersionInfo;
21 class ZapDependencies;
22 class ZapCodeManagerEntry;
23
24 class ZapReadyToRunHeader;
25
26 class ZapInnerPtrTable;
27 class ZapMethodEntryPointTable;
28 class ZapWrapperTable;
29
30 class ZapBaseRelocs;
31
32 class ZapBlobWithRelocs;
33
34 //class ZapGCInfoTable;
35 #ifdef WIN64EXCEPTIONS
36 class ZapUnwindDataTable;
37 #endif
38
39 class ZapImportTable;
40 class ZapImportSectionsTable;
41 class ZapImportSectionSignatures;
42
43 class ZapVirtualSectionsTable;
44 class DataImage;
45
46 class ZapperStats;
47
48 #undef SAFERELEASE
49 #define SAFERELEASE(p) if ((p) != NULL) { IUnknown * _ = (p); (p) = NULL; _->Release();  };
50
51 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
52 #define DEFAULT_CODE_BUFFER_INIT 0xcc // breakpoint
53 #else
54 #define DEFAULT_CODE_BUFFER_INIT 0
55 #endif
56
57 #ifdef _TARGET_64BIT_
58 // Optimize for speed
59 #define DEFAULT_CODE_ALIGN  16
60 #else
61 // Optimize for size.
62 #define DEFAULT_CODE_ALIGN  4
63 #endif
64
65 #ifdef _TARGET_ARM_
66 #define MINIMUM_CODE_ALIGN 2
67 #elif _TARGET_ARM64_
68 #define MINIMUM_CODE_ALIGN 4
69 #else
70 #define MINIMUM_CODE_ALIGN 1
71 #endif
72
73 // Various zapper hashtables are preallocated based on the size of IL image to reduce amount of
74 // rehashing we have to do. Turn ZAP_HASHTABLE_TUNING on to collect data for the tuning of initial hashtable sizes.
75 // #define ZAP_HASHTABLE_TUNING
76
77 #ifdef ZAP_HASHTABLE_TUNING
78
79 #define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \
80     PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage)
81
82 #define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) \
83     do { \
84         GetSvcLogger()->Printf(W("HashTable:\t%S\t%d\t%f\n"), #table, table.GetCount(), (double)table.GetCount() / (double)cbILImage); \
85     } while (0)
86
87 #define PREALLOCATE_ARRAY(array, quotient, cbILImage)  \
88     do { \
89         GetSvcLogger()->Printf(W("Array:\t%S\t%d\t%f\n"), #array, array.GetCount(), (double)array.GetCount() / (double)cbILImage); \
90     } while (0)
91
92 #else // ZAP_HASHTABLE_TUNING
93
94 #define PREALLOCATE_HASHTABLE(table, quotient, cbILImage)  \
95     do { \
96         COUNT_T nSize = (COUNT_T)(quotient * \
97             ((double)table.s_density_factor_denominator / (double)table.s_density_factor_numerator) * \
98             cbILImage); \
99         if (nSize > table.s_minimum_allocation) \
100             table.Reallocate(nSize); \
101     } while (0)
102
103 #define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage)
104
105 #define PREALLOCATE_ARRAY(array, quotient, cbILImage)  \
106     do { \
107         COUNT_T nSize = (COUNT_T)(quotient * \
108             cbILImage); \
109         array.Preallocate(nSize); \
110     } while (0)
111
112 #endif // ZAP_HASHTABLE_TUNING
113
114 //---------------------------------------------------------------------------------------
115 //
116 // ZapImportSectionType is enum describing import sections allocated in the image
117 //
118 enum ZapImportSectionType
119 {
120     ZapImportSectionType_Handle,        // Unspecified handle
121     ZapImportSectionType_TypeHandle,    // Type and method handles have to have their own section so we can restore them correctly
122     ZapImportSectionType_MethodHandle,
123 #ifdef _TARGET_ARM_
124     ZapImportSectionType_PCode,         // Code pointers have to be in a own section on ARM because of they are tagged differently
125 #endif
126     ZapImportSectionType_StringHandle,  // String handles require special handling for interning
127     ZapImportSectionType_Count,
128
129     ZapImportSectionType_Hot = 0,       // We have two sets of the section - hot and cold
130     ZapImportSectionType_Cold = ZapImportSectionType_Count,
131
132     ZapImportSectionType_Eager = 2 * ZapImportSectionType_Count,    // And one section for eager loaded handles
133
134     ZapImportSectionType_Total = 2 * ZapImportSectionType_Count + 1,
135 };
136
137 #include "zaprelocs.h"
138 #include "zapinfo.h"
139 #include "zapcode.h"
140
141 class ZapImage
142     : public ZapWriter
143     , public ICorCompileDataStore
144 {
145     friend class Zapper;
146     friend class ZapInfo;
147     friend class ZapILMetaData;
148     friend class ZapImportTable;
149     friend class ZapCodeMethodDescs;
150     friend class ZapColdCodeMap;
151     friend class ZapReadyToRunHeader;
152
153  private:
154
155     Zapper          *m_zapper;
156
157     //
158     // Output module
159     //
160
161     LPWSTR          m_pOutputFileFullName;      // Name of the temp ngen file to generate (including the path)
162
163     //
164     // Make all virtual section pointers public for now. It should be cleaned up as we get more sophisticated layout
165     // algorithm in place.
166     //
167 public:
168     ZapPhysicalSection * m_pTextSection;
169
170     //
171     // All virtual sections of the native image in alphabetical order
172     //
173
174     ZapVirtualSection * m_pBaseRelocsSection;
175     ZapVirtualSection * m_pCodeSection;
176     ZapVirtualSection * m_pColdCodeSection;
177     ZapVirtualSection * m_pDebugSection;
178     ZapVirtualSection * m_pDelayLoadInfoDelayListSectionEager;
179     ZapVirtualSection * m_pDelayLoadInfoDelayListSectionCold;
180     ZapVirtualSection * m_pDelayLoadInfoDelayListSectionHot;
181     ZapVirtualSection * m_pDelayLoadInfoTableSection[ZapImportSectionType_Total];
182     ZapVirtualSection * m_pStubsSection;
183     ZapVirtualSection * m_pEETableSection;
184     ZapVirtualSection * m_pExceptionSection;
185     ZapVirtualSection * m_pGCSection;
186     ZapVirtualSection * m_pHeaderSection;
187     ZapVirtualSection * m_pHelperTableSection;
188     ZapVirtualSection * m_pLazyHelperSection;
189     ZapVirtualSection * m_pLazyMethodCallHelperSection;
190     ZapVirtualSection * m_pHotCodeSection;
191     ZapVirtualSection * m_pHotGCSection;
192     ZapVirtualSection * m_pHotTouchedGCSection;
193     ZapVirtualSection * m_pILMetaDataSection;
194     ZapVirtualSection * m_pILSection;
195     ZapVirtualSection * m_pImportTableSection;
196     ZapVirtualSection * m_pInstrumentSection;
197     ZapVirtualSection * m_pMetaDataSection;
198     ZapVirtualSection * m_pReadOnlyDataSection;
199     ZapVirtualSection * m_pResourcesSection;
200     ZapVirtualSection * m_pWin32ResourceSection;
201     ZapVirtualSection * m_pStubDispatchCellSection;
202     ZapVirtualSection * m_pStubDispatchDataSection;
203     ZapVirtualSection * m_pDynamicHelperCellSection;
204     ZapVirtualSection * m_pDynamicHelperDataSection;
205     ZapVirtualSection * m_pVirtualImportThunkSection;
206     ZapVirtualSection * m_pExternalMethodThunkSection;
207     ZapVirtualSection * m_pExternalMethodCellSection;
208     ZapVirtualSection * m_pExternalMethodDataSection;
209     ZapVirtualSection * m_pHotRuntimeFunctionSection;
210     ZapVirtualSection * m_pRuntimeFunctionSection;
211     ZapVirtualSection * m_pColdRuntimeFunctionSection;
212     ZapVirtualSection * m_pHotCodeMethodDescsSection;
213     ZapVirtualSection * m_pCodeMethodDescsSection;
214     ZapVirtualSection * m_pHotRuntimeFunctionLookupSection;
215     ZapVirtualSection * m_pRuntimeFunctionLookupSection;
216     ZapVirtualSection * m_pColdCodeMapSection;
217 #if defined(WIN64EXCEPTIONS)
218     ZapVirtualSection * m_pHotUnwindDataSection;
219     ZapVirtualSection * m_pUnwindDataSection;
220     ZapVirtualSection * m_pColdUnwindDataSection;
221 #endif // defined(WIN64EXCEPTIONS)
222
223 #ifdef FEATURE_READYTORUN_COMPILER
224     ZapVirtualSection * m_pAvailableTypesSection;
225 #endif
226
227     // Preloader sections
228     ZapVirtualSection * m_pPreloadSections[CORCOMPILE_SECTION_COUNT];
229
230     ZapExceptionInfoLookupTable*      m_pExceptionInfoLookupTable;
231 public:
232     // TODO: Remove once all EE datastructures are converted to ZapNodes
233     ICorCompilePreloader * m_pPreloader;
234     DataImage * m_pDataImage;
235
236 public:
237     // TODO: The stats should be removed once we have all information available in nidump
238     ZapperStats                *m_stats;
239
240 private:
241     IMetaDataAssemblyEmit      *m_pAssemblyEmit; // native image manifest
242     ZapMetaData *               m_pAssemblyMetaData;
243
244     ZapVersionInfo *            m_pVersionInfo;
245     ZapDependencies *           m_pDependencies;
246
247     SString                     m_pdbFileName;
248
249     ZapCodeManagerEntry *       m_pCodeManagerEntry;
250
251     ZapBlob *                   m_pEEInfoTable;
252
253     //
254     // Auxiliary tables
255     //
256     ZapImportTable *            m_pImportTable;
257
258     ZapImportSectionsTable *    m_pImportSectionsTable;
259
260     ZapInnerPtrTable *          m_pInnerPtrs;
261
262     ZapMethodEntryPointTable *  m_pMethodEntryPoints;
263
264     ZapWrapperTable *           m_pWrappers;
265
266     ZapBaseRelocs *             m_pBaseRelocs;
267
268     ULONGLONG                   m_NativeBaseAddress;
269
270     ULONGLONG GetNativeBaseAddress()
271     {
272         return m_NativeBaseAddress;
273     }
274
275     void                        CalculateZapBaseAddress();
276
277     // Preallocate hashtables to avoid rehashing
278     void Preallocate();
279
280     ZapGCInfoTable *            m_pGCInfoTable;
281
282 #ifdef WIN64EXCEPTIONS
283     ZapUnwindDataTable *        m_pUnwindDataTable;
284 #endif
285
286     ZapImportSectionSignatures * m_pDelayLoadInfoDataTable[ZapImportSectionType_Total];
287     ZapImportSectionSignatures * m_pStubDispatchDataTable;
288     ZapImportSectionSignatures * m_pExternalMethodDataTable;
289     ZapImportSectionSignatures * m_pDynamicHelperDataTable;
290
291     ZapVirtualSectionsTable *   m_pVirtualSectionsTable;
292
293     ZapDebugInfoTable *         m_pDebugInfoTable;
294
295     ZapILMetaData *             m_pILMetaData;
296
297     ZapCorHeader *              m_pCorHeader;
298
299     ZapNode *                   m_pResources;
300
301     ZapNode *                   m_pNativeHeader;
302
303     ZapBlob *                   m_pNGenPdbDebugData;
304
305     ULONG                       m_totalHotCodeSize;
306     ULONG                       m_totalColdCodeSize;
307
308     ULONG                       m_totalCodeSizeInProfiledMethods;
309     ULONG                       m_totalColdCodeSizeInProfiledMethods;
310
311     //information to track the boundaries of the different subsections within
312     //the hot section.
313     COUNT_T                     m_iIBCMethod;
314     COUNT_T                     m_iGenericsMethod;
315     COUNT_T                     m_iUntrainedMethod;
316
317     //
318     // Input module
319     //
320
321     LPWSTR                      m_pModuleFileName; // file name of the module being compiled, including path
322     CORINFO_MODULE_HANDLE       m_hModule;   // Module being compiled
323     PEDecoder                   m_ModuleDecoder;
324     IMDInternalImport *         m_pMDImport;
325     bool                        m_fManifestModule;  // Is this the assembly-manifest-module
326     bool                        m_fHaveProfileData;
327
328     ZapNode **                  m_pHelperThunks; // Array of on demand allocated JIT helper thunks
329
330     //
331     // Profile source
332     //
333
334     BYTE *                      m_profileDataFile;
335     BYTE *                      m_pRawProfileData;
336     COUNT_T                     m_cRawProfileData;
337     CorProfileData *            m_pCorProfileData;
338
339 public:
340     enum CompileStatus {
341         // Failure status values are negative
342         LOOKUP_FAILED    = -2,
343         COMPILE_FAILED   = -1,
344
345         // Info status values are [0..9]
346         NOT_COMPILED          =  0,
347         COMPILE_EXCLUDED      =  1,
348         COMPILE_HOT_EXCLUDED  =  2,
349         COMPILE_COLD_EXCLUDED =  3,
350
351         // Successful status values are 10 or greater
352         COMPILE_SUCCEED  = 10,
353         ALREADY_COMPILED = 11
354     };
355
356 private:
357     // A hash table entry that contains the profile infomation and the CompileStatus for a given method
358     struct ProfileDataHashEntry
359     {
360         mdMethodDef   md;       // The method.token, also used as the key for the ProfileDataHashTable
361         DWORD         size;     // The size of the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData()
362         ULONG         pos;      // the offset to the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData()
363
364         unsigned      flags;    // The methodProfilingDataFlags, set by ZapImage::CompileHotRegion()
365         CompileStatus status;   // The compileResult, set by ZapImage::CompileHotRegion()
366     };
367
368     class ProfileDataHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ProfileDataHashEntry> >
369     {
370     public:
371         typedef const mdMethodDef key_t;
372
373         static key_t GetKey(element_t e)
374         {
375             LIMITED_METHOD_CONTRACT;
376             return e.md;
377         }
378         static BOOL Equals(key_t k1, key_t k2)
379         {
380             LIMITED_METHOD_CONTRACT;
381             return k1 == k2;
382         }
383         static count_t Hash(key_t k)
384         {
385             LIMITED_METHOD_CONTRACT;
386             return (count_t)k;
387         }
388
389         static const element_t Null()
390         {
391             LIMITED_METHOD_CONTRACT; 
392             ProfileDataHashEntry e; 
393             e.md = 0; 
394             e.size = 0; 
395             e.pos = 0;
396             e.flags = 0;
397             e.status = NOT_COMPILED;
398             return e;
399         }
400
401         static bool IsNull(const element_t &e)
402         {
403             LIMITED_METHOD_CONTRACT;
404             // returns true if both md and pos are zero
405             return (e.md == 0) && (e.pos == 0);
406         }
407     };
408     typedef SHash<ProfileDataHashTraits> ProfileDataHashTable;
409
410     ProfileDataHashTable profileDataHashTable;
411
412     SArray<SString, FALSE> fileNotFoundErrorsTable;
413     void FileNotFoundError(LPCWSTR pszMessage);
414
415 public:
416     struct ProfileDataSection
417     {
418         BYTE    *pData;
419         DWORD    dataSize;
420         DWORD    tableSize;
421         CORBBTPROF_TOKEN_INFO *pTable;
422     };
423
424 private:
425     ProfileDataSection m_profileDataSections[SectionFormatCount];
426
427     DWORD m_profileDataNumRuns;
428
429     CorInfoRegionKind m_currentRegionKind;
430
431     BOOL IsAssemblyBeingCompiled(CORINFO_MODULE_HANDLE module) {
432         return ((module == m_hModule) ||
433                 (m_zapper->m_pEECompileInfo->GetModuleAssembly(module) == m_zapper->m_hAssembly));
434     }
435
436     class ZapMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodHeader *> >
437     {
438     public:
439         typedef CORINFO_METHOD_HANDLE key_t;
440
441         static key_t GetKey(element_t e)
442         {
443             LIMITED_METHOD_CONTRACT;
444             return e->GetHandle();
445         }
446         static BOOL Equals(key_t k1, key_t k2)
447         {
448             LIMITED_METHOD_CONTRACT;
449             return k1 == k2;
450         }
451         static count_t Hash(key_t k)
452         {
453             LIMITED_METHOD_CONTRACT;
454             return (count_t)(size_t)k;
455         }
456     };
457
458     typedef SHash<ZapMethodTraits> ZapMethodHashTable;
459
460     ZapMethodHashTable m_CompiledMethods;
461
462     SArray<ZapMethodHeader *> m_MethodCompilationOrder;
463
464     SArray<ZapGCInfo *> m_PrioritizedGCInfo;
465
466 #ifndef FEATURE_FULL_NGEN
467     class MethodCodeTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodHeader *> >
468     {
469     public:
470         typedef ZapMethodHeader * key_t;
471
472         static FORCEINLINE key_t GetKey(element_t e)
473         {
474             LIMITED_METHOD_CONTRACT;
475             return e;
476         }
477
478         static BOOL Equals(key_t k1, key_t k2);
479         static COUNT_T Hash(key_t k);
480
481         static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
482         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
483     };
484
485     typedef SHash <MethodCodeTraits> ZapMethodCodeHashTable;
486
487     ZapMethodCodeHashTable m_CodeDeduplicator;
488 #endif // FEATURE_FULL_NGEN
489
490     struct ClassLayoutOrderEntry
491     {
492         CORINFO_CLASS_HANDLE m_cls;
493         unsigned             m_order;
494
495         ClassLayoutOrderEntry()
496             : m_cls(0), m_order(0)
497         {
498         }
499
500         ClassLayoutOrderEntry(CORINFO_CLASS_HANDLE cls, unsigned order)
501             : m_cls(cls), m_order(order)
502         {
503         }
504     };
505
506     class ClassLayoutOrderTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ClassLayoutOrderEntry> >
507     {
508     public:
509         typedef CORINFO_CLASS_HANDLE key_t;
510
511         static key_t GetKey(element_t e)
512         {
513             LIMITED_METHOD_CONTRACT;
514             return e.m_cls;
515         }
516         static BOOL Equals(key_t k1, key_t k2)
517         {
518             LIMITED_METHOD_CONTRACT;
519             return k1 == k2;
520         }
521         static count_t Hash(key_t k)
522         {
523             LIMITED_METHOD_CONTRACT;
524             return (count_t)(size_t)k;
525         }
526         static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(0,0); }
527         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_cls == 0; }
528     };
529
530     typedef SHash<ClassLayoutOrderTraits> ClassLayoutOrderHashTable;
531
532     ClassLayoutOrderHashTable m_ClassLayoutOrder;
533
534     // See ComputeClassLayoutOrder for an explanation of these flags
535     #define UNSEEN_CLASS_FLAG (0x80000000)
536     #define METHOD_INDEX_FLAG (0x40000000)
537
538     // The class layout order needs to be initialized with the first index
539     // in m_MethodCompilationOrder of a method in the given class.
540     inline void InitializeClassLayoutOrder(CORINFO_CLASS_HANDLE cls, unsigned order)
541     {
542         WRAPPER_NO_CONTRACT;
543
544         if (!m_ClassLayoutOrder.LookupPtr(cls))
545         {
546             ClassLayoutOrderEntry entry(cls, order | UNSEEN_CLASS_FLAG | METHOD_INDEX_FLAG);
547             m_ClassLayoutOrder.Add(entry);
548         }
549     }
550
551 public:
552     inline unsigned LookupClassLayoutOrder(CORINFO_CLASS_HANDLE cls)
553     {
554         WRAPPER_NO_CONTRACT;
555
556         const ClassLayoutOrderEntry *pEntry = m_ClassLayoutOrder.LookupPtr(cls);
557         _ASSERTE(!pEntry || pEntry->m_order != 0);
558
559         return pEntry ? pEntry->m_order : 0;
560     }
561
562 private:
563
564     //
565     // The image layout algorithm
566     //
567
568     enum CodeType
569     {
570         ProfiledHot,
571         ProfiledCold,
572         Unprofiled
573     };
574
575     ZapVirtualSection * GetCodeSection(CodeType codeType);
576     ZapVirtualSection * GetRuntimeFunctionSection(CodeType codeType);
577     ZapVirtualSection * GetCodeMethodDescSection(CodeType codeType);
578     ZapVirtualSection * GetUnwindInfoLookupSection(CodeType codeType);
579
580 #if defined(WIN64EXCEPTIONS)
581     ZapVirtualSection * GetUnwindDataSection(CodeType codeType);
582 #endif
583
584     void GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end);
585
586     void OutputCode(CodeType codeType);
587     void OutputCodeInfo(CodeType codeType);
588
589     void OutputGCInfo();
590
591     void OutputDebugInfo();
592     void OutputProfileData();
593
594     void OutputEntrypointsTableForReadyToRun();
595     void OutputDebugInfoForReadyToRun();
596     void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport);
597     void OutputInliningTableForReadyToRun();
598     void OutputProfileDataForReadyToRun();
599
600     void CopyDebugDirEntry();
601     void CopyWin32VersionResource();
602
603     void OutputManifestMetadata();
604     void OutputTables();
605
606     // Assign RVAs to all ZapNodes
607     void ComputeRVAs();
608
609     HANDLE GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
610
611     void PrintStats(LPCWSTR wszOutputFileName);
612
613     bool m_fHasClassLayoutOrder;
614
615     void ComputeClassLayoutOrder();
616     void SortUnprofiledMethodsByClassLayoutOrder();
617
618     HRESULT GetPdbFileNameFromModuleFilePath(__in_z const wchar_t *pwszModuleFilePath,
619                                              __out_ecount(dwPdbFileNameBufferSize) char * pwszPdbFileName,
620                                              DWORD dwPdbFileNameBufferSize);
621
622 public:
623     ZapImage(Zapper *zapper);
624     virtual ~ZapImage();
625
626     // ----------------------------------------------------------------------------------------------------------
627     //
628     // Utility function for converting ZapWriter * to ZapImage *. This cast should not be done directly by the code
629     // so that the relationship between ZapWriter and ZapImage is abstracted away.
630     //
631     static ZapImage * GetImage(ZapWriter * pZapWriter)
632     {
633         return (ZapImage *)pZapWriter;
634     }
635
636     // ----------------------------------------------------------------------------------------------------------
637     //
638     // Add relocation record. This method is meant to be called from the Save method of custom ZapNodes right
639     // before the given datastructure is written into the native image.
640     //
641     // Arguments:
642     //    pSrc - the datastructure being written
643     //    offset - offset of the relocation within the datastructure
644     //    pTarget - target of the relocation
645     //    targetOffset - adjusment of the target (usually 0)
646     //    type - relocation type (IMAGE_REL_BASED_XXX enum, note that we have private additions to this enum:
647     //              IMAGE_REL_BASED_PTR - architecture specific reloc of virtual address
648     //              IMAGE_REL_BASED_ABSOLUTE_TAGGED - absolute stored in the middle 30-bits, used for fixups.
649     //              IMAGE_REL_BASED_RELPTR - pointer stored as address relative delta
650     //              IMAGE_REL_BASED_RELPTR32 - pointer stored as address relative 32-bit delta
651     //
652     void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type);
653
654     void Open(CORINFO_MODULE_HANDLE hModule, IMetaDataAssemblyEmit *pEmit);
655
656     void InitializeSections();
657     void InitializeSectionsForReadyToRun();
658
659     // Wrapper of ZapWriter::NewVirtualSection that sets sectionType
660     ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD sectionType /* ZapVirtualSectionType */, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL)
661     {
662         ZapVirtualSection * pSection = ZapWriter::NewVirtualSection(pPhysicalSection, dwAlignment, pInsertAfter);
663         pSection->SetSectionType(sectionType);
664         return pSection;
665     }
666
667     void AllocateVirtualSections();
668
669     HANDLE SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
670
671     void Preload();
672     void LinkPreload();
673
674     void SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo);
675     void SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies);
676     void SetPdbFileName(const SString &strFileName);
677
678 #ifdef WIN64EXCEPTIONS
679     void SetRuntimeFunctionsDirectoryEntry();
680 #endif
681
682     void SaveCorHeader();
683     void SaveNativeHeader();
684     void SaveCodeManagerEntry();
685
686     void Compile();
687
688     ZapMethodHeader * GetCompiledMethod(CORINFO_METHOD_HANDLE handle)
689     {
690         return m_CompiledMethods.Lookup(handle);
691     }
692
693     static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags);
694
695     BOOL IsVTableGapMethod(mdMethodDef md);
696
697     CompileStatus TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags);
698     CompileStatus TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, unsigned methodProfilingDataFlags);
699     CompileStatus TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, unsigned methodProfilingDataFlags);
700
701     BOOL ShouldCompileMethodDef(mdMethodDef md);
702     BOOL ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle);
703
704     bool canIntraModuleDirectCall(CORINFO_METHOD_HANDLE  callerFtn,
705                          CORINFO_METHOD_HANDLE  targetFtn,
706                          CorInfoIndirectCallReason *pReason = NULL,
707                          CORINFO_ACCESS_FLAGS   accessFlags = CORINFO_ACCESS_ANY);
708
709     CORINFO_MODULE_HANDLE GetModuleHandle()
710     {
711         return m_hModule;
712     }
713
714     IMetaDataAssemblyEmit * GetAssemblyEmit()
715     {
716         return m_pAssemblyEmit;
717     }
718
719     ZapWrapperTable * GetWrappers()
720     {
721         return m_pWrappers;
722     }
723
724     ZapImportTable * GetImportTable()
725     {
726         return m_pImportTable;
727     }
728
729     ZapImportSectionsTable * GetImportSectionsTable()
730     {
731         return m_pImportSectionsTable;
732     }
733
734     ZapNode * GetEEInfoTable()
735     {
736         return m_pEEInfoTable;
737     }
738
739     ZapReadyToRunHeader * GetReadyToRunHeader()
740     {
741         _ASSERTE(IsReadyToRunCompilation());
742         return (ZapReadyToRunHeader *)m_pNativeHeader;
743     }
744
745     ZapNode * GetInnerPtr(ZapNode * pNode, SSIZE_T offset);
746
747     CorInfoRegionKind GetCurrentRegionKind()
748     {
749         return m_currentRegionKind;
750     }
751
752     //
753     // Called from  ZapImportTable::PlaceBlob
754     // to determine wheather to place the new signature Blob
755     // into the HotImports or the ColdImports section.
756     //
757     // The Assert will fire if BeginRegion was not called
758     // to setup the region
759     //
760     bool IsCurrentCodeRegionHot()
761     {
762         if (GetCurrentRegionKind() == CORINFO_REGION_HOT)
763         {
764             return true;
765         }
766         else if (GetCurrentRegionKind() == CORINFO_REGION_COLD)
767         {
768             return false;
769         }
770         _ASSERTE(!"unsupported RegionKind");
771         return false;
772     }
773
774     //
775     // Marks the start of a region where we want to place any
776     // new signature Blobs into the Hot/Cold region
777     //
778     void BeginRegion(CorInfoRegionKind regionKind)
779     {
780         _ASSERTE(GetCurrentRegionKind() == CORINFO_REGION_NONE);
781         m_currentRegionKind = regionKind;
782     }
783
784     //
785     // Marks the end of a region and we no longer expect to
786     // need any new signature Blobs
787     //
788     void EndRegion(CorInfoRegionKind regionKind)
789     {
790         _ASSERTE(GetCurrentRegionKind() == regionKind);
791         m_currentRegionKind = CORINFO_REGION_NONE;
792     }
793
794     ICorCompilationDomain * GetDomain()
795     {
796         return m_zapper->m_pDomain;
797     }
798
799     ICorDynamicInfo * GetJitInfo()
800     {
801         return m_zapper->m_pEEJitInfo;
802     }
803
804     ICorCompileInfo * GetCompileInfo()
805     {
806         return m_zapper->m_pEECompileInfo;
807     }
808
809     ZapperOptions *    GetZapperOptions()
810     {
811         return m_zapper->m_pOpt;
812     }
813
814     ZapNode * GetHelperThunkIfExists(CorInfoHelpFunc ftnNum)
815     {
816         return m_pHelperThunks[ftnNum];
817     }
818
819     ZapNode * GetHelperThunk(CorInfoHelpFunc ftnNum);
820
821     BOOL HasClassLayoutOrder()
822     {
823         return m_fHasClassLayoutOrder;
824     }
825
826     HRESULT PrintTokenDescription(CorZapLogLevel level, mdToken token);
827
828     // ICorCompileDataStore
829
830     // Returns ZapImage
831     virtual ZapImage * GetZapImage();
832     void Error(mdToken token, HRESULT error, UINT resID, LPCWSTR message);
833
834     // Returns virtual section for EE datastructures
835     ZapVirtualSection * GetSection(CorCompileSection section)
836     {
837         return m_pPreloadSections[section];
838     }
839
840     HRESULT LocateProfileData();
841     HRESULT parseProfileData  ();
842     HRESULT convertProfileDataFromV1();
843     void RehydrateBasicBlockSection();
844     void RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]);
845     void RehydrateBlobStream();
846     HRESULT RehydrateProfileData();
847     HRESULT hashBBProfileData ();
848     void hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, CompileStatus compileResult);
849
850     void              LoadProfileData();
851     CorProfileData *  NewProfileData();
852     CorProfileData *  GetProfileData();
853     bool              CanConvertIbcData();
854
855     CompileStatus     CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags);
856
857     void              ProfileDisableInlining();
858     void              CompileHotRegion();
859     void              CompileColdRegion();
860     void              PlaceMethodIL();
861 };
862
863 class BinaryWriter
864 {
865 private:
866     char *m_buffer;
867     unsigned int m_length;
868     unsigned int m_currentPosition;
869     ZapHeap *m_heap;
870
871 private:
872     // Make sure that the buffer is at least newLength bytes long;
873     // expand it if necessary.
874     void RequireLength(unsigned int newLength)
875     {
876         if (newLength <= m_length)
877         {
878             return;
879         }
880
881         if (newLength < (m_length * 3) / 2)
882         {
883             newLength = (m_length * 3) / 2;
884         }
885
886         char *newBuffer = new (m_heap) char[newLength];
887
888         memcpy(newBuffer, m_buffer, m_length);
889
890         m_length = newLength;
891         m_buffer = newBuffer;
892     }
893
894 public:
895     BinaryWriter(unsigned int initialLength, ZapHeap *heap)
896     {
897         m_heap = heap;
898         m_length = initialLength;
899         m_buffer = new (m_heap) char[initialLength];
900         m_currentPosition = 0;
901     }
902
903     template <typename T>
904     void WriteAt(unsigned int position, const T &v)
905     {
906         RequireLength(position + sizeof(T));
907
908         *(T *)(m_buffer + position) = v;
909     }
910
911     template <typename T>
912     void Write(const T &v)
913     {
914         WriteAt<T>(m_currentPosition, v);
915         m_currentPosition += sizeof(T);
916     }
917
918     void Write(const char *data, unsigned int length)
919     {
920         RequireLength(m_currentPosition + length);
921
922         memcpy(m_buffer + m_currentPosition, data, length);
923         m_currentPosition += length;
924     }
925
926     BYTE *GetBuffer()
927     {
928         return (BYTE *)m_buffer;
929     }
930
931     unsigned int GetWrittenSize()
932     {
933         return m_currentPosition;
934     }
935 };
936
937 class ProfileReader
938 {
939 public:
940     ProfileReader(void *buffer, ULONG length)
941     {
942         profileBuffer = (char *) buffer;
943         bufferSize    = length;
944         currentPos    = 0;
945     }
946
947     bool Seek(ULONG pos)
948     {
949         if (pos <= bufferSize)
950         {
951             currentPos = pos;
952             return true;
953         }
954         else
955         {
956             _ASSERTE(!"ProfileReader:  attempt to seek out of bounds");
957             return false;
958         }
959     }
960
961     void *Read(ULONG size)
962     {
963         ULONG oldPos = currentPos;
964
965         if (!Seek(currentPos + size))
966         {
967             return NULL;
968         }
969
970         return (void *)(profileBuffer + oldPos);
971     }
972
973     template <typename T> T Read()
974     {
975         T* pResult = (T*)Read(sizeof(T));
976
977         if (!pResult)
978         {
979             ThrowHR(E_FAIL);
980         }
981
982         return *pResult;
983     }
984
985     // Read an integer a la BinaryReader.Read7BitEncodedInt.
986     unsigned int Read7BitEncodedInt()
987     {
988         unsigned int result = 0;
989         int shift = 0;
990         unsigned char current = 0x80;
991
992         while ((currentPos < bufferSize) &&
993                (shift <= 28))
994         {
995             current = profileBuffer[currentPos++];
996             result |= (current & 0x7f) << shift;
997             shift += 7;
998
999             if (!(current & 0x80))
1000             {
1001                 return result;
1002             }
1003         }
1004
1005         _ASSERTE(!"Improperly encoded value");
1006         ThrowHR(E_FAIL);
1007     }
1008
1009     // Read a token given a 'memory' value--the last token of this type read
1010     // from the stream. The encoding takes advantage of the fact that two
1011     // adjacent tokens in the file are usually of the same type, and therefore
1012     // share a high byte. With the high byte removed the rest of the token can
1013     // be encoded more efficiently.
1014     mdToken ReadTokenWithMemory(mdToken &memory)
1015     {
1016         mdToken current;
1017         mdToken result;
1018
1019         current = Read7BitEncodedInt();
1020
1021         unsigned char highByte = ((current >> 24) & 0xff);
1022
1023         if (highByte == 0)
1024         {
1025             result = current | (memory & 0xff000000);
1026         }
1027         else if (highByte == 0xff)
1028         {
1029             result = current & 0x00ffffff;
1030         }
1031         else
1032         {
1033             result = current;
1034         }
1035
1036         memory = result;
1037
1038         return result;
1039     }
1040
1041     // Read a 32-bit flag value using a lookup table built while processing the
1042     // file. Flag values are represented by a one-byte index. If the index
1043     // hasn't occurred before in the file, it is followed by the four-byte flag
1044     // value it represents. The index 255 is used as an escape code--it is
1045     // always followed by a flag value.
1046     // flagTable must have 255 entries and they must all start as 0xFFFFFFFF.
1047     unsigned int ReadFlagWithLookup(unsigned int flagTable[255])
1048     {
1049         unsigned char index;
1050         unsigned int flags;
1051
1052         index = Read<unsigned char>();
1053
1054         if ((index < 255) && (flagTable[index] != 0xffffffff))
1055         {
1056             return flagTable[index];
1057         }
1058
1059         flags = Read<unsigned int>();
1060
1061         if (index < 255)
1062         {
1063             flagTable[index] = flags;
1064         }
1065
1066         return flags;
1067     }
1068
1069     ULONG GetCurrentPos()
1070     {
1071         _ASSERTE(currentPos <= bufferSize);
1072         return currentPos;
1073     }
1074
1075 private:
1076     char *profileBuffer;
1077     ULONG bufferSize;
1078     ULONG currentPos;
1079 };
1080
1081 struct RSDS {
1082         DWORD magic;
1083         GUID  signature;
1084         DWORD age;
1085         char  path[MAX_LONGPATH];
1086 };
1087
1088 #define SEEK(pos)                                \
1089     if (!profileReader.Seek(pos)) return E_FAIL;
1090
1091 #define READ_SIZE(dst,type,size)                 \
1092     dst = (type *) profileReader.Read(size);     \
1093     if (!dst) return E_FAIL;
1094
1095 #define READ(dst,type)                           \
1096     READ_SIZE(dst,type,sizeof(type))
1097
1098 #endif // __ZAPIMAGE_H__