3ad696720aa3494523964bafc8eb20e66340f7e9
[platform/upstream/coreclr.git] / src / zap / zapimage.cpp
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.cpp
6 //
7
8 //
9 // NGEN-specific infrastructure for writing PE files.
10 // 
11 // ======================================================================================
12
13 #include "common.h"
14 #include "strsafe.h"
15
16 #include "zaprelocs.h"
17
18 #include "zapinnerptr.h"
19 #include "zapwrapper.h"
20
21 #include "zapheaders.h"
22 #include "zapmetadata.h"
23 #include "zapcode.h"
24 #include "zapimport.h"
25
26 #ifdef FEATURE_READYTORUN_COMPILER
27 #include "zapreadytorun.h"
28 #endif
29
30 #include "md5.h"
31
32 // This is RTL_CONTAINS_FIELD from ntdef.h
33 #define CONTAINS_FIELD(Struct, Size, Field) \
34     ( (((PCHAR)(&(Struct)->Field)) + sizeof((Struct)->Field)) <= (((PCHAR)(Struct))+(Size)) )
35
36 /* --------------------------------------------------------------------------- *
37  * Destructor wrapper objects
38  * --------------------------------------------------------------------------- */
39
40 ZapImage::ZapImage(Zapper *zapper)
41   : m_zapper(zapper),
42     m_stats(new ZapperStats())
43     /* Everything else is initialized to 0 by default */
44 {
45 }
46
47 ZapImage::~ZapImage()
48 {
49 #ifdef ZAP_HASHTABLE_TUNING
50     // If ZAP_HASHTABLE_TUNING is defined, preallocate is overloaded to print the tunning constants
51     Preallocate();
52 #endif
53
54     //
55     // Clean up.
56     //
57     if (m_stats != NULL)
58             delete m_stats;
59
60     if (m_pModuleFileName != NULL)
61         delete [] m_pModuleFileName;
62
63     if (m_pMDImport != NULL)
64         m_pMDImport->Release();
65
66     if (m_pAssemblyEmit != NULL)
67         m_pAssemblyEmit->Release();
68
69     if (m_profileDataFile != NULL)
70         UnmapViewOfFile(m_profileDataFile);
71
72     if (m_pPreloader)
73         m_pPreloader->Release();
74
75     if (m_pImportSectionsTable != NULL)
76         m_pImportSectionsTable->~ZapImportSectionsTable();
77
78     if (m_pGCInfoTable != NULL)
79         m_pGCInfoTable->~ZapGCInfoTable();
80
81 #ifdef WIN64EXCEPTIONS
82     if (m_pUnwindDataTable != NULL)
83         m_pUnwindDataTable->~ZapUnwindDataTable();
84 #endif
85
86     if (m_pStubDispatchDataTable != NULL)
87         m_pStubDispatchDataTable->~ZapImportSectionSignatures();
88
89     if (m_pExternalMethodDataTable != NULL)
90         m_pExternalMethodDataTable->~ZapImportSectionSignatures();
91
92     if (m_pDynamicHelperDataTable != NULL)
93         m_pDynamicHelperDataTable->~ZapImportSectionSignatures();
94
95     if (m_pDebugInfoTable != NULL)
96         m_pDebugInfoTable->~ZapDebugInfoTable();
97
98     if (m_pVirtualSectionsTable != NULL)
99         m_pVirtualSectionsTable->~ZapVirtualSectionsTable();
100
101     if (m_pILMetaData != NULL)
102         m_pILMetaData->~ZapILMetaData();
103
104     if (m_pBaseRelocs != NULL)
105         m_pBaseRelocs->~ZapBaseRelocs();
106
107     if (m_pAssemblyMetaData != NULL)
108         m_pAssemblyMetaData->~ZapMetaData();
109
110     //
111     // Destruction of auxiliary tables in alphabetical order
112     //
113
114     if (m_pImportTable != NULL) 
115         m_pImportTable->~ZapImportTable();
116
117     if (m_pInnerPtrs != NULL) 
118         m_pInnerPtrs->~ZapInnerPtrTable();
119
120     if (m_pMethodEntryPoints != NULL)
121         m_pMethodEntryPoints->~ZapMethodEntryPointTable();
122
123     if (m_pWrappers != NULL) 
124         m_pWrappers->~ZapWrapperTable();
125 }
126
127 void ZapImage::InitializeSections()
128 {
129     AllocateVirtualSections();
130
131     m_pCorHeader = new (GetHeap()) ZapCorHeader(this);
132     m_pHeaderSection->Place(m_pCorHeader);
133
134     SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader);
135
136     m_pNativeHeader = new (GetHeap()) ZapNativeHeader(this);
137     m_pHeaderSection->Place(m_pNativeHeader);
138
139     m_pCodeManagerEntry = new (GetHeap()) ZapCodeManagerEntry(this);
140     m_pHeaderSection->Place(m_pCodeManagerEntry);
141
142     m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this);
143     m_pImportTableSection->Place(m_pImportSectionsTable);
144
145     m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodThunkSection, m_pGCSection);
146     m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable);
147
148     m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection);
149     m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable);
150
151     m_pImportTable = new (GetHeap()) ZapImportTable(this);
152     m_pImportTableSection->Place(m_pImportTable);
153
154     m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this);
155     m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this);
156
157 #ifdef WIN64EXCEPTIONS
158     m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this);
159 #endif
160
161     m_pEEInfoTable = ZapBlob::NewAlignedBlob(this, NULL, sizeof(CORCOMPILE_EE_INFO_TABLE), sizeof(TADDR));
162     m_pEETableSection->Place(m_pEEInfoTable);
163
164     //
165     // Allocate Helper table, and fill it out
166     //
167
168     m_pHelperThunks = new (GetHeap()) ZapNode * [CORINFO_HELP_COUNT];
169
170     if (!m_zapper->m_pOpt->m_fNoMetaData)
171     {
172         m_pILMetaData = new (GetHeap()) ZapILMetaData(this);
173         m_pILMetaDataSection->Place(m_pILMetaData);
174     }
175
176     m_pDebugInfoTable = new (GetHeap()) ZapDebugInfoTable(this);
177     m_pDebugSection->Place(m_pDebugInfoTable);
178
179     m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this);
180     m_pBaseRelocsSection->Place(m_pBaseRelocs);
181
182     SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection);
183
184     //
185     // Initialization of auxiliary tables in alphabetical order
186     //
187     m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this);
188     m_pMethodEntryPoints = new (GetHeap()) ZapMethodEntryPointTable(this);
189     m_pWrappers = new (GetHeap()) ZapWrapperTable(this);
190
191     // Place the virtual sections tables in debug section. It exists for diagnostic purposes
192     // only and should not be touched under normal circumstances    
193     m_pVirtualSectionsTable = new (GetHeap()) ZapVirtualSectionsTable(this);
194     m_pDebugSection->Place(m_pVirtualSectionsTable);
195
196 #ifndef ZAP_HASHTABLE_TUNING
197     Preallocate();
198 #endif
199 }
200
201 #ifdef FEATURE_READYTORUN_COMPILER
202 void ZapImage::InitializeSectionsForReadyToRun()
203 {
204     AllocateVirtualSections();
205
206     // Preload sections are not used for ready to run. Clear the pointers to them to catch accidental use.
207     for (int i = 0; i < CORCOMPILE_SECTION_COUNT; i++)
208         m_pPreloadSections[i] = NULL;
209
210     m_pCorHeader = new (GetHeap()) ZapCorHeader(this);
211     m_pHeaderSection->Place(m_pCorHeader);
212
213     SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader);
214
215     m_pNativeHeader = new (GetHeap()) ZapReadyToRunHeader(this);
216     m_pHeaderSection->Place(m_pNativeHeader);
217
218     m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this);
219     m_pHeaderSection->Place(m_pImportSectionsTable);
220
221     {
222 #define COMPILER_NAME "CoreCLR"
223
224         const char * pCompilerIdentifier = COMPILER_NAME " " FX_FILEVERSION_STR " " QUOTE_MACRO(__BUILDMACHINE__);
225         ZapBlob * pCompilerIdentifierBlob = new (GetHeap()) ZapBlobPtr((PVOID)pCompilerIdentifier, strlen(pCompilerIdentifier) + 1);
226
227         GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_COMPILER_IDENTIFIER, pCompilerIdentifierBlob);
228         m_pHeaderSection->Place(pCompilerIdentifierBlob);
229     }
230
231     m_pImportTable = new (GetHeap()) ZapImportTable(this);
232     m_pImportTableSection->Place(m_pImportTable);
233
234     for (int i=0; i<ZapImportSectionType_Total; i++)
235     {
236         ZapVirtualSection * pSection;
237         if (i == ZapImportSectionType_Eager)
238             pSection = m_pDelayLoadInfoDelayListSectionEager;
239         else
240         if (i < ZapImportSectionType_Cold)
241             pSection = m_pDelayLoadInfoDelayListSectionHot;
242         else
243             pSection = m_pDelayLoadInfoDelayListSectionCold;
244
245         m_pDelayLoadInfoDataTable[i] = new (GetHeap()) ZapImportSectionSignatures(this, m_pDelayLoadInfoTableSection[i]);
246         pSection->Place(m_pDelayLoadInfoDataTable[i]);
247     }
248
249     m_pDynamicHelperDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pDynamicHelperCellSection);
250     m_pDynamicHelperDataSection->Place(m_pDynamicHelperDataTable);
251
252     m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodCellSection, m_pGCSection);
253     m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable);
254
255     m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection);
256     m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable);
257
258     m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this);
259
260 #ifdef WIN64EXCEPTIONS
261     m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this);
262 #endif
263
264     m_pILMetaData = new (GetHeap()) ZapILMetaData(this);
265     m_pILMetaDataSection->Place(m_pILMetaData);
266
267     m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this);
268     m_pBaseRelocsSection->Place(m_pBaseRelocs);
269
270     SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection);
271
272     //
273     // Initialization of auxiliary tables in alphabetical order
274     //
275     m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this);
276
277     m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this);
278
279     //
280     // Always allocate slot for module - it is used to determine that the image is used
281     //
282     m_pImportTable->GetPlacedHelperImport(READYTORUN_HELPER_Module);
283
284     //
285     // Make sure the import sections table is in the image, so we can find the slot for module
286     //
287     _ASSERTE(m_pImportSectionsTable->GetSize() != 0);
288     GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_IMPORT_SECTIONS, m_pImportSectionsTable);
289 }
290 #endif // FEATURE_READYTORUN_COMPILER
291
292
293 #define DATA_MEM_READONLY IMAGE_SCN_MEM_READ
294 #define DATA_MEM_WRITABLE IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
295 #define XDATA_MEM         IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
296 #define TEXT_MEM          IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
297
298 void ZapImage::AllocateVirtualSections()
299 {
300     //
301     // Allocate all virtual sections in the order they will appear in the final image
302     //
303     // To maximize packing of the data in the native image, the number of named physical sections is minimized -  
304     // the named physical sections are used just for memory protection control. All items with the same memory
305     // protection are packed together in one physical section.
306     //
307
308     {
309         //
310         // .data section
311         //
312         DWORD access = DATA_MEM_WRITABLE;
313
314 #ifdef FEATURE_LAZY_COW_PAGES
315         // READYTORUN: FUTURE: Optional support for COW pages
316         if (!IsReadyToRunCompilation() && CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ZapLazyCOWPagesEnabled))
317             access = DATA_MEM_READONLY;
318 #endif
319
320         ZapPhysicalSection * pDataSection = NewPhysicalSection(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | access);
321
322         m_pPreloadSections[CORCOMPILE_SECTION_MODULE] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | ModuleSection);
323
324         m_pEETableSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | EETableSection); // Could be marked bss if it makes sense
325
326         // These are all known to be hot or writeable
327         m_pPreloadSections[CORCOMPILE_SECTION_WRITE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteDataSection);
328         m_pPreloadSections[CORCOMPILE_SECTION_HOT_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteableDataSection); // hot for reading, potentially written to 
329         m_pPreloadSections[CORCOMPILE_SECTION_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | WriteableDataSection); // Cold based on IBC profiling data.
330         m_pPreloadSections[CORCOMPILE_SECTION_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | DataSection);
331
332         m_pPreloadSections[CORCOMPILE_SECTION_RVA_STATICS_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | RVAStaticsSection);
333
334         m_pDelayLoadInfoTableSection[ZapImportSectionType_Eager] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | DelayLoadInfoTableEagerSection, sizeof(TADDR));
335
336         //
337         // Allocate dynamic info tables
338         //
339
340         // Place the HOT CorCompileTables now, the cold ones would be placed later in this routine (after other HOT sections)
341         for (int i=0; i<ZapImportSectionType_Count; i++)
342         {
343             m_pDelayLoadInfoTableSection[i] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | DelayLoadInfoTableSection, sizeof(TADDR));
344         }
345
346         m_pDynamicHelperCellSection = NewVirtualSection(pDataSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(TADDR));
347
348         m_pExternalMethodCellSection = NewVirtualSection(pDataSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodThunkSection, sizeof(TADDR));
349
350         // m_pStubDispatchCellSection is  deliberately placed  directly after
351         // the last m_pDelayLoadInfoTableSection (all .data sections go together in the order indicated).
352         // We do this to place it as the last "hot, written" section.  Why? Because
353         // we don't split the dispatch cells into hot/cold sections (We probably should),
354         // and so the section is actually half hot and half cold.
355         // But it turns out that the hot dispatch cells always come
356         // first (because the code that uses them is hot and gets compiled first).
357         // Thus m_pStubDispatchCellSection contains all hot cells at the front of
358         // this blob of data.  By making them last in a grouping of written data we
359         // make sure the hot data is grouped with hot data in the
360         // m_pDelayLoadInfoTableSection sections.
361
362         m_pStubDispatchCellSection = NewVirtualSection(pDataSection, IBCProfiledSection | HotColdSortedRange | StubDispatchDataSection, sizeof(TADDR));
363
364         // Earlier we placed the HOT corCompile tables. Now place the cold ones after the stub dispatch cell section. 
365         for (int i=0; i<ZapImportSectionType_Count; i++)
366         {
367             m_pDelayLoadInfoTableSection[ZapImportSectionType_Cold + i] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | DelayLoadInfoTableSection, sizeof(TADDR));
368         }
369
370         //
371         // Virtual sections that are moved to .cdata when we have profile data.
372         //
373
374         // This is everyhing that is assumed to be warm in the first strata
375         // of non-profiled scenarios.  MethodTables related to objects etc.
376         m_pPreloadSections[CORCOMPILE_SECTION_WARM] = NewVirtualSection(pDataSection, IBCProfiledSection | WarmRange | EEDataSection, sizeof(TADDR));
377
378         m_pPreloadSections[CORCOMPILE_SECTION_RVA_STATICS_COLD] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | RVAStaticsSection);
379
380         // In an ideal world these are cold in both profiled and the first strata
381         // of non-profiled scenarios (i.e. no reflection, etc. )  The sections at the
382         // bottom correspond to further strata of non-profiled scenarios.
383         m_pPreloadSections[CORCOMPILE_SECTION_CLASS_COLD] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | ClassSection, sizeof(TADDR));
384         m_pPreloadSections[CORCOMPILE_SECTION_CROSS_DOMAIN_INFO] = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | CrossDomainInfoSection, sizeof(TADDR));
385         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_DESC_COLD] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | MethodDescSection, sizeof(TADDR));
386         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_DESC_COLD_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | MethodDescWriteableSection, sizeof(TADDR));
387         m_pPreloadSections[CORCOMPILE_SECTION_MODULE_COLD] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | ModuleSection, sizeof(TADDR));
388         m_pPreloadSections[CORCOMPILE_SECTION_DEBUG_COLD] = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | DebugSection, sizeof(TADDR));
389
390         //
391         // If we're instrumenting allocate a section for writing profile data
392         //
393         if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR))
394         {
395             m_pInstrumentSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | InstrumentSection, sizeof(TADDR));
396         }
397     }
398
399     // No RWX pages in ready to run images
400     if (!IsReadyToRunCompilation())
401     {
402         DWORD access = XDATA_MEM;
403
404 #ifdef FEATURE_LAZY_COW_PAGES
405         if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ZapLazyCOWPagesEnabled))
406             access = TEXT_MEM;
407 #endif            
408
409         //
410         // .xdata section
411         //
412         ZapPhysicalSection * pXDataSection  = NewPhysicalSection(".xdata", IMAGE_SCN_CNT_INITIALIZED_DATA | access);
413
414         // Some sections are placed in a sorted order. Hot items are placed first,
415         // then cold items. These sections are marked as HotColdSortedRange since
416         // they are neither completely hot, nor completely cold. 
417         m_pVirtualImportThunkSection        = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | VirtualImportThunkSection, HELPER_TABLE_ALIGN);
418         m_pExternalMethodThunkSection       = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodThunkSection, HELPER_TABLE_ALIGN);
419         m_pHelperTableSection               = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange| HelperTableSection, HELPER_TABLE_ALIGN);
420
421         // hot for writing, i.e. profiling has indicated a write to this item, so at least one write likely per item at some point
422         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_WRITE] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeWriteSection, sizeof(TADDR));
423         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_HOT] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeSection, sizeof(TADDR));
424
425         //
426         // cold sections
427         //
428         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeSection, sizeof(TADDR));
429         m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD_WRITEABLE] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeWriteableSection, sizeof(TADDR));
430     }
431
432     {
433         // code:NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod and code:NativeImageJitManager::GetFunctionEntry expects 
434         // sentinel value right after end of .pdata section. 
435         static const DWORD dwRuntimeFunctionSectionSentinel = (DWORD)-1;
436
437
438         //
439         // .text section
440         //
441 #if defined(_TARGET_ARM_)
442         // for ARM, put the resource section at the end if it's very large - this
443         // is because b and bl instructions have a limited distance range of +-16MB
444         // which we should not exceed if we can avoid it.
445         // we draw the limit at 1 MB resource size, somewhat arbitrarily
446         COUNT_T resourceSize;
447         m_ModuleDecoder.GetResources(&resourceSize);
448         BOOL bigResourceSection = resourceSize >= 1024*1024;
449 #endif
450         ZapPhysicalSection * pTextSection = NewPhysicalSection(".text", IMAGE_SCN_CNT_CODE | TEXT_MEM);
451         m_pTextSection = pTextSection;
452
453         // Marked as HotRange since it contains items that are always touched by
454         // the OS during NGEN image loading (i.e. VersionInfo) 
455         m_pWin32ResourceSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | Win32ResourcesSection);
456
457         // Marked as a HotRange since it is always touched during Ngen image load. 
458         m_pHeaderSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HeaderSection);
459
460         // Marked as a HotRange since it is always touched during Ngen image binding.
461         m_pMetaDataSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | MetadataSection);
462
463         m_pImportTableSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | ImportTableSection, sizeof(DWORD));
464
465         m_pDelayLoadInfoDelayListSectionEager = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD));
466
467         //
468         // GC Info for methods which were profiled hot AND had their GC Info touched during profiling
469         //
470         m_pHotTouchedGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | GCInfoSection, sizeof(DWORD));
471
472         m_pLazyHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN);
473         m_pLazyHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT);
474
475         m_pLazyMethodCallHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN);
476         m_pLazyMethodCallHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT);
477
478         int codeSectionAlign = DEFAULT_CODE_ALIGN;
479
480         m_pHotCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeSection, codeSectionAlign);
481         m_pHotCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT);
482
483 #if defined(WIN64EXCEPTIONS)
484         m_pHotUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | UnwindDataSection, sizeof(DWORD)); // .rdata area
485
486         // All RuntimeFunctionSections have to be together for WIN64EXCEPTIONS
487         m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD));  // .pdata area
488         m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange  | ColdRange | RuntimeFunctionSection, sizeof(DWORD));
489         m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD));
490
491         // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification 
492         NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD))
493             ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD)));
494 #endif  // defined(WIN64EXCEPTIONS)
495
496         m_pStubsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubsSection);
497         m_pReadOnlyDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ReadonlyDataSection);
498
499         m_pDynamicHelperDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD));
500         m_pExternalMethodDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD));
501         m_pStubDispatchDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubDispatchDataSection, sizeof(DWORD));
502
503         m_pHotRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD));
504 #if !defined(WIN64EXCEPTIONS)
505         m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD));
506
507         // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification 
508         NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD))
509             ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD)));
510 #endif
511         m_pHotCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeManagerSection, sizeof(DWORD));
512
513         m_pDelayLoadInfoDelayListSectionHot = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD));
514
515         //
516         // The hot set of read-only data structures.  Note that read-only data structures are the things that we can (and aggressively do) intern
517         // to share between different owners.  However, this can have a bad interaction with IBC, which performs its ordering optimizations without
518         // knowing that NGen may jumble around layout with interning.  Thankfully, it is a relatively small percentage of the items that are duplicates
519         // (many of them used a great deal to add up to large interning savings).  This means that we can track all of the interned items for which we
520         // actually find any duplicates and put those in a small section.  For the rest, where there wasn't a duplicate in the entire image, we leave the
521         // singleton in its normal place in the READONLY_HOT section, which was selected carefully by IBC.
522         //
523         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_SHARED_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySharedSection, sizeof(TADDR));
524         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySection, sizeof(TADDR));
525
526         //
527         // GC Info for methods which were touched during profiling but didn't explicitly have
528         // their GC Info touched during profiling
529         //
530         m_pHotGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | GCInfoSection, sizeof(DWORD));
531
532 #if !defined(_TARGET_ARM_)
533         // For ARM, put these sections more towards the end because bl/b instructions have limited diplacement
534
535         // IL
536         m_pILSection  = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD));
537
538         //ILMetadata/Resources sections are reported as a statically known warm ranges for now.
539         m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD));
540 #endif  // _TARGET_ARM_
541
542 #if defined(_TARGET_ARM_)
543         if (!bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above
544 #endif
545             m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection);
546
547         //
548         // Allocate the unprofiled code section and code manager nibble map here
549         //
550         m_pCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeSection, codeSectionAlign);
551         m_pCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT);
552
553         m_pRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD));
554 #if !defined(WIN64EXCEPTIONS)
555         m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange  | ColdRange | RuntimeFunctionSection, sizeof(DWORD));
556
557         // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification 
558         NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange  | ColdRange | RuntimeFunctionSection, sizeof(DWORD))
559             ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD)));
560 #endif
561         m_pCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeHeaderSection,sizeof(DWORD));
562
563 #ifdef FEATURE_READYTORUN_COMPILER
564         if (IsReadyToRunCompilation())
565         {
566             m_pAvailableTypesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ReadonlySection);
567         }
568 #endif    
569
570 #if defined(WIN64EXCEPTIONS)
571         m_pUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | UnwindDataSection, sizeof(DWORD));
572 #endif // defined(WIN64EXCEPTIONS)
573
574         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_WARM] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, sizeof(TADDR));
575         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_VCHUNKS] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, sizeof(TADDR));
576         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_DICTIONARY] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, sizeof(TADDR));
577
578         //
579         // GC Info for methods which were not touched in profiling
580         //
581         m_pGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | GCInfoSection, sizeof(DWORD));
582
583         m_pDelayLoadInfoDelayListSectionCold = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | DelayLoadInfoDelayListSection, sizeof(DWORD));
584
585         m_pPreloadSections[CORCOMPILE_SECTION_READONLY_COLD] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | ReadonlySection, sizeof(TADDR));
586
587         //
588         // Allocate the cold code section near the end of the image
589         //
590         m_pColdCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeSection, codeSectionAlign);
591         m_pColdCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT);
592
593 #if defined(_TARGET_ARM_)
594         // For ARM, put these sections more towards the end because bl/b instructions have limited diplacement
595
596         // IL
597         m_pILSection  = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD));
598
599         //ILMetadata/Resources sections are reported as a statically known warm ranges for now.
600         m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD));
601
602         if (bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above
603             m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection);
604 #endif // _TARGET_ARM_
605         m_pColdCodeMapSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeManagerSection, sizeof(DWORD));
606
607 #if !defined(WIN64EXCEPTIONS)
608         m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD));
609
610         // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification 
611         NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD))
612             ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD)));
613 #endif
614
615 #if defined(WIN64EXCEPTIONS)
616         m_pColdUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | UnwindDataSection, sizeof(DWORD));
617 #endif // defined(WIN64EXCEPTIONS)
618
619         //
620         // Allocate space for compressed LookupMaps (ridmaps). This needs to come after the .data physical
621         // section (which is currently true for the .text section) and late enough in the .text section to be
622         // after any structure referenced by the LookupMap (current MethodTables and MethodDescs). This is a
623         // hard requirement since the compression algorithm requires that all referenced data structures have
624         // been laid out by the time we come to lay out the compressed nodes.
625         //
626         m_pPreloadSections[CORCOMPILE_SECTION_COMPRESSED_MAPS] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | CompressedMapsSection, sizeof(DWORD));
627
628         m_pExceptionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExceptionSection, sizeof(DWORD));
629
630         //
631         // Debug info is sometimes used during exception handling to build stacktrace
632         //
633         m_pDebugSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | ColdRange | DebugSection, sizeof(DWORD));
634     }
635
636     {
637         //
638         // .reloc section
639         //
640
641         ZapPhysicalSection * pRelocSection = NewPhysicalSection(".reloc", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ);
642
643         // .reloc section is always read by the OS when the image is opted in ASLR
644         // (Vista+ default behavior). 
645         m_pBaseRelocsSection = NewVirtualSection(pRelocSection, IBCUnProfiledSection | HotRange | BaseRelocsSection);
646
647     }
648 }
649
650 void ZapImage::Preallocate()
651 {
652     COUNT_T cbILImage = m_ModuleDecoder.GetSize();
653
654     // Curb the estimate to handle corner cases gracefuly
655     cbILImage = min(cbILImage, 50000000);
656
657     PREALLOCATE_HASHTABLE(ZapImage::m_CompiledMethods, 0.0050, cbILImage);
658     PREALLOCATE_HASHTABLE(ZapImage::m_ClassLayoutOrder, 0.0003, cbILImage);
659
660     //
661     // Preallocation of auxiliary tables in alphabetical order
662     //
663     m_pImportTable->Preallocate(cbILImage);
664     m_pInnerPtrs->Preallocate(cbILImage);
665     m_pMethodEntryPoints->Preallocate(cbILImage);
666     m_pWrappers->Preallocate(cbILImage);
667
668     if (m_pILMetaData != NULL)
669         m_pILMetaData->Preallocate(cbILImage);
670     m_pGCInfoTable->Preallocate(cbILImage);
671 #ifdef WIN64EXCEPTIONS
672     m_pUnwindDataTable->Preallocate(cbILImage);
673 #endif // WIN64EXCEPTIONS
674     m_pDebugInfoTable->Preallocate(cbILImage);
675 }
676
677 void ZapImage::SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo)
678 {
679     m_pVersionInfo = new (GetHeap()) ZapVersionInfo(pVersionInfo);
680     m_pHeaderSection->Place(m_pVersionInfo);
681 }
682
683 void ZapImage::SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies)
684 {
685     m_pDependencies = new (GetHeap()) ZapDependencies(pDependencies, cDependencies);
686     m_pHeaderSection->Place(m_pDependencies);
687 }
688
689 void ZapImage::SetPdbFileName(const SString &strFileName)
690 {
691     m_pdbFileName.Set(strFileName);
692 }
693
694 #ifdef WIN64EXCEPTIONS
695 void ZapImage::SetRuntimeFunctionsDirectoryEntry()
696 {
697     //
698     // Runtime functions span multiple virtual sections and so there is no natural ZapNode * to cover them all.
699     // Create dummy ZapNode * that covers them all for IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry.
700     //
701     ZapVirtualSection * rgRuntimeFunctionSections[] = {
702         m_pHotRuntimeFunctionSection,
703         m_pRuntimeFunctionSection,
704         m_pColdRuntimeFunctionSection
705     };
706
707     DWORD dwTotalSize = 0, dwStartRVA = (DWORD)-1, dwEndRVA = 0;
708
709     for (size_t i = 0; i < _countof(rgRuntimeFunctionSections); i++)
710     {
711         ZapVirtualSection * pSection = rgRuntimeFunctionSections[i];
712
713         DWORD dwSize = pSection->GetSize();
714         if (dwSize == 0)
715             continue;
716
717         DWORD dwRVA = pSection->GetRVA();
718
719         dwTotalSize += dwSize;
720
721         dwStartRVA = min(dwStartRVA, dwRVA);
722         dwEndRVA = max(dwEndRVA, dwRVA + dwSize);
723     }
724
725     if (dwTotalSize != 0)
726     {
727         // Verify that there are no holes between the sections
728         _ASSERTE(dwStartRVA + dwTotalSize == dwEndRVA);
729
730         ZapNode * pAllRuntimeFunctionSections = new (GetHeap()) ZapDummyNode(dwTotalSize);
731         pAllRuntimeFunctionSections->SetRVA(dwStartRVA);
732
733         // Write the address of the sorted pdata to the optionalHeader.DataDirectory
734         SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION, pAllRuntimeFunctionSections);
735     }
736 }
737 #endif // WIN64EXCEPTIONS
738
739 // Assign RVAs to all ZapNodes
740 void ZapImage::ComputeRVAs()
741 {
742     ZapWriter::ComputeRVAs();
743
744     if (!IsReadyToRunCompilation())
745     {
746         m_pMethodEntryPoints->Resolve();
747         m_pWrappers->Resolve();
748     }
749
750     m_pInnerPtrs->Resolve();
751
752 #ifdef WIN64EXCEPTIONS
753     SetRuntimeFunctionsDirectoryEntry();
754 #endif
755
756 #if defined(_DEBUG) 
757 #ifdef FEATURE_SYMDIFF
758     if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SymDiffDump))
759     {
760         COUNT_T curMethod = 0;
761         COUNT_T numMethods = m_MethodCompilationOrder.GetCount();
762
763         for (; curMethod < numMethods; curMethod++)
764         {
765             bool fCold = false;
766             //if(curMethod >= m_iUntrainedMethod) fCold = true;
767                 
768             ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod];
769
770             ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode;
771             if (pCode == NULL)
772             {            
773                 continue;
774             }
775             CORINFO_METHOD_HANDLE handle = pMethod->GetHandle();
776             mdMethodDef token;
777             GetCompileInfo()->GetMethodDef(handle, &token);
778             GetSvcLogger()->Printf(W("(EntryPointRVAMap (MethodToken %0X) (RVA %0X) (SIZE %0X))\n"), token, pCode->GetRVA(), pCode->GetSize()); 
779         }
780
781     }
782 #endif // FEATURE_SYMDIFF 
783 #endif //_DEBUG
784 }
785
786 class ZapFileStream : public IStream
787 {
788     HANDLE  m_hFile;
789     MD5 m_hasher;
790
791 public:
792     ZapFileStream()
793         : m_hFile(INVALID_HANDLE_VALUE)
794     {
795         m_hasher.Init();
796     }
797
798     ~ZapFileStream()
799     {
800         Close();
801     }
802
803     void SetHandle(HANDLE hFile)
804     {
805         _ASSERTE(m_hFile == INVALID_HANDLE_VALUE);
806         m_hFile = hFile;
807     }
808
809     // IUnknown methods:
810     STDMETHODIMP_(ULONG) AddRef()
811     {
812         return 1;
813     }
814
815     STDMETHODIMP_(ULONG) Release()
816     {
817         return 1;
818     }
819
820     STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)
821     {
822         HRESULT hr = S_OK;
823         if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) {
824             *ppv = static_cast<IStream *>(this);
825         }
826         else {
827             hr = E_NOINTERFACE;
828         }
829         return hr;
830     }
831
832     // ISequentialStream methods:
833     STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead)
834     {
835         _ASSERTE(false);
836         return E_NOTIMPL;
837     }
838
839     STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten)
840     {
841         HRESULT hr = S_OK;
842
843         _ASSERTE(m_hFile != INVALID_HANDLE_VALUE);
844
845         m_hasher.HashMore(pv, cb);
846
847         // We are calling with lpOverlapped == NULL so pcbWritten has to be present
848         // to prevent crashes in Win7 and below.
849         _ASSERTE(pcbWritten);
850
851         if (!::WriteFile(m_hFile, pv, cb, pcbWritten, NULL))
852         {
853             hr = HRESULT_FROM_GetLastError();
854             goto Exit;
855         }
856
857     Exit:
858         return hr;
859     }
860
861     // IStream methods:
862     STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
863     {
864         HRESULT hr = S_OK;        
865
866         _ASSERTE(m_hFile != INVALID_HANDLE_VALUE);
867
868         DWORD dwFileOrigin;
869         switch (dwOrigin) {
870             case STREAM_SEEK_SET:
871                 dwFileOrigin = FILE_BEGIN;
872                 break;
873                 
874             case STREAM_SEEK_CUR:
875                 dwFileOrigin = FILE_CURRENT;
876                 break;
877                 
878             case STREAM_SEEK_END:
879                 dwFileOrigin = FILE_END;
880                 break;
881                 
882             default:
883                 hr = E_UNEXPECTED;
884                 goto Exit;
885         }
886         if (!::SetFilePointerEx(m_hFile, dlibMove, (LARGE_INTEGER *)plibNewPosition, dwFileOrigin))
887         {
888             hr = HRESULT_FROM_GetLastError();
889             goto Exit;
890         }
891
892     Exit:
893         return hr;
894     }
895
896     STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize)
897     {
898         HRESULT hr = S_OK;
899
900         _ASSERTE(m_hFile != INVALID_HANDLE_VALUE);
901
902         hr = Seek(*(LARGE_INTEGER *)&libNewSize, FILE_BEGIN, NULL);
903         if (FAILED(hr))
904         {
905             goto Exit;
906         }
907
908         if (!::SetEndOfFile(m_hFile))
909         {
910             hr = HRESULT_FROM_GetLastError();
911             goto Exit;
912         }
913
914     Exit:
915         return hr;
916     }
917
918     STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
919     {
920         _ASSERTE(false);
921         return E_NOTIMPL;
922     }
923
924     STDMETHODIMP Commit(DWORD grfCommitFlags)
925     {
926         _ASSERTE(false);
927         return E_NOTIMPL;
928     }
929
930     STDMETHODIMP Revert()
931     {
932         _ASSERTE(false);
933         return E_NOTIMPL;
934     }
935
936     STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
937     {
938         _ASSERTE(false);
939         return E_NOTIMPL;
940     }
941
942     STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
943     {
944         _ASSERTE(false);
945         return E_NOTIMPL;
946     }
947
948     STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag)
949     {
950         _ASSERTE(false);
951         return E_NOTIMPL;
952     }
953
954     STDMETHODIMP Clone(IStream **ppIStream)
955     {
956         _ASSERTE(false);
957         return E_NOTIMPL;
958     }
959
960     HRESULT Close()
961     {
962         HRESULT hr = S_OK;
963
964         HANDLE hFile = m_hFile;
965         if (hFile != INVALID_HANDLE_VALUE)
966         {
967             m_hFile = INVALID_HANDLE_VALUE;
968
969             if (!::CloseHandle(hFile))
970             {
971                 hr = HRESULT_FROM_GetLastError();
972                 goto Exit;
973             }
974         }
975
976     Exit:
977         return hr;
978     }
979
980     void SuppressClose()
981     {
982         m_hFile = INVALID_HANDLE_VALUE;
983     }
984
985     void GetHash(MD5HASHDATA* pHash)
986     {
987         m_hasher.GetHashValue(pHash);
988     }
989 };
990
991 HANDLE ZapImage::GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig)
992 {
993     ZapFileStream outputStream;
994
995     HANDLE hFile = WszCreateFile(wszOutputFileName,
996                         GENERIC_READ | GENERIC_WRITE,
997                         FILE_SHARE_READ | FILE_SHARE_DELETE,
998                         NULL,
999                         CREATE_ALWAYS,
1000                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
1001                         NULL);
1002
1003     if (hFile == INVALID_HANDLE_VALUE)
1004         ThrowLastError();
1005
1006     outputStream.SetHandle(hFile);
1007
1008     Save(&outputStream);
1009
1010     LARGE_INTEGER filePos;
1011
1012     if (m_pNativeHeader != NULL)
1013     {
1014         // Write back the updated CORCOMPILE_HEADER (relocs and guid is not correct the first time around)
1015         filePos.QuadPart = m_pTextSection->GetFilePos() + 
1016             (m_pNativeHeader->GetRVA() - m_pTextSection->GetRVA());
1017         IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL));
1018         m_pNativeHeader->Save(this);
1019         FlushWriter();
1020     }
1021
1022     GUID signature = {0};
1023
1024     static_assert_no_msg(sizeof(GUID) == sizeof(MD5HASHDATA));
1025     outputStream.GetHash((MD5HASHDATA*)&signature);
1026
1027     {    
1028         // Write the debug directory entry for the NGEN PDB
1029         RSDS rsds = {0};
1030         
1031         rsds.magic = 'SDSR';
1032         rsds.age = 1;
1033         // our PDB signature will be the same as our NGEN signature.  
1034         // However we want the printed version of the GUID to be be the same as the
1035         // byte dump of the signature so we swap bytes to make this work.  
1036         // 
1037         // * See code:CCorSvcMgr::CreatePdb for where this is used.
1038         BYTE* asBytes = (BYTE*) &signature;
1039         rsds.signature.Data1 = ((asBytes[0] * 256 + asBytes[1]) * 256 + asBytes[2]) * 256 + asBytes[3];
1040         rsds.signature.Data2 = asBytes[4] * 256 + asBytes[5];
1041         rsds.signature.Data3 = asBytes[6] * 256 + asBytes[7];
1042         memcpy(&rsds.signature.Data4, &asBytes[8], 8);
1043
1044         _ASSERTE(!m_pdbFileName.IsEmpty());
1045         ZeroMemory(&rsds.path[0], sizeof(rsds.path));
1046         if (WideCharToMultiByte(CP_UTF8, 
1047                                 0, 
1048                                 m_pdbFileName.GetUnicode(),
1049                                 m_pdbFileName.GetCount(), 
1050                                 &rsds.path[0], 
1051                                 sizeof(rsds.path) - 1, // -1 to keep the buffer zero terminated
1052                                 NULL, 
1053                                 NULL) == 0)
1054             ThrowHR(E_FAIL);
1055         
1056         ULONG cbWritten = 0;
1057         filePos.QuadPart = m_pTextSection->GetFilePos() + (m_pNGenPdbDebugData->GetRVA() - m_pTextSection->GetRVA());
1058         IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL));
1059         IfFailThrow(outputStream.Write(&rsds, sizeof rsds, &cbWritten));
1060     }
1061
1062     if (m_pVersionInfo != NULL)
1063     {
1064         ULONG cbWritten;
1065
1066         filePos.QuadPart = m_pTextSection->GetFilePos() + 
1067             (m_pVersionInfo->GetRVA() - m_pTextSection->GetRVA()) + 
1068             offsetof(CORCOMPILE_VERSION_INFO, signature);
1069         IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL));
1070         IfFailThrow(outputStream.Write(&signature, sizeof(signature), &cbWritten));
1071
1072         if (pNativeImageSig != NULL)
1073             *pNativeImageSig = signature;
1074     }
1075     else
1076     {
1077         _ASSERTE(pNativeImageSig == NULL);
1078     }
1079
1080     outputStream.SuppressClose();
1081     return hFile;
1082 }
1083
1084
1085 HANDLE ZapImage::SaveImage(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig)
1086 {
1087     if (!IsReadyToRunCompilation())
1088     {
1089         OutputManifestMetadata();
1090     }
1091
1092     OutputTables();
1093
1094     // Create a empty export table.  This makes tools like symchk not think
1095     // that native images are resoure-only DLLs.  It is important to NOT
1096     // be a resource-only DLL because those DLL's PDBS are not put up on the
1097     // symbol server and we want NEN PDBS to be placed there.  
1098     ZapPEExports* exports = new(GetHeap()) ZapPEExports(wszOutputFileName);
1099     m_pDebugSection->Place(exports);
1100     SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT, exports);
1101     
1102     ComputeRVAs();
1103
1104     if (!IsReadyToRunCompilation())
1105     {
1106         m_pPreloader->FixupRVAs();
1107     }
1108
1109     HANDLE hFile = GenerateFile(wszOutputFileName, pNativeImageSig);
1110
1111     if (m_zapper->m_pOpt->m_verbose)
1112     {
1113         PrintStats(wszOutputFileName);
1114     }
1115
1116     return hFile;
1117 }
1118
1119 void ZapImage::PrintStats(LPCWSTR wszOutputFileName)
1120 {
1121 #define ACCUM_SIZE(dest, src) if( src != NULL ) dest+= src->GetSize()
1122     ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotTouchedGCSection);
1123     ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotGCSection);
1124     ACCUM_SIZE(m_stats->m_gcInfoSize, m_pGCSection);
1125 #if defined(WIN64EXCEPTIONS)
1126     ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pUnwindDataSection);
1127     ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pHotRuntimeFunctionSection);
1128     ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pRuntimeFunctionSection);
1129     ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pColdRuntimeFunctionSection);
1130 #endif // defined(WIN64EXCEPTIONS)
1131
1132     //
1133     // Get the size of the input & output files
1134     //
1135
1136     {
1137         WIN32_FIND_DATA inputData;
1138         FindHandleHolder inputHandle = WszFindFirstFile(m_pModuleFileName, &inputData);
1139         if (inputHandle != INVALID_HANDLE_VALUE)
1140             m_stats->m_inputFileSize = inputData.nFileSizeLow;
1141     }
1142
1143     {
1144         WIN32_FIND_DATA outputData;
1145         FindHandleHolder outputHandle = WszFindFirstFile(wszOutputFileName, &outputData);
1146         if (outputHandle != INVALID_HANDLE_VALUE)
1147             m_stats->m_outputFileSize = outputData.nFileSizeLow;
1148     }
1149
1150     ACCUM_SIZE(m_stats->m_metadataSize, m_pAssemblyMetaData);
1151
1152     DWORD dwPreloadSize = 0;
1153     for (int iSection = 0; iSection < CORCOMPILE_SECTION_COUNT; iSection++)
1154         ACCUM_SIZE(dwPreloadSize, m_pPreloadSections[iSection]);
1155     m_stats->m_preloadImageSize = dwPreloadSize;
1156
1157     ACCUM_SIZE(m_stats->m_hotCodeMgrSize, m_pHotCodeMethodDescsSection);
1158     ACCUM_SIZE(m_stats->m_unprofiledCodeMgrSize, m_pCodeMethodDescsSection);
1159     ACCUM_SIZE(m_stats->m_coldCodeMgrSize, m_pHotRuntimeFunctionLookupSection);
1160
1161     ACCUM_SIZE(m_stats->m_eeInfoTableSize, m_pEEInfoTable);
1162     ACCUM_SIZE(m_stats->m_helperTableSize, m_pHelperTableSection);
1163     ACCUM_SIZE(m_stats->m_dynamicInfoTableSize, m_pImportSectionsTable);
1164
1165     ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionEager);
1166     ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionHot);
1167     ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionCold);
1168
1169     ACCUM_SIZE(m_stats->m_importTableSize, m_pImportTable);
1170
1171     ACCUM_SIZE(m_stats->m_debuggingTableSize, m_pDebugSection);
1172     ACCUM_SIZE(m_stats->m_headerSectionSize, m_pGCSection);
1173     ACCUM_SIZE(m_stats->m_codeSectionSize, m_pHotCodeSection);
1174     ACCUM_SIZE(m_stats->m_coldCodeSectionSize, m_pColdCodeSection);
1175     ACCUM_SIZE(m_stats->m_exceptionSectionSize, m_pExceptionSection);
1176     ACCUM_SIZE(m_stats->m_readOnlyDataSectionSize, m_pReadOnlyDataSection);
1177     ACCUM_SIZE(m_stats->m_relocSectionSize, m_pBaseRelocsSection);
1178     ACCUM_SIZE(m_stats->m_ILMetadataSize, m_pILMetaData);
1179     ACCUM_SIZE(m_stats->m_virtualImportThunkSize, m_pVirtualImportThunkSection);
1180     ACCUM_SIZE(m_stats->m_externalMethodThunkSize, m_pExternalMethodThunkSection);
1181     ACCUM_SIZE(m_stats->m_externalMethodDataSize, m_pExternalMethodDataSection);
1182 #undef ACCUM_SIZE
1183
1184     if (m_stats->m_failedMethods)
1185         m_zapper->Warning(W("Warning: %d methods (%d%%) could not be compiled.\n"),
1186                           m_stats->m_failedMethods, (m_stats->m_failedMethods*100) / m_stats->m_methods);
1187     if (m_stats->m_failedILStubs)
1188         m_zapper->Warning(W("Warning: %d IL STUB methods could not be compiled.\n"),
1189                           m_stats->m_failedMethods);
1190     m_stats->PrintStats();
1191 }
1192
1193 // Align native images to 64K
1194 const SIZE_T BASE_ADDRESS_ALIGNMENT  = 0xffff;
1195 const double CODE_EXPANSION_FACTOR   =  3.6;
1196
1197 void ZapImage::CalculateZapBaseAddress()
1198 {
1199     static SIZE_T nextBaseAddressForMultiModule;
1200
1201     SIZE_T baseAddress = 0;
1202
1203     {
1204         // Read the actual preferred base address from the disk
1205
1206         // Note that we are reopening the file here. We are not guaranteed to get the same file.
1207         // The worst thing that can happen is that we will read a bogus preferred base address from the file.
1208         HandleHolder hFile(WszCreateFile(m_pModuleFileName,
1209                                             GENERIC_READ,
1210                                             FILE_SHARE_READ|FILE_SHARE_DELETE,
1211                                             NULL,
1212                                             OPEN_EXISTING,
1213                                             FILE_ATTRIBUTE_NORMAL,
1214                                             NULL));
1215         if (hFile == INVALID_HANDLE_VALUE)
1216             ThrowLastError();
1217
1218         HandleHolder hFileMap(WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL));
1219         if (hFileMap == NULL)
1220             ThrowLastError();
1221
1222         MapViewHolder base(MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0));
1223         if (base == NULL)
1224             ThrowLastError();
1225     
1226         DWORD dwFileLen = SafeGetFileSize(hFile, 0);
1227         if (dwFileLen == INVALID_FILE_SIZE)
1228             ThrowLastError();
1229
1230         PEDecoder peFlat((void *)base, (COUNT_T)dwFileLen);
1231
1232         baseAddress = (SIZE_T) peFlat.GetPreferredBase();
1233     }
1234
1235     // See if the header has the linker's default preferred base address
1236     if (baseAddress == (SIZE_T) 0x00400000)
1237     {
1238         if (m_fManifestModule)
1239         {
1240             // Set the base address for the main assembly with the manifest
1241         
1242             if (!m_ModuleDecoder.IsDll())
1243             {
1244 #if defined(_TARGET_X86_)
1245                 // We use 30000000 for an exe
1246                 baseAddress = 0x30000000;
1247 #elif defined(_TARGET_64BIT_)
1248                 // We use 04000000 for an exe
1249                 // which is remapped to 0x642`88000000 on x64
1250                 baseAddress = 0x04000000;
1251 #endif
1252             }
1253             else
1254             {
1255 #if defined(_TARGET_X86_)
1256                 // We start a 31000000 for the main assembly with the manifest
1257                 baseAddress = 0x31000000;
1258 #elif defined(_TARGET_64BIT_)
1259                 // We start a 05000000 for the main assembly with the manifest
1260                 // which is remapped to 0x642`8A000000 on x64
1261                 baseAddress = 0x05000000;
1262 #endif
1263             }
1264         }
1265         else // is dependent assembly of a multi-module assembly
1266         {
1267             // Set the base address for a dependant multi module assembly
1268                 
1269             // We should have already set the nextBaseAddressForMultiModule
1270             // when we compiled the manifest module
1271             _ASSERTE(nextBaseAddressForMultiModule != 0);
1272             baseAddress = nextBaseAddressForMultiModule;
1273         }
1274     }
1275     else 
1276     {
1277         //
1278         // For some assemblies we have to move the ngen image base address up
1279         // past the end of IL image so that that we don't have a conflict.
1280         //
1281         // CoreCLR currently always loads both the IL and the native image, so
1282         // move the native image out of the way.
1283         {
1284             baseAddress += m_ModuleDecoder.GetVirtualSize();
1285         }
1286     }
1287
1288     // Round to a multiple of 64K
1289     // 64K is the allocation granularity of VirtualAlloc. (Officially this number is not a constant -
1290     // we should be querying the system for its allocation granularity, but we do this all over the place
1291     // currently.)
1292
1293     baseAddress = (baseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT;
1294
1295     //
1296     // Calculate the nextBaseAddressForMultiModule
1297     //
1298     SIZE_T tempBaseAddress = baseAddress;
1299     tempBaseAddress += (SIZE_T) (CODE_EXPANSION_FACTOR * (double) m_ModuleDecoder.GetVirtualSize());
1300     tempBaseAddress += BASE_ADDRESS_ALIGNMENT;
1301     tempBaseAddress = (tempBaseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT;
1302     
1303     nextBaseAddressForMultiModule = tempBaseAddress;
1304
1305     //
1306     // Now we remap the 32-bit address range used for x86 and PE32 images into thre
1307     // upper address range used on 64-bit platforms
1308     //
1309 #if USE_UPPER_ADDRESS
1310 #if defined(_TARGET_64BIT_)
1311     if (baseAddress < 0x80000000)
1312     {
1313         if (baseAddress < 0x40000000)
1314             baseAddress += 0x40000000; // We map [00000000..3fffffff] to [642'80000000..642'ffffffff]
1315         else
1316             baseAddress -= 0x40000000; // We map [40000000..7fffffff] to [642'00000000..642'7fffffff]
1317
1318         baseAddress *= UPPER_ADDRESS_MAPPING_FACTOR;
1319         baseAddress += CLR_UPPER_ADDRESS_MIN;
1320     }
1321 #endif
1322 #endif
1323
1324
1325     // Apply the calculated base address.
1326     SetBaseAddress(baseAddress);
1327
1328     m_NativeBaseAddress = baseAddress;
1329 }
1330
1331 void ZapImage::Open(CORINFO_MODULE_HANDLE hModule,
1332                         IMetaDataAssemblyEmit *pEmit)
1333 {
1334     m_hModule   = hModule;
1335     m_fManifestModule = (hModule == m_zapper->m_pEECompileInfo->GetAssemblyModule(m_zapper->m_hAssembly));
1336
1337     m_ModuleDecoder = *m_zapper->m_pEECompileInfo->GetModuleDecoder(hModule);
1338
1339
1340     //
1341     // Get file name, and base address from module
1342     //
1343
1344     StackSString moduleFileName;
1345     m_zapper->m_pEECompileInfo->GetModuleFileName(hModule, moduleFileName);
1346
1347     DWORD fileNameLength = moduleFileName.GetCount();
1348     m_pModuleFileName = new WCHAR[fileNameLength+1];
1349     wcscpy_s(m_pModuleFileName, fileNameLength+1, moduleFileName.GetUnicode());
1350
1351     //
1352     // Load the IBC Profile data for the assembly if it exists
1353     // 
1354     LoadProfileData();
1355
1356     //
1357     // Get metadata of module to be compiled
1358     //
1359     m_pMDImport = m_zapper->m_pEECompileInfo->GetModuleMetaDataImport(m_hModule);
1360     _ASSERTE(m_pMDImport != NULL);
1361
1362     //
1363     // Open new assembly metadata data for writing.  We may not use it,
1364     // if so we'll just discard it at the end.
1365     //
1366     if (pEmit != NULL)
1367     {
1368         pEmit->AddRef();
1369         m_pAssemblyEmit = pEmit;
1370     }
1371     else
1372     {
1373         // Hardwire the metadata version to be the current runtime version so that the ngen image
1374         // does not change when the directory runtime is installed in different directory (e.g. v2.0.x86chk vs. v2.0.80826).
1375         BSTRHolder strVersion(SysAllocString(W("v")VER_PRODUCTVERSION_NO_QFE_STR_L));
1376         VARIANT versionOption;
1377         V_VT(&versionOption) = VT_BSTR;
1378         V_BSTR(&versionOption) = strVersion;
1379         IfFailThrow(m_zapper->m_pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption));
1380
1381         IfFailThrow(m_zapper->m_pMetaDataDispenser->
1382                     DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataAssemblyEmit,
1383                                 (IUnknown **) &m_pAssemblyEmit));
1384     }
1385
1386 #ifdef FEATURE_READYTORUN_COMPILER
1387     if (IsReadyToRunCompilation())
1388     {
1389         InitializeSectionsForReadyToRun();
1390     }
1391     else
1392 #endif
1393     {
1394         InitializeSections();
1395     }
1396
1397     // Set the module base address for the ngen native image
1398     CalculateZapBaseAddress();
1399 }
1400
1401
1402
1403
1404 //
1405 // Load the module and populate all the data-structures
1406 //
1407
1408 void ZapImage::Preload()
1409 {
1410
1411     CorProfileData *  pProfileData = NewProfileData();
1412     m_pPreloader = m_zapper->m_pEECompileInfo->PreloadModule(m_hModule, this, pProfileData);
1413 }
1414
1415 //
1416 // Store the module
1417 //
1418
1419 void ZapImage::LinkPreload()
1420 {
1421     m_pPreloader->Link();
1422 }
1423
1424 void ZapImage::OutputManifestMetadata()
1425 {
1426     //
1427     // Write out manifest metadata
1428     //
1429
1430     //
1431     // First, see if we have useful metadata to store
1432     //
1433
1434     BOOL fMetadata = FALSE;
1435
1436     if (m_pAssemblyEmit != NULL)
1437     {
1438         //
1439         // We may have added some assembly refs for exports.
1440         //
1441
1442         NonVMComHolder<IMetaDataAssemblyImport> pAssemblyImport;
1443         IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataAssemblyImport,
1444                                                     (void **)&pAssemblyImport));
1445
1446         NonVMComHolder<IMetaDataImport> pImport;
1447         IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataImport,
1448                                                     (void **)&pImport));
1449
1450         HCORENUM hEnum = 0;
1451         ULONG cRefs;
1452         IfFailThrow(pAssemblyImport->EnumAssemblyRefs(&hEnum, NULL, 0, &cRefs));
1453         IfFailThrow(pImport->CountEnum(hEnum, &cRefs));
1454         pImport->CloseEnum(hEnum);
1455
1456         if (cRefs > 0)
1457             fMetadata = TRUE;
1458
1459         //
1460         // If we are the main module, we have the assembly def for the zap file.
1461         //
1462
1463         mdAssembly a;
1464         if (pAssemblyImport->GetAssemblyFromScope(&a) == S_OK)
1465             fMetadata = TRUE;
1466     }
1467
1468     if (fMetadata)
1469     {
1470         // Metadata creates a new MVID for every instantiation.
1471         // However, we want the generated ngen image to always be the same
1472         // for the same input. So set the metadata MVID to NGEN_IMAGE_MVID.
1473
1474         NonVMComHolder<IMDInternalEmit> pMDInternalEmit;
1475         IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMDInternalEmit,
1476                                                   (void**)&pMDInternalEmit));
1477
1478         IfFailThrow(pMDInternalEmit->ChangeMvid(NGEN_IMAGE_MVID));
1479
1480         m_pAssemblyMetaData = new (GetHeap()) ZapMetaData();
1481         m_pAssemblyMetaData->SetMetaData(m_pAssemblyEmit);
1482
1483         m_pMetaDataSection->Place(m_pAssemblyMetaData);
1484     }
1485 }
1486
1487 void ZapImage::OutputTables()
1488 {
1489     //
1490     // Copy over any resources to the native image
1491     //
1492
1493     COUNT_T size;
1494     PVOID resource = (PVOID)m_ModuleDecoder.GetResources(&size);
1495
1496     if (size != 0)
1497     {
1498         m_pResources = new (GetHeap()) ZapBlobPtr(resource, size);
1499         m_pResourcesSection->Place(m_pResources);
1500     }
1501
1502     CopyDebugDirEntry();
1503     CopyWin32VersionResource();
1504
1505     if (m_pILMetaData != NULL)
1506     {
1507         m_pILMetaData->CopyIL();
1508         m_pILMetaData->CopyMetaData();
1509     }
1510
1511     if (IsReadyToRunCompilation())
1512     {
1513         m_pILMetaData->CopyRVAFields();
1514     }
1515
1516     // Copy over the timestamp from IL image for determinism
1517     SetTimeDateStamp(m_ModuleDecoder.GetTimeDateStamp());
1518
1519     SetSubsystem(m_ModuleDecoder.GetSubsystem());
1520
1521     {
1522         USHORT dllCharacteristics = 0;
1523
1524 #ifndef _TARGET_64BIT_
1525         dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH;
1526 #endif
1527
1528 #ifdef _TARGET_ARM_
1529         // Images without NX compat bit set fail to load on ARM
1530         dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
1531 #endif
1532
1533         // Copy over selected DLL characteristics bits from IL image
1534         dllCharacteristics |= (m_ModuleDecoder.GetDllCharacteristics() & 
1535             (IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | IMAGE_DLLCHARACTERISTICS_APPCONTAINER));
1536
1537 #ifdef _DEBUG
1538         if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen))
1539 #endif // _DEBUG
1540         {
1541             dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
1542         }
1543
1544         SetDllCharacteristics(dllCharacteristics);
1545     }
1546
1547     if (IsReadyToRunCompilation())
1548     {
1549
1550         SetSizeOfStackReserve(m_ModuleDecoder.GetSizeOfStackReserve());
1551         SetSizeOfStackCommit(m_ModuleDecoder.GetSizeOfStackCommit());
1552     }
1553
1554 #if defined(FEATURE_PAL) && !defined(_TARGET_64BIT_)
1555     // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K).
1556     SetFileAlignment(0x1000);
1557 #elif defined(_TARGET_ARM_) && defined(FEATURE_CORESYSTEM)
1558     if (!IsReadyToRunCompilation())
1559     {
1560         // On ARM CoreSys builds, crossgen will use 4k file alignment, as requested by Phone perf team
1561         // to improve perf on phones with compressed system partitions.
1562         SetFileAlignment(0x1000);
1563     }
1564 #endif
1565 }
1566
1567 ZapImage::CompileStatus ZapImage::CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags)
1568 {
1569     if ((TypeFromToken(token) != mdtMethodDef) ||
1570         (!m_pMDImport->IsValidToken(token)))
1571     {
1572         m_zapper->Info(W("Warning: Invalid method token %08x in profile data.\n"), token);
1573         return NOT_COMPILED;
1574     }
1575
1576 #ifdef _DEBUG
1577     static ConfigDWORD g_NgenOrder;
1578
1579     if ((g_NgenOrder.val(CLRConfig::INTERNAL_NgenOrder) & 2) == 2)
1580     {
1581         const ProfileDataHashEntry * foundEntry = profileDataHashTable.LookupPtr(token);
1582     
1583         if (foundEntry == NULL)
1584             return NOT_COMPILED;
1585
1586         // The md must match.
1587         _ASSERTE(foundEntry->md == token); 
1588         // The target position cannot be 0.
1589         _ASSERTE(foundEntry->pos > 0);
1590     }
1591 #endif
1592
1593     // Now compile the method
1594     return TryCompileMethodDef(token, methodProfilingDataFlags);
1595 }
1596
1597 //  ProfileDisableInlining
1598 //     Before we start compiling any methods we may need to suppress the inlining
1599 //     of certain methods based upon our profile data.
1600 //     This method will arrange to disable this inlining.
1601 //
1602 void ZapImage::ProfileDisableInlining()
1603 {
1604     // We suppress the inlining of any Hot methods that have the ExcludeHotMethodCode flag.
1605     // We want such methods to be Jitted at runtime rather than compiled in the AOT native image.
1606     // The inlining of such a method also need to be suppressed.
1607     //
1608     ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]);
1609     if (methodProfileData->tableSize > 0)
1610     {
1611         for (DWORD i = 0; i < methodProfileData->tableSize; i++)
1612         {
1613             CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]);
1614             unsigned methodProfilingDataFlags = pTokenInfo->flags;
1615
1616             // Hot methods can be marked to be excluded from the AOT native image.
1617             // We also need to disable inlining of such methods.
1618             //
1619             if ((methodProfilingDataFlags & (1 << DisableInlining)) != 0)
1620             {
1621                 // Disable the inlining of this method
1622                 //
1623                 // @ToDo: Figure out how to disable inlining for this method.               
1624             }
1625         }
1626     }
1627 }
1628
1629 //  CompileHotRegion
1630 //     Performs the compilation and placement for all methods in the the "Hot" code region
1631 //     Methods placed in this region typically correspond to all of the methods that were
1632 //     executed during any of the profiling scenarios.
1633 //
1634 void ZapImage::CompileHotRegion()
1635 {
1636     // Compile all of the methods that were executed during profiling into the "Hot" code region.
1637     //
1638     BeginRegion(CORINFO_REGION_HOT);
1639
1640     CorProfileData* pProfileData = GetProfileData();
1641         
1642     ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]);
1643     if (methodProfileData->tableSize > 0)
1644     {
1645         // record the start of hot IBC methods.
1646         m_iIBCMethod = m_MethodCompilationOrder.GetCount();
1647
1648         //
1649         // Compile the hot methods in the order specified in the MethodProfilingData
1650         //
1651         for (DWORD i = 0; i < methodProfileData->tableSize; i++)
1652         {
1653             CompileStatus compileResult = NOT_COMPILED;
1654             CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]);
1655
1656             mdToken token = pTokenInfo->token;
1657             unsigned methodProfilingDataFlags = pTokenInfo->flags;
1658             _ASSERTE(methodProfilingDataFlags != 0);
1659
1660             if (TypeFromToken(token) == mdtMethodDef)
1661             {
1662                 //
1663                 // Compile a non-generic method
1664                 // 
1665                 compileResult = CompileProfileDataWorker(token, methodProfilingDataFlags);
1666             }
1667             else if (TypeFromToken(token) == ibcMethodSpec)
1668             {
1669                 //
1670                 //  compile a generic/parameterized method
1671                 // 
1672                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = pProfileData->GetBlobSigEntry(token);
1673                 
1674                 if (pBlobSigEntry == NULL)
1675                 {
1676                     m_zapper->Info(W("Warning: Did not find definition for method token %08x in profile data.\n"), token);
1677                 }
1678                 else // (pBlobSigEntry  != NULL)
1679                 {
1680                     _ASSERTE(pBlobSigEntry->blob.token == token);
1681
1682                     // decode method desc
1683                     CORINFO_METHOD_HANDLE pMethod = m_pPreloader->FindMethodForProfileEntry(pBlobSigEntry);
1684                    
1685                     if (pMethod)
1686                     {
1687                         m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pMethod);
1688
1689                         compileResult = TryCompileInstantiatedMethod(pMethod, methodProfilingDataFlags);
1690                     }
1691                     else
1692                     {
1693                         // This generic/parameterized method is not part of the native image
1694                         // Either the IBC type  specified no longer exists or it is a SIMD types
1695                         // or the type can't be loaded in a ReadyToRun native image because of
1696                         // a cross-module type dependencies.
1697                         //
1698                         compileResult = COMPILE_EXCLUDED;
1699                     }
1700                 }
1701             }
1702
1703             // Update the 'flags' and 'compileResult' saved in the profileDataHashTable hash table.
1704             //
1705             hashBBUpdateFlagsAndCompileResult(token, methodProfilingDataFlags, compileResult);
1706         }
1707         // record the start of hot Generics methods.
1708         m_iGenericsMethod = m_MethodCompilationOrder.GetCount();
1709     }
1710
1711     // record the start of untrained code
1712     m_iUntrainedMethod = m_MethodCompilationOrder.GetCount();
1713
1714     EndRegion(CORINFO_REGION_HOT);
1715 }
1716
1717 //  CompileColdRegion
1718 //     Performs the compilation and placement for all methods in the the "Cold" code region
1719 //     Methods placed in this region typically correspond to all of the methods that were
1720 //     NOT executed during any of the profiling scenarios.
1721 //
1722 void ZapImage::CompileColdRegion()
1723 {
1724     // Compile all of the methods that were NOT executed during profiling into the "Cold" code region.
1725     //
1726
1727     BeginRegion(CORINFO_REGION_COLD);
1728     
1729     IMDInternalImport * pMDImport = m_pMDImport;
1730     
1731     HENUMInternalHolder hEnum(pMDImport);
1732     hEnum.EnumAllInit(mdtMethodDef);
1733     
1734     mdMethodDef md;
1735     while (pMDImport->EnumNext(&hEnum, &md))
1736     {
1737         //
1738         // Compile the remaining methods that weren't compiled during the CompileHotRegion phase
1739         //
1740         TryCompileMethodDef(md, 0);
1741     }
1742
1743     // Compile any generic code which lands in this LoaderModule
1744     // that resulted from the above compilations
1745     CORINFO_METHOD_HANDLE handle = m_pPreloader->NextUncompiledMethod();
1746     while (handle != NULL)
1747     {
1748         TryCompileInstantiatedMethod(handle, 0);
1749         handle = m_pPreloader->NextUncompiledMethod();
1750     }
1751     
1752     EndRegion(CORINFO_REGION_COLD);
1753 }
1754
1755 //  PlaceMethodIL
1756 //     Copy the IL for all method into the AOT native image
1757 //
1758 void ZapImage::PlaceMethodIL()
1759 {
1760     // Place the IL for all of the methods 
1761     //
1762     IMDInternalImport * pMDImport = m_pMDImport;
1763     HENUMInternalHolder hEnum(pMDImport);
1764     hEnum.EnumAllInit(mdtMethodDef);
1765     
1766     mdMethodDef md;
1767     while (pMDImport->EnumNext(&hEnum, &md))
1768     {
1769         if (m_pILMetaData != NULL)
1770         {
1771             // Copy IL for all methods. We treat errors during copying IL 
1772             // over as fatal error. These errors are typically caused by 
1773             // corrupted IL images.
1774             // 
1775             m_pILMetaData->EmitMethodIL(md);
1776         }
1777     }
1778 }
1779
1780 void ZapImage::Compile()
1781 {
1782     //
1783     // Compile all of the methods for our AOT native image
1784     //
1785
1786     bool doNothingNgen = false;
1787 #ifdef _DEBUG
1788     static ConfigDWORD fDoNothingNGen;
1789     doNothingNgen = !!fDoNothingNGen.val(CLRConfig::INTERNAL_ZapDoNothing);
1790 #endif
1791
1792     ProfileDisableInlining();
1793
1794     if (!doNothingNgen)
1795     {
1796         CompileHotRegion();
1797
1798         CompileColdRegion();
1799     }
1800
1801     PlaceMethodIL();
1802
1803     // Compute a preferred class layout order based on analyzing the graph
1804     // of which classes contain calls to other classes.
1805     ComputeClassLayoutOrder();
1806
1807     // Sort the unprofiled methods by this preferred class layout, if available
1808     if (m_fHasClassLayoutOrder)
1809     {
1810         SortUnprofiledMethodsByClassLayoutOrder();
1811     }
1812
1813     if (IsReadyToRunCompilation())
1814     {
1815         // Pretend that no methods are trained, so that everything is in single code section
1816         // READYTORUN: FUTURE: More than one code section
1817         m_iUntrainedMethod = 0;
1818     }
1819
1820     OutputCode(ProfiledHot);
1821     OutputCode(Unprofiled);
1822     OutputCode(ProfiledCold);
1823
1824     OutputCodeInfo(ProfiledHot);
1825     OutputCodeInfo(ProfiledCold);  // actually both Unprofiled and ProfiledCold
1826
1827     OutputGCInfo();
1828     OutputProfileData();
1829
1830 #ifdef FEATURE_READYTORUN_COMPILER
1831     if (IsReadyToRunCompilation())
1832     {
1833         OutputEntrypointsTableForReadyToRun();
1834         OutputDebugInfoForReadyToRun();
1835         OutputTypesTableForReadyToRun(m_pMDImport);
1836         OutputInliningTableForReadyToRun();
1837         OutputProfileDataForReadyToRun();
1838     }
1839     else
1840 #endif
1841     {
1842         OutputDebugInfo();
1843     }
1844 }
1845
1846 struct CompileMethodStubContext
1847 {
1848     ZapImage *                  pImage;
1849     unsigned                    methodProfilingDataFlags;
1850     ZapImage::CompileStatus     enumCompileStubResult;
1851
1852     CompileMethodStubContext(ZapImage * _image, unsigned _methodProfilingDataFlags)
1853     {
1854         pImage                   = _image;
1855         methodProfilingDataFlags = _methodProfilingDataFlags;
1856         enumCompileStubResult    = ZapImage::NOT_COMPILED;
1857     }
1858 };
1859
1860 //-----------------------------------------------------------------------------
1861 // This method is a callback function use to compile any IL_STUBS that are
1862 // associated with a normal IL method.  It is called from CompileMethodStubIfNeeded
1863 // via the function pointer stored in the CompileMethodStubContext.
1864 // It handles the temporary change to the m_compilerFlags and removes any flags
1865 // that we don't want set when compiling IL_STUBS.
1866 //-----------------------------------------------------------------------------
1867
1868 // static void __stdcall 
1869 void ZapImage::TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags)
1870 {
1871     STANDARD_VM_CONTRACT;
1872
1873     // The caller must always set the IL_STUB flag
1874     _ASSERTE(jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB));
1875
1876     CompileMethodStubContext *pCompileContext = reinterpret_cast<CompileMethodStubContext *>(pContext);
1877     ZapImage *pImage = pCompileContext->pImage;
1878
1879     CORJIT_FLAGS oldFlags = pImage->m_zapper->m_pOpt->m_compilerFlags;
1880
1881     CORJIT_FLAGS* pCompilerFlags = &pImage->m_zapper->m_pOpt->m_compilerFlags;
1882     pCompilerFlags->Add(jitFlags);
1883     pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE);
1884     pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE);
1885     pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC);
1886     pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO);
1887
1888     mdMethodDef md = mdMethodDefNil;
1889
1890     pCompileContext->enumCompileStubResult = pImage->TryCompileMethodWorker(hStub, md,
1891                                                          pCompileContext->methodProfilingDataFlags);
1892
1893     pImage->m_zapper->m_pOpt->m_compilerFlags = oldFlags;
1894 }
1895
1896 //-----------------------------------------------------------------------------
1897 // Helper for ZapImage::TryCompileMethodDef that indicates whether a given method def token refers to a
1898 // "vtable gap" method. These are pseudo-methods used to lay out the vtable for COM interop and as such don't
1899 // have any associated code (or even a method handle).
1900 //-----------------------------------------------------------------------------
1901 BOOL ZapImage::IsVTableGapMethod(mdMethodDef md)
1902 {
1903 #ifdef FEATURE_COMINTEROP 
1904     HRESULT hr;
1905     DWORD dwAttributes;
1906
1907     // Get method attributes and check that RTSpecialName was set for the method (this means the name has
1908     // semantic import to the runtime and must be formatted rigorously with one of a few well known rules).
1909     // Note that we just return false on any failure path since this will just lead to our caller continuing
1910     // to throw the exception they were about to anyway.
1911     hr = m_pMDImport->GetMethodDefProps(md, &dwAttributes);
1912     if (FAILED(hr) || !IsMdRTSpecialName(dwAttributes))
1913         return FALSE;
1914
1915     // Now check the name of the method. All vtable gap methods will have a prefix of "_VtblGap".
1916     LPCSTR szMethod;
1917     PCCOR_SIGNATURE pvSigBlob;
1918     ULONG cbSigBlob;    
1919     hr = m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod);
1920     if (FAILED(hr) || (strncmp(szMethod, "_VtblGap", 8) != 0))
1921         return FALSE;
1922
1923     // If we make it to here we have a vtable gap method.
1924     return TRUE;
1925 #else
1926     return FALSE;
1927 #endif // FEATURE_COMINTEROP
1928 }
1929
1930 //-----------------------------------------------------------------------------
1931 // This function is called for non-generic methods in the current assembly,
1932 // and for the typical "System.__Canon" instantiations of generic methods
1933 // in the current assembly.
1934 //-----------------------------------------------------------------------------
1935
1936 ZapImage::CompileStatus ZapImage::TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags)
1937 {
1938     _ASSERTE(!IsNilToken(md));
1939
1940     CORINFO_METHOD_HANDLE handle = NULL;
1941     CompileStatus         result = NOT_COMPILED;
1942
1943     if (ShouldCompileMethodDef(md))
1944     {
1945         handle = m_pPreloader->LookupMethodDef(md);
1946         if (handle == nullptr)
1947         {
1948             result = LOOKUP_FAILED;
1949         }
1950     }
1951     else
1952     {
1953         result = COMPILE_EXCLUDED;
1954     }
1955
1956     if (handle == NULL)
1957         return result;
1958
1959     // compile the method
1960     //
1961     CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, md, methodProfilingDataFlags);
1962
1963     // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method
1964     //
1965     if (methodCompileStatus == COMPILE_SUCCEED)
1966     {
1967         CompileMethodStubContext context(this, methodProfilingDataFlags);
1968
1969         // compile stubs associated with the method
1970         m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage,
1971                                           &TryCompileMethodStub,
1972                                           &context);
1973     }
1974
1975     return methodCompileStatus;
1976 }
1977
1978
1979 //-----------------------------------------------------------------------------
1980 // This function is called for non-"System.__Canon" instantiations of generic methods.
1981 // These could be methods defined in other assemblies too.
1982 //-----------------------------------------------------------------------------
1983
1984 ZapImage::CompileStatus ZapImage::TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, 
1985                                                                unsigned methodProfilingDataFlags)
1986 {
1987     if (IsReadyToRunCompilation())
1988     {
1989         if (!GetCompileInfo()->IsInCurrentVersionBubble(m_zapper->m_pEEJitInfo->getMethodModule(handle)))
1990             return COMPILE_EXCLUDED;
1991     }
1992
1993     if (!ShouldCompileInstantiatedMethod(handle))
1994         return COMPILE_EXCLUDED;
1995
1996     // If we compiling this method because it was specified by the IBC profile data
1997     // then issue an warning if this method is not on our uncompiled method list
1998     // 
1999     if (methodProfilingDataFlags != 0)
2000     {
2001         if (methodProfilingDataFlags & (1 << ReadMethodCode))
2002         {
2003             // When we have stale IBC data the method could have been rejected from this image.
2004             if (!m_pPreloader->IsUncompiledMethod(handle))
2005             {
2006                 const char* szClsName;
2007                 const char* szMethodName = m_zapper->m_pEEJitInfo->getMethodName(handle, &szClsName);
2008
2009                 SString fullname(SString::Utf8, szClsName);
2010                 fullname.AppendUTF8(NAMESPACE_SEPARATOR_STR);
2011                 fullname.AppendUTF8(szMethodName);
2012
2013                 m_zapper->Info(W("Warning: Invalid method instantiation in profile data: %s\n"), fullname.GetUnicode());
2014
2015                 return NOT_COMPILED;
2016             }
2017         }
2018     }
2019    
2020     CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, mdMethodDefNil, methodProfilingDataFlags);
2021
2022     // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method
2023     //
2024     if (methodCompileStatus == COMPILE_SUCCEED)
2025     {
2026         CompileMethodStubContext context(this, methodProfilingDataFlags);
2027
2028         // compile stubs associated with the method
2029         m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage,
2030                                           &TryCompileMethodStub, 
2031                                           &context);
2032     }
2033
2034     return methodCompileStatus;
2035 }
2036
2037 //-----------------------------------------------------------------------------
2038
2039 ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, 
2040                                                          unsigned methodProfilingDataFlags)
2041 {
2042     _ASSERTE(handle != NULL);
2043
2044     if (m_zapper->m_pOpt->m_onlyOneMethod && (m_zapper->m_pOpt->m_onlyOneMethod != md))
2045         return NOT_COMPILED;
2046
2047     if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassNGenAttribute"))
2048         return NOT_COMPILED;
2049
2050 #ifdef FEATURE_READYTORUN_COMPILER
2051     // This is a quick workaround to opt specific methods out of ReadyToRun compilation to work around bugs.
2052     if (IsReadyToRunCompilation())
2053     {
2054         if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassReadyToRunAttribute"))
2055             return NOT_COMPILED;
2056     }
2057 #endif
2058
2059     // Do we have a profile entry for this method?
2060     //
2061     if (methodProfilingDataFlags != 0)
2062     {
2063         // Report the profiling data flags for layout of the EE datastructures
2064         m_pPreloader->SetMethodProfilingFlags(handle, methodProfilingDataFlags);
2065
2066         // Hot methods can be marked to be excluded from the AOT native image.
2067         // A Jitted method executes faster than a ReadyToRun compiled method.
2068         //
2069         if ((methodProfilingDataFlags & (1 << ExcludeHotMethodCode)) != 0)
2070         {
2071             // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image
2072             return COMPILE_HOT_EXCLUDED;
2073         }
2074
2075         // Cold methods can be marked to be excluded from the AOT native image.
2076         // We can reduced the size of the AOT native image by selectively
2077         // excluding the code for some of the cold methods.
2078         //
2079         if ((methodProfilingDataFlags & (1 << ExcludeColdMethodCode)) != 0)
2080         {
2081             // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image
2082             return COMPILE_COLD_EXCLUDED;
2083         }
2084
2085         // If the code was never executed based on the profile data
2086         // then don't compile this method now. Wait until until later
2087         // when we are compiling the methods in the cold section.
2088         //
2089         if ((methodProfilingDataFlags & (1 << ReadMethodCode)) == 0)
2090         {
2091             // returning NOT_COMPILED will defer until later the compilation of this method
2092             return NOT_COMPILED;
2093         }
2094     }
2095     else  // we are compiling methods for the cold region
2096     {
2097         // When Partial Ngen is specified we will omit the AOT native code for every
2098         // method that was not executed based on the profile data.
2099         //
2100         if (m_zapper->m_pOpt->m_fPartialNGen)
2101         {
2102             // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image
2103             return COMPILE_COLD_EXCLUDED;
2104         }
2105
2106         // Retrieve any information that we have about a previous compilation attempt of this method
2107         const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(md);
2108
2109         if (pEntry != nullptr)
2110         { 
2111             if ((pEntry->status == COMPILE_HOT_EXCLUDED) || (pEntry->status == COMPILE_COLD_EXCLUDED))
2112             {
2113                 // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image
2114                 return pEntry->status;
2115             }
2116         }
2117     }
2118
2119     // Have we already compiled it?
2120     if (GetCompiledMethod(handle) != NULL)
2121         return ALREADY_COMPILED;
2122
2123     _ASSERTE(m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) || IsNilToken(md) || handle == m_pPreloader->LookupMethodDef(md));
2124
2125     CompileStatus result = NOT_COMPILED;
2126     
2127     // This is an entry point into the JIT which can call back into the VM. There are methods in the
2128     // JIT that will swallow exceptions and only the VM guarentees that exceptions caught or swallowed
2129     // with restore the debug state of the stack guards. So it is necessary to ensure that the status
2130     // is restored on return from the call into the JIT, which this light-weight transition macro
2131     // will do.
2132     REMOVE_STACK_GUARD;
2133
2134     CORINFO_MODULE_HANDLE module;
2135
2136     // We only compile IL_STUBs from the current assembly
2137     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
2138         module = m_hModule;
2139     else
2140         module = m_zapper->m_pEEJitInfo->getMethodModule(handle);
2141
2142     ZapInfo zapInfo(this, md, handle, module, methodProfilingDataFlags);
2143
2144     EX_TRY
2145     {
2146         zapInfo.CompileMethod();
2147         result = COMPILE_SUCCEED;
2148     }
2149     EX_CATCH
2150     {
2151         // Continue unwinding if fatal error was hit.
2152         if (FAILED(g_hrFatalError))
2153             ThrowHR(g_hrFatalError);
2154
2155         Exception *ex = GET_EXCEPTION();
2156         HRESULT hrException = ex->GetHR();
2157
2158         CorZapLogLevel level;
2159
2160 #ifdef CROSSGEN_COMPILE
2161         // Warnings should not go to stderr during crossgen
2162         level = CORZAP_LOGLEVEL_WARNING;
2163 #else
2164         level = CORZAP_LOGLEVEL_ERROR;
2165
2166         m_zapper->m_failed = TRUE;
2167 #endif
2168
2169         result = COMPILE_FAILED;
2170
2171 #ifdef FEATURE_READYTORUN_COMPILER
2172         // NYI features in R2R - Stop crossgen from spitting unnecessary
2173         //     messages to the console
2174         if (IsReadyToRunCompilation())
2175         {
2176             // When compiling the method we may recieve an exeception when the
2177             // method uses a feature that is Not Implemented for ReadyToRun 
2178             // or a Type Load exception if the method uses for a SIMD type.
2179             //
2180             // We skip the compilation of such methods and we don't want to
2181             // issue a warning or error
2182             //
2183             if ((hrException == E_NOTIMPL) || (hrException == IDS_CLASSLOAD_GENERAL))
2184             {
2185                 result = NOT_COMPILED;
2186                 level = CORZAP_LOGLEVEL_INFO;
2187             }
2188         }
2189 #endif
2190         {
2191             StackSString message;
2192             ex->GetMessage(message);
2193
2194             // FileNotFound errors here can be converted into a single error string per ngen compile, 
2195             //  and the detailed error is available with verbose logging
2196             if (hrException == COR_E_FILENOTFOUND)
2197             {
2198                 StackSString logMessage(W("System.IO.FileNotFoundException: "));
2199                 logMessage.Append(message);
2200                 FileNotFoundError(logMessage.GetUnicode());
2201                 level = CORZAP_LOGLEVEL_INFO;
2202             }
2203
2204             m_zapper->Print(level, W("%s while compiling method %s\n"), message.GetUnicode(), zapInfo.m_currentMethodName.GetUnicode());
2205
2206             if ((result == COMPILE_FAILED) && (m_stats != NULL))
2207             {
2208                 if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
2209                     m_stats->m_failedMethods++;
2210                 else
2211                     m_stats->m_failedILStubs++;
2212             }
2213         }
2214     }
2215     EX_END_CATCH(SwallowAllExceptions);
2216     
2217     return result;
2218 }
2219
2220
2221 // Should we compile this method, defined in the ngen'ing module?
2222 // Result is FALSE if any of the controls (only used by prejit.exe) exclude the method
2223 BOOL ZapImage::ShouldCompileMethodDef(mdMethodDef md)
2224 {
2225     DWORD partialNGenStressVal = PartialNGenStressPercentage();
2226     if (partialNGenStressVal &&
2227         // Module::AddCerListToRootTable has problems if mscorlib.dll is
2228         // a partial ngen image
2229         m_hModule != m_zapper->m_pEECompileInfo->GetLoaderModuleForMscorlib())
2230     {
2231         _ASSERTE(partialNGenStressVal <= 100);
2232         DWORD methodPercentageVal = (md % 100) + 1;
2233         if (methodPercentageVal <= partialNGenStressVal)
2234             return FALSE;
2235     }
2236     
2237     mdTypeDef td;
2238     IfFailThrow(m_pMDImport->GetParentToken(md, &td));
2239     
2240 #ifdef FEATURE_COMINTEROP
2241     mdToken tkExtends;
2242     if (td != mdTypeDefNil)
2243     {
2244         m_pMDImport->GetTypeDefProps(td, NULL, &tkExtends);
2245         
2246         mdAssembly tkAssembly;
2247         DWORD dwAssemblyFlags;
2248         
2249         m_pMDImport->GetAssemblyFromScope(&tkAssembly);
2250         if (TypeFromToken(tkAssembly) == mdtAssembly)
2251         {
2252             m_pMDImport->GetAssemblyProps(tkAssembly,
2253                                             NULL, NULL,     // Public Key
2254                                             NULL,           // Hash Algorithm
2255                                             NULL,           // Name
2256                                             NULL,           // MetaData
2257                                             &dwAssemblyFlags);
2258             
2259             if (IsAfContentType_WindowsRuntime(dwAssemblyFlags))
2260             {
2261                 if (TypeFromToken(tkExtends) == mdtTypeRef)
2262                 {
2263                     LPCSTR szNameSpace = NULL;
2264                     LPCSTR szName = NULL;
2265                     m_pMDImport->GetNameOfTypeRef(tkExtends, &szNameSpace, &szName);
2266                     
2267                     if (!strcmp(szNameSpace, "System") && !_stricmp((szName), "Attribute"))
2268                     {
2269                         return FALSE;
2270                     }
2271                 }
2272             }
2273         }
2274     }
2275 #endif
2276
2277 #ifdef _DEBUG
2278     static ConfigMethodSet fZapOnly;
2279     fZapOnly.ensureInit(CLRConfig::INTERNAL_ZapOnly);
2280
2281     static ConfigMethodSet fZapExclude;
2282     fZapExclude.ensureInit(CLRConfig::INTERNAL_ZapExclude);
2283
2284     PCCOR_SIGNATURE pvSigBlob;
2285     ULONG cbSigBlob;
2286
2287     // Get the name of the current method and its class
2288     LPCSTR szMethod;
2289     IfFailThrow(m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod));
2290     
2291     LPCWSTR wszClass = W("");
2292     SString sClass;
2293
2294     if (td != mdTypeDefNil)
2295     {
2296         LPCSTR szNameSpace = NULL;
2297         LPCSTR szName = NULL;
2298         
2299         IfFailThrow(m_pMDImport->GetNameOfTypeDef(td, &szName, &szNameSpace));
2300         
2301         const SString nameSpace(SString::Utf8, szNameSpace);
2302         const SString name(SString::Utf8, szName);
2303         sClass.MakeFullNamespacePath(nameSpace, name);
2304         wszClass = sClass.GetUnicode();
2305     }
2306
2307     MAKE_UTF8PTR_FROMWIDE(szClass,  wszClass);
2308
2309     if (!fZapOnly.isEmpty() && !fZapOnly.contains(szMethod, szClass, pvSigBlob))
2310     {
2311         LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod));
2312         return FALSE;
2313     }
2314
2315     if (fZapExclude.contains(szMethod, szClass, pvSigBlob))
2316     {
2317         LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod));
2318         return FALSE;
2319     }
2320
2321     LOG((LF_ZAP, LL_INFO1000, "Compiling method %08x, %s::%s\n", md, szClass, szMethod));
2322 #endif    
2323     
2324     return TRUE;
2325 }
2326
2327
2328 BOOL ZapImage::ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle)
2329 {
2330     DWORD partialNGenStressVal = PartialNGenStressPercentage();
2331     if (partialNGenStressVal &&
2332         // Module::AddCerListToRootTable has problems if mscorlib.dll is
2333         // a partial ngen image
2334         m_hModule != m_zapper->m_pEECompileInfo->GetLoaderModuleForMscorlib())
2335     {
2336         _ASSERTE(partialNGenStressVal <= 100);
2337         DWORD methodPercentageVal = (m_zapper->m_pEEJitInfo->getMethodHash(handle) % 100) + 1;
2338         if (methodPercentageVal <= partialNGenStressVal)
2339             return FALSE;
2340     }
2341
2342     return TRUE;
2343 }
2344
2345 HRESULT ZapImage::PrintTokenDescription(CorZapLogLevel level, mdToken token)
2346 {
2347     HRESULT hr;
2348
2349     if (RidFromToken(token) == 0)
2350         return S_OK;
2351
2352     LPCSTR szNameSpace = NULL;
2353     LPCSTR szName = NULL;
2354
2355     if (m_pMDImport->IsValidToken(token))
2356     {
2357         switch (TypeFromToken(token))
2358         {
2359             case mdtMemberRef:
2360             {
2361                 mdToken parent;
2362                 IfFailRet(m_pMDImport->GetParentOfMemberRef(token, &parent));
2363                 if (RidFromToken(parent) != 0)
2364                 {
2365                     PrintTokenDescription(level, parent);
2366                     m_zapper->Print(level, W("."));
2367                 }
2368                 IfFailRet(m_pMDImport->GetNameAndSigOfMemberRef(token, NULL, NULL, &szName));
2369                 break;
2370             }
2371
2372             case mdtMethodDef:
2373             {
2374                 mdToken parent;
2375                 IfFailRet(m_pMDImport->GetParentToken(token, &parent));
2376                 if (RidFromToken(parent) != 0)
2377                 {
2378                     PrintTokenDescription(level, parent);
2379                     m_zapper->Print(level, W("."));
2380                 }
2381                 IfFailRet(m_pMDImport->GetNameOfMethodDef(token, &szName));
2382                 break;
2383             }
2384
2385             case mdtTypeRef:
2386             {   
2387                 IfFailRet(m_pMDImport->GetNameOfTypeRef(token, &szNameSpace, &szName));
2388                 break;
2389             }
2390
2391             case mdtTypeDef:
2392             {
2393                 IfFailRet(m_pMDImport->GetNameOfTypeDef(token, &szName, &szNameSpace));
2394                 break;
2395             }
2396
2397             default:
2398                 break;
2399         }      
2400     }
2401     else
2402     {
2403         szName = "InvalidToken";
2404     }
2405
2406     SString fullName;
2407
2408     if (szNameSpace != NULL)
2409     {
2410         const SString nameSpace(SString::Utf8, szNameSpace);
2411         const SString name(SString::Utf8, szName);
2412         fullName.MakeFullNamespacePath(nameSpace, name);
2413     }
2414     else
2415     {
2416         fullName.SetUTF8(szName);
2417     }
2418
2419     m_zapper->Print(level, W("%s"), fullName.GetUnicode());
2420
2421     return S_OK;
2422 }
2423
2424
2425 HRESULT ZapImage::LocateProfileData()
2426 {
2427     if (m_zapper->m_pOpt->m_ignoreProfileData)
2428     {
2429         return S_FALSE;
2430     }
2431
2432     //
2433     // In the past, we have ignored profile data when instrumenting the assembly.
2434     // However, this creates significant differences between the tuning image and the eventual
2435     // optimized image (e.g. generic instantiations) which in turn leads to missed data during
2436     // training and cold touches during execution.  Instead, we take advantage of any IBC data
2437     // the assembly already has and attempt to make the tuning image as close as possible to
2438     // the final image.
2439     //
2440 #if 0
2441     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR))
2442         return S_FALSE;
2443 #endif
2444
2445     //
2446     // Don't use IBC data from untrusted assemblies--this allows us to assume that
2447     // the IBC data is not malicious
2448     //
2449     if (m_zapper->m_pEEJitInfo->canSkipVerification(m_hModule) != CORINFO_VERIFICATION_CAN_SKIP)
2450     {
2451         return S_FALSE;
2452     }
2453
2454 #if !defined(FEATURE_PAL)
2455     //
2456     // See if there's profile data in the resource section of the PE
2457     //
2458     m_pRawProfileData = (BYTE*)m_ModuleDecoder.GetWin32Resource(W("PROFILE_DATA"), W("IBC"), &m_cRawProfileData);
2459
2460     if ((m_pRawProfileData != NULL) && (m_cRawProfileData != 0))
2461     {
2462         m_zapper->Info(W("Found embedded profile resource in %s.\n"), m_pModuleFileName);
2463         return S_OK;
2464     }
2465
2466     static ConfigDWORD g_UseIBCFile;
2467     if (g_UseIBCFile.val(CLRConfig::EXTERNAL_UseIBCFile) != 1)
2468         return S_OK;
2469 #endif
2470
2471     //
2472     // Couldn't find profile resource--let's see if there's an ibc file to use instead
2473     //
2474
2475     SString path(m_pModuleFileName);
2476
2477     SString::Iterator dot = path.End();
2478     if (path.FindBack(dot, '.'))
2479     {
2480         SString slName(SString::Literal, "ibc");
2481         path.Replace(dot+1, path.End() - (dot+1), slName);
2482
2483         HandleHolder hFile = WszCreateFile(path.GetUnicode(),
2484                                      GENERIC_READ,
2485                                      FILE_SHARE_READ,
2486                                      NULL,
2487                                      OPEN_EXISTING,
2488                                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
2489                                      NULL);
2490         if (hFile != INVALID_HANDLE_VALUE)
2491         {
2492             HandleHolder hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
2493             DWORD dwFileLen = SafeGetFileSize(hFile, 0);
2494             if (dwFileLen != INVALID_FILE_SIZE)
2495             {
2496                 if (hMapFile == NULL)
2497                 {
2498                     m_zapper->Warning(W("Found profile data file %s, but could not open it"), path.GetUnicode());
2499                 }
2500                 else
2501                 {
2502                     m_zapper->Info(W("Found ibc file %s.\n"), path.GetUnicode());
2503
2504                     m_profileDataFile  = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
2505
2506                     m_pRawProfileData  = m_profileDataFile;
2507                     m_cRawProfileData  = dwFileLen;
2508                 }
2509             }
2510         }
2511     }
2512
2513     return S_OK;
2514 }
2515
2516
2517 bool ZapImage::CanConvertIbcData()
2518 {
2519     static ConfigDWORD g_iConvertIbcData;
2520     DWORD val = g_iConvertIbcData.val(CLRConfig::UNSUPPORTED_ConvertIbcData);
2521     return (val != 0);
2522 }
2523
2524 HRESULT ZapImage::parseProfileData()
2525 {
2526     if (m_pRawProfileData == NULL)
2527     {
2528         return S_FALSE;
2529     }
2530
2531     ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData);
2532
2533     CORBBTPROF_FILE_HEADER *fileHeader;
2534
2535     READ(fileHeader, CORBBTPROF_FILE_HEADER);
2536     if (fileHeader->HeaderSize < sizeof(CORBBTPROF_FILE_HEADER))
2537     {
2538         _ASSERTE(!"HeaderSize is too small");
2539         return E_FAIL;
2540     }
2541
2542     // Read any extra header data. It will be needed for V3 files.
2543
2544     DWORD extraHeaderDataSize = fileHeader->HeaderSize - sizeof(CORBBTPROF_FILE_HEADER);
2545     void *extraHeaderData = profileReader.Read(extraHeaderDataSize);
2546
2547     bool convertFromV1 = false;
2548     bool minified = false;
2549
2550     if (fileHeader->Magic != CORBBTPROF_MAGIC) 
2551     {
2552         _ASSERTE(!"ibcHeader contains bad values");
2553         return E_FAIL;
2554     }
2555
2556     // CoreCLR should never be presented with V1 IBC data.
2557     if (fileHeader->Version == CORBBTPROF_V3_VERSION)
2558     {
2559         CORBBTPROF_FILE_OPTIONAL_HEADER *optionalHeader =
2560             (CORBBTPROF_FILE_OPTIONAL_HEADER *)extraHeaderData;
2561
2562         if (!optionalHeader ||
2563             !CONTAINS_FIELD(optionalHeader, extraHeaderDataSize, Size) ||
2564             (optionalHeader->Size > extraHeaderDataSize))
2565         {
2566             m_zapper->Info(W("Optional header missing or corrupt."));
2567             return E_FAIL;
2568         }
2569
2570         if (CONTAINS_FIELD(optionalHeader, optionalHeader->Size, FileFlags))
2571         {
2572             minified = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_MINIFIED);
2573
2574             if (!m_zapper->m_pOpt->m_fPartialNGenSet)
2575             {
2576                 m_zapper->m_pOpt->m_fPartialNGen = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_PARTIAL_NGEN);
2577             }
2578         }
2579     }
2580     else if (fileHeader->Version != CORBBTPROF_V2_VERSION)
2581     {
2582         m_zapper->Info(W("Discarding profile data with unknown version."));
2583         return S_FALSE;
2584     }
2585
2586     // This module has profile data (this ends up controling the layout of physical and virtual
2587     // sections within the image, see ZapImage::AllocateVirtualSections.
2588     m_fHaveProfileData = true;
2589     m_zapper->m_pOpt->m_fHasAnyProfileData = true;
2590
2591     CORBBTPROF_SECTION_TABLE_HEADER *sectionHeader;
2592     READ(sectionHeader, CORBBTPROF_SECTION_TABLE_HEADER);
2593
2594     //
2595     // Parse the section table
2596     //
2597
2598     for (ULONG i = 0; i < sectionHeader->NumEntries; i++)
2599     {
2600         CORBBTPROF_SECTION_TABLE_ENTRY *entry;
2601         READ(entry,CORBBTPROF_SECTION_TABLE_ENTRY);
2602
2603         SectionFormat format = sectionHeader->Entries[i].FormatID;
2604         _ASSERTE(format >= 0);
2605         if (format < 0)
2606         {
2607             continue;
2608         }
2609
2610         if (convertFromV1)
2611         {
2612             if (format < LastTokenFlagSection)
2613             {
2614                 format = (SectionFormat) (format + 1);
2615             }
2616         }
2617
2618         _ASSERTE(format < SectionFormatCount);
2619
2620         if (format < SectionFormatCount)
2621         {
2622             BYTE *start = m_pRawProfileData + sectionHeader->Entries[i].Data.Offset;
2623             BYTE *end   = start             + sectionHeader->Entries[i].Data.Size;
2624
2625             if ((start > m_pRawProfileData)                     &&
2626                 (end   < m_pRawProfileData + m_cRawProfileData) &&
2627                 (start < end))
2628             {
2629                 _ASSERTE(m_profileDataSections[format].pData  == 0);
2630                 _ASSERTE(m_profileDataSections[format].dataSize == 0);
2631
2632                 m_profileDataSections[format].pData     = start;
2633                 m_profileDataSections[format].dataSize  = (DWORD) (end - start);
2634             }
2635             else
2636             {
2637                 _ASSERTE(!"Invalid profile section offset or size");
2638                 return E_FAIL;
2639             }
2640         }
2641     }
2642
2643     HRESULT hr = S_OK;
2644
2645     if (convertFromV1)
2646     {
2647         hr = convertProfileDataFromV1();
2648         if (FAILED(hr))
2649         {
2650             return hr;
2651         }
2652     }
2653     else if (minified)
2654     {
2655         hr = RehydrateProfileData();
2656         if (FAILED(hr))
2657         {
2658             return hr;
2659         }
2660     }
2661     else
2662     {
2663         //
2664         // For those sections that are collections of tokens, further parse that format to get
2665         // the token pointer and number of tokens
2666         //
2667
2668         for (int format = FirstTokenFlagSection; format < SectionFormatCount; format++)
2669         {
2670             if (m_profileDataSections[format].pData)
2671             {
2672                 SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData)));
2673
2674                 CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header;
2675                 READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER);
2676
2677                 DWORD tableSize = header->NumTokens;
2678                 DWORD dataSize  = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER));
2679                 DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_INFO);
2680
2681                 if (dataSize == expectedSize)
2682                 {
2683                     BYTE * startOfTable = m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER);
2684                     m_profileDataSections[format].tableSize = tableSize;
2685                     m_profileDataSections[format].pTable = (CORBBTPROF_TOKEN_INFO *) startOfTable;
2686                 }
2687                 else
2688                 {
2689                     _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header");
2690                     return E_FAIL;
2691                 }
2692             }
2693         }
2694     }
2695
2696     ZapImage::ProfileDataSection * DataSection_ScenarioInfo = & m_profileDataSections[ScenarioInfo];
2697     if (DataSection_ScenarioInfo->pData != NULL)
2698     {
2699         CORBBTPROF_SCENARIO_INFO_SECTION_HEADER * header = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) DataSection_ScenarioInfo->pData;
2700         m_profileDataNumRuns = header->TotalNumRuns;
2701     }
2702
2703     return S_OK;
2704 }
2705
2706
2707 HRESULT ZapImage::convertProfileDataFromV1()
2708 {
2709     if (m_pRawProfileData == NULL)
2710     {
2711         return S_FALSE;
2712     }
2713
2714     //
2715     // For those sections that are collections of tokens, further parse that format to get
2716     // the token pointer and number of tokens
2717     //
2718
2719     ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData);
2720
2721     for (SectionFormat format = FirstTokenFlagSection; format < SectionFormatCount; format = (SectionFormat) (format + 1))
2722     {
2723         if (m_profileDataSections[format].pData)
2724         {
2725             SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData)));
2726
2727             CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header;
2728             READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER);
2729
2730             DWORD tableSize = header->NumTokens;
2731
2732             if (tableSize == 0)
2733             {
2734                 m_profileDataSections[format].tableSize = 0;
2735                 m_profileDataSections[format].pTable    = NULL;
2736                 continue;
2737             }
2738
2739             DWORD dataSize  = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER));
2740             DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_LIST_ENTRY_V1);
2741
2742             if (dataSize == expectedSize)
2743             {
2744                 DWORD  newDataSize  = tableSize * sizeof (CORBBTPROF_TOKEN_INFO);
2745
2746                 if (newDataSize < dataSize)
2747                     return E_FAIL;
2748
2749                 BYTE * startOfTable = new (GetHeap()) BYTE[newDataSize];
2750
2751                 CORBBTPROF_TOKEN_LIST_ENTRY_V1 * pOldEntry;
2752                 CORBBTPROF_TOKEN_INFO *    pNewEntry;
2753
2754                 pOldEntry = (CORBBTPROF_TOKEN_LIST_ENTRY_V1 *) (m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER));
2755                 pNewEntry = (CORBBTPROF_TOKEN_INFO *)    startOfTable;
2756
2757                 for (DWORD i=0; i<tableSize; i++)
2758                 {
2759                     pNewEntry->token = pOldEntry->token;
2760                     pNewEntry->flags = pOldEntry->flags;
2761                     pNewEntry->scenarios = 1;
2762
2763                     pOldEntry++;
2764                     pNewEntry++;
2765                 }
2766                 m_profileDataSections[format].tableSize = tableSize;
2767                 m_profileDataSections[format].pTable    = (CORBBTPROF_TOKEN_INFO *) startOfTable;
2768             }
2769             else
2770             {
2771                 _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header");
2772                 return E_FAIL;
2773             }
2774         }
2775     }
2776
2777     _ASSERTE(m_profileDataSections[ScenarioInfo].pData == 0);
2778     _ASSERTE(m_profileDataSections[ScenarioInfo].dataSize == 0);
2779
2780     //
2781     // Convert the MethodBlockCounts format from V1 to V2
2782     //
2783     CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 * mbcSectionHeader = NULL;
2784     if (m_profileDataSections[MethodBlockCounts].pData)
2785     {
2786         //
2787         // Compute the size of the method block count stream
2788         // 
2789         BYTE *  dstPtr           = NULL;
2790         BYTE *  srcPtr           = m_profileDataSections[MethodBlockCounts].pData;
2791         DWORD   maxSizeToRead    = m_profileDataSections[MethodBlockCounts].dataSize;
2792         DWORD   totalSizeNeeded  = 0; 
2793         DWORD   totalSizeRead    = 0;
2794        
2795         mbcSectionHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 *) srcPtr;
2796
2797         totalSizeRead   += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1);
2798         totalSizeNeeded += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); 
2799         srcPtr          += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1);
2800
2801         if (totalSizeRead > maxSizeToRead)
2802         {
2803             return E_FAIL;
2804         }
2805        
2806         for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++)
2807         {
2808             CORBBTPROF_METHOD_HEADER_V1* methodEntry = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr;
2809             DWORD sizeRead   = 0;
2810             DWORD sizeWrite  = 0;
2811
2812             sizeRead  += methodEntry->HeaderSize;
2813             sizeRead  += methodEntry->Size;
2814             sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER);
2815             sizeWrite += methodEntry->Size;
2816
2817             totalSizeRead   += sizeRead;
2818             totalSizeNeeded += sizeWrite;            
2819
2820             if (totalSizeRead > maxSizeToRead)
2821             {
2822                 return E_FAIL;
2823             }
2824
2825             srcPtr += sizeRead;
2826         }
2827         assert(totalSizeRead == maxSizeToRead);
2828
2829         // Reset the srcPtr
2830         srcPtr = m_profileDataSections[MethodBlockCounts].pData;
2831        
2832         BYTE * newMethodData = new (GetHeap()) BYTE[totalSizeNeeded];
2833
2834         dstPtr = newMethodData;
2835
2836         memcpy(dstPtr, srcPtr, sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER));
2837         srcPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1);
2838         dstPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER);
2839         
2840         for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++)
2841         {
2842             CORBBTPROF_METHOD_HEADER_V1 *  methodEntryV1 = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr;
2843             CORBBTPROF_METHOD_HEADER *     methodEntry   = (CORBBTPROF_METHOD_HEADER *)    dstPtr;
2844             DWORD sizeRead   = 0;
2845             DWORD sizeWrite  = 0;
2846
2847             methodEntry->method.token   = methodEntryV1->MethodToken;
2848             methodEntry->method.ILSize  = 0;
2849             methodEntry->method.cBlock  = (methodEntryV1->Size / sizeof(CORBBTPROF_BLOCK_DATA));
2850             sizeRead  += methodEntryV1->HeaderSize; 
2851             sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER);
2852
2853             memcpy( dstPtr + sizeof(CORBBTPROF_METHOD_HEADER),
2854                     srcPtr + sizeof(CORBBTPROF_METHOD_HEADER_V1), 
2855                     (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA)));
2856             sizeRead  += methodEntryV1->Size; 
2857             sizeWrite += (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA));
2858
2859             methodEntry->size    = sizeWrite;
2860             methodEntry->cDetail = 0;
2861             srcPtr += sizeRead;
2862             dstPtr += sizeWrite;
2863         }
2864        
2865         m_profileDataSections[MethodBlockCounts].pData    = newMethodData;
2866         m_profileDataSections[MethodBlockCounts].dataSize = totalSizeNeeded;
2867     }
2868
2869     //
2870     // Allocate the scenario info section
2871     //
2872     {
2873         DWORD   sizeNeeded  = sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER) + sizeof(CORBBTPROF_SCENARIO_HEADER);
2874         BYTE *  newData     = new (GetHeap()) BYTE[sizeNeeded];
2875         BYTE *  dstPtr      = newData;
2876         {
2877             CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *siHeader = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) dstPtr;
2878             
2879             if (mbcSectionHeader != NULL)
2880                 siHeader->TotalNumRuns = mbcSectionHeader->NumRuns;
2881             else
2882                 siHeader->TotalNumRuns = 1;
2883
2884             siHeader->NumScenarios = 1;
2885
2886             dstPtr += sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER);
2887         }
2888         {
2889             CORBBTPROF_SCENARIO_HEADER *sHeader = (CORBBTPROF_SCENARIO_HEADER *) dstPtr;
2890
2891             sHeader->scenario.ordinal  = 1;
2892             sHeader->scenario.mask     = 1;
2893             sHeader->scenario.priority = 0;
2894             sHeader->scenario.numRuns  = 0;
2895             sHeader->scenario.cName    = 0; 
2896
2897             sHeader->size = sHeader->Size();
2898
2899             dstPtr += sizeof(CORBBTPROF_SCENARIO_HEADER);
2900         }
2901         m_profileDataSections[ScenarioInfo].pData = newData;
2902         m_profileDataSections[ScenarioInfo].dataSize = sizeNeeded;
2903     }
2904
2905     //
2906     // Convert the BlobStream format from V1 to V2 
2907     //   
2908     if (m_profileDataSections[BlobStream].dataSize > 0)
2909     {
2910         //
2911         // Compute the size of the blob stream
2912         // 
2913         
2914         BYTE *  srcPtr           = m_profileDataSections[BlobStream].pData;
2915         BYTE *  dstPtr           = NULL;
2916         DWORD   maxSizeToRead    = m_profileDataSections[BlobStream].dataSize;
2917         DWORD   totalSizeNeeded  = 0;
2918         DWORD   totalSizeRead    = 0;
2919         bool    done             = false;
2920         
2921         while (!done)
2922         {
2923             CORBBTPROF_BLOB_ENTRY_V1* blobEntry = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr;
2924             DWORD sizeWrite  = 0;
2925             DWORD sizeRead   = 0;
2926
2927             if ((blobEntry->blobType >= MetadataStringPool) && (blobEntry->blobType <= MetadataUserStringPool))
2928             {
2929                 sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY);
2930                 sizeWrite += blobEntry->cBuffer;
2931                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
2932                 sizeRead  += blobEntry->cBuffer;
2933             }
2934             else if ((blobEntry->blobType >= ParamTypeSpec) && (blobEntry->blobType <= ParamMethodSpec))
2935             {
2936                 sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
2937                 sizeWrite += blobEntry->cBuffer;
2938                 if (blobEntry->blobType == ParamMethodSpec)
2939                 {
2940                     sizeWrite -= 1;  // Adjust for 
2941                 }
2942                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
2943                 sizeRead  += blobEntry->cBuffer;
2944             }
2945             else if (blobEntry->blobType == EndOfBlobStream)
2946             {
2947                 sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY);
2948                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
2949                 done = true;
2950             }
2951             else
2952             {
2953                 return E_FAIL;
2954             }
2955             
2956             totalSizeNeeded += sizeWrite;
2957             totalSizeRead   += sizeRead;
2958             
2959             if (sizeRead > maxSizeToRead)
2960             {
2961                 return E_FAIL;
2962             }
2963             
2964             srcPtr += sizeRead;
2965         }
2966
2967         assert(totalSizeRead == maxSizeToRead);
2968
2969         // Reset the srcPtr
2970         srcPtr = m_profileDataSections[BlobStream].pData;
2971         
2972         BYTE * newBlobData = new (GetHeap()) BYTE[totalSizeNeeded];
2973
2974         dstPtr = newBlobData;
2975         done = false;
2976         
2977         while (!done)
2978         {
2979             CORBBTPROF_BLOB_ENTRY_V1* blobEntryV1 = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr;
2980             DWORD sizeWrite  = 0;
2981             DWORD sizeRead   = 0;
2982             
2983             if ((blobEntryV1->blobType >= MetadataStringPool) && (blobEntryV1->blobType <= MetadataUserStringPool))
2984             {
2985                 CORBBTPROF_BLOB_POOL_ENTRY* blobPoolEntry = (CORBBTPROF_BLOB_POOL_ENTRY*) dstPtr;
2986                 
2987                 blobPoolEntry->blob.type = blobEntryV1->blobType;
2988                 blobPoolEntry->blob.size = sizeof(CORBBTPROF_BLOB_POOL_ENTRY) + blobEntryV1->cBuffer;
2989                 blobPoolEntry->cBuffer   = blobEntryV1->cBuffer;
2990                 memcpy(blobPoolEntry->buffer, blobEntryV1->pBuffer, blobEntryV1->cBuffer);
2991                 
2992                 sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY);
2993                 sizeWrite += blobEntryV1->cBuffer;
2994                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
2995                 sizeRead  += blobEntryV1->cBuffer;
2996             }
2997             else if ((blobEntryV1->blobType >= ParamTypeSpec) && (blobEntryV1->blobType <= ParamMethodSpec))
2998             {
2999                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY* blobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) dstPtr;
3000
3001                 blobSigEntry->blob.type  = blobEntryV1->blobType;
3002                 blobSigEntry->blob.size  = sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY) + blobEntryV1->cBuffer;
3003                 blobSigEntry->blob.token = 0;
3004                 blobSigEntry->cSig       = blobEntryV1->cBuffer; 
3005
3006                 if (blobEntryV1->blobType == ParamMethodSpec)
3007                 {
3008                     // Adjust cSig and blob.size
3009                     blobSigEntry->cSig--; 
3010                     blobSigEntry->blob.size--;
3011                 }
3012                 memcpy(blobSigEntry->sig, blobEntryV1->pBuffer, blobSigEntry->cSig);
3013                 
3014                 sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
3015                 sizeWrite += blobSigEntry->cSig;
3016                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
3017                 sizeRead  += blobEntryV1->cBuffer;
3018             }
3019             else if (blobEntryV1->blobType == EndOfBlobStream)
3020             {
3021                 CORBBTPROF_BLOB_ENTRY* blobEntry = (CORBBTPROF_BLOB_ENTRY*) dstPtr;
3022
3023                 blobEntry->type = blobEntryV1->blobType;
3024                 blobEntry->size = sizeof(CORBBTPROF_BLOB_ENTRY);
3025                 
3026                 sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY);
3027                 sizeRead  += sizeof(CORBBTPROF_BLOB_ENTRY_V1);
3028                 done = true;
3029             }
3030             else
3031             {
3032                 return E_FAIL;
3033             }
3034             srcPtr += sizeRead;
3035             dstPtr += sizeWrite;
3036         }
3037        
3038         m_profileDataSections[BlobStream].pData    = newBlobData;
3039         m_profileDataSections[BlobStream].dataSize = totalSizeNeeded;
3040     }
3041     else
3042     {
3043         m_profileDataSections[BlobStream].pData    = NULL;
3044         m_profileDataSections[BlobStream].dataSize = 0;
3045     }
3046
3047     return S_OK;
3048 }
3049
3050 void ZapImage::RehydrateBasicBlockSection()
3051 {
3052     ProfileDataSection &section = m_profileDataSections[MethodBlockCounts];
3053     if (!section.pData)
3054     {
3055         return;
3056     }
3057
3058     ProfileReader reader(section.pData, section.dataSize);
3059
3060     m_profileDataNumRuns = reader.Read<unsigned int>();
3061
3062     // The IBC data provides a hint to the number of basic blocks, which is
3063     // used here to determine how much space to allocate for the rehydrated
3064     // data.
3065     unsigned int blockCountHint = reader.Read<unsigned int>();
3066
3067     unsigned int numMethods = reader.Read<unsigned int>();
3068
3069     unsigned int expectedLength =
3070         sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER) +
3071         sizeof(CORBBTPROF_METHOD_HEADER) * numMethods +
3072         sizeof(CORBBTPROF_BLOCK_DATA) * blockCountHint;
3073
3074     BinaryWriter writer(expectedLength, GetHeap());
3075
3076     writer.Write(numMethods);
3077
3078     mdToken lastMethodToken = 0x06000000;
3079
3080     CORBBTPROF_METHOD_HEADER methodHeader;
3081     methodHeader.cDetail = 0;
3082     methodHeader.method.ILSize = 0;
3083
3084     for (unsigned int i = 0; i < numMethods; ++i)
3085     {
3086         // Translate the method header
3087         unsigned int size = reader.Read7BitEncodedInt();
3088         unsigned int startPosition = reader.GetCurrentPos();
3089
3090         mdToken token = reader.ReadTokenWithMemory(lastMethodToken);
3091         unsigned int ilSize = reader.Read7BitEncodedInt();
3092         unsigned int firstBlockHitCount = reader.Read7BitEncodedInt();
3093
3094         unsigned int numOtherBlocks = reader.Read7BitEncodedInt();
3095
3096         methodHeader.method.cBlock = 1 + numOtherBlocks;
3097         methodHeader.method.token = token;
3098         methodHeader.method.ILSize = ilSize;
3099         methodHeader.size = (DWORD)methodHeader.Size();
3100
3101         writer.Write(methodHeader);
3102
3103         CORBBTPROF_BLOCK_DATA blockData;
3104
3105         // The first block is handled specially.
3106         blockData.ILOffset = 0;
3107         blockData.ExecutionCount = firstBlockHitCount;
3108
3109         writer.Write(blockData);
3110
3111         // Translate the rest of the basic blocks
3112         for (unsigned int j = 0; j < numOtherBlocks; ++j)
3113         {
3114             blockData.ILOffset = reader.Read7BitEncodedInt();
3115             blockData.ExecutionCount = reader.Read7BitEncodedInt();
3116
3117             writer.Write(blockData);
3118         }
3119
3120         if (!reader.Seek(startPosition + size))
3121         {
3122             ThrowHR(E_FAIL);
3123         }
3124     }
3125
3126     // If the expected and actual lengths differ, the result will still be
3127     // correct but performance may suffer slightly because of reallocations.
3128     _ASSERTE(writer.GetWrittenSize() == expectedLength);
3129
3130     section.pData = writer.GetBuffer();
3131     section.dataSize = writer.GetWrittenSize();
3132 }
3133
3134 void ZapImage::RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255])
3135 {
3136     ProfileDataSection &section = m_profileDataSections[sectionFormat];
3137     ProfileReader reader(section.pData, section.dataSize);
3138
3139     unsigned int numTokens = reader.Read<unsigned int>();
3140
3141     unsigned int dataLength = sizeof(unsigned int) +
3142                               numTokens * sizeof(CORBBTPROF_TOKEN_INFO);
3143     BinaryWriter writer(dataLength, GetHeap());
3144
3145     writer.Write(numTokens);
3146
3147     mdToken lastToken = (sectionFormat - FirstTokenFlagSection) << 24;
3148
3149     CORBBTPROF_TOKEN_INFO tokenInfo;
3150     tokenInfo.scenarios = 1;
3151
3152     for (unsigned int i = 0; i < numTokens; ++i)
3153     {
3154         tokenInfo.token = reader.ReadTokenWithMemory(lastToken);
3155         tokenInfo.flags = reader.ReadFlagWithLookup(flagTable);
3156
3157         writer.Write(tokenInfo);
3158     }
3159
3160     _ASSERTE(writer.GetWrittenSize() == dataLength);
3161     
3162     section.pData = writer.GetBuffer();
3163     section.dataSize = writer.GetWrittenSize();
3164     section.pTable = (CORBBTPROF_TOKEN_INFO *)(section.pData + sizeof(unsigned int));
3165     section.tableSize = numTokens;
3166 }
3167
3168 void ZapImage::RehydrateBlobStream()
3169 {
3170     ProfileDataSection &section = m_profileDataSections[BlobStream];
3171
3172     ProfileReader reader(section.pData, section.dataSize);
3173
3174     // Evidence suggests that rehydrating the blob stream in Framework binaries
3175     // increases the size from 1.5-2x. When this was written, 1.85x minimized
3176     // the amount of extra memory allocated (about 48K in the worst case).
3177     BinaryWriter writer((DWORD)(section.dataSize * 1.85f), GetHeap());
3178
3179     mdToken LastBlobToken = 0;
3180     mdToken LastAssemblyToken = 0x23000000;
3181     mdToken LastExternalTypeToken = 0x62000000;
3182     mdToken LastExternalNamespaceToken = 0x61000000;
3183     mdToken LastExternalSignatureToken = 0x63000000;
3184
3185     int blobType = 0;
3186     do
3187     {
3188         // Read the blob header.
3189
3190         unsigned int sizeToRead = reader.Read7BitEncodedInt();
3191         unsigned int startPositionRead = reader.GetCurrentPos();
3192     
3193         blobType = reader.Read7BitEncodedInt();
3194         mdToken token = reader.ReadTokenWithMemory(LastBlobToken);
3195
3196         // Write out the blob header.
3197
3198         // Note the location in the write stream, and write a 0 there. Once
3199         // this blob has been written in its entirety, this location can be
3200         // used to calculate the real size and to go back to the right place
3201         // to write it.
3202
3203         unsigned int startPositionWrite = writer.GetWrittenSize();
3204         writer.Write(0U);
3205
3206         writer.Write(blobType);
3207         writer.Write(token);
3208
3209         // All blobs (except the end-of-stream indicator) end as:
3210         //     <data length> <data>
3211         // Two blob types (handled immediately below) include tokens as well.
3212         // Handle those first, then handle the common case.
3213
3214         if (blobType == ExternalTypeDef)
3215         {
3216             writer.Write(reader.ReadTokenWithMemory(LastAssemblyToken));
3217             writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken));
3218             writer.Write(reader.ReadTokenWithMemory(LastExternalNamespaceToken));
3219         }
3220         else if (blobType == ExternalMethodDef)
3221         {
3222             writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken));
3223             writer.Write(reader.ReadTokenWithMemory(LastExternalSignatureToken));
3224         }
3225
3226         if ((blobType >= MetadataStringPool) && (blobType < IllegalBlob))
3227         {
3228             // This blob is of known type and ends with data.
3229             unsigned int dataLength = reader.Read7BitEncodedInt();
3230             char *data = (char *)reader.Read(dataLength);
3231
3232             if (!data)
3233             {
3234                 ThrowHR(E_FAIL);
3235             }
3236
3237             writer.Write(dataLength);
3238             writer.Write(data, dataLength);
3239         }
3240
3241         // Write the size for this blob.
3242
3243         writer.WriteAt(startPositionWrite,
3244                        writer.GetWrittenSize() - startPositionWrite);
3245
3246         // Move to the next blob.
3247
3248         if (!reader.Seek(startPositionRead + sizeToRead))
3249         {
3250             ThrowHR(E_FAIL);
3251         }
3252     }
3253     while (blobType != EndOfBlobStream);
3254
3255     section.pData = writer.GetBuffer();
3256     section.dataSize = writer.GetWrittenSize();
3257 }
3258
3259 HRESULT ZapImage::RehydrateProfileData()
3260 {
3261     HRESULT hr = S_OK;
3262     unsigned int flagTable[255];
3263     memset(flagTable, 0xFF, sizeof(flagTable));
3264     
3265     EX_TRY
3266     {
3267         RehydrateBasicBlockSection();
3268         RehydrateBlobStream();
3269         for (int format = FirstTokenFlagSection;
3270              format < SectionFormatCount;
3271              ++format)
3272         {
3273             if (m_profileDataSections[format].pData)
3274             {
3275                 RehydrateTokenSection(format, flagTable);
3276             }
3277         }
3278     }
3279     EX_CATCH_HRESULT_NO_ERRORINFO(hr);
3280
3281     return hr;
3282 }
3283
3284 HRESULT ZapImage::hashBBProfileData ()
3285 {
3286     ProfileDataSection * DataSection_MethodBlockCounts = & m_profileDataSections[MethodBlockCounts];
3287
3288     if (!DataSection_MethodBlockCounts->pData)
3289     {
3290         return E_FAIL;
3291     }
3292
3293     ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize);
3294
3295     CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader;
3296     READ(mbcHeader,CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER);
3297
3298     for (ULONG i = 0; i < mbcHeader->NumMethods; i++)
3299     {
3300         ProfileDataHashEntry newEntry;
3301         newEntry.pos = profileReader.GetCurrentPos();
3302         
3303         CORBBTPROF_METHOD_HEADER *methodHeader;
3304         READ(methodHeader,CORBBTPROF_METHOD_HEADER);
3305         newEntry.md   = methodHeader->method.token;
3306         newEntry.size = methodHeader->size;
3307         newEntry.flags = 0;
3308         newEntry.status = NOT_COMPILED;
3309
3310         // Add the new entry to the table
3311         profileDataHashTable.Add(newEntry);
3312
3313         // Skip the profileData so we can read the next method.
3314         void *profileData;
3315         READ_SIZE(profileData, void, (methodHeader->size - sizeof(CORBBTPROF_METHOD_HEADER)));
3316     }
3317
3318     return S_OK;
3319 }
3320
3321 void ZapImage::hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, ZapImage::CompileStatus compileResult)
3322 {
3323     // SHash only supports replacing an entry so we setup our newEntry and then perform a lookup
3324     //
3325     ProfileDataHashEntry newEntry;
3326     newEntry.md = token;
3327     newEntry.flags = methodProfilingDataFlags;
3328     newEntry.status = compileResult;
3329
3330     const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(token);
3331     if (pEntry != nullptr)
3332     {
3333         assert(pEntry->md == newEntry.md);
3334         assert(pEntry->flags == 0);   // the flags should not be set at this point.
3335
3336         // Copy and keep the two fleids that were previously set
3337         newEntry.size = pEntry->size;
3338         newEntry.pos = pEntry->pos;
3339     }
3340     else // We have a method that doesn't have basic block counts
3341     {
3342         newEntry.size = 0;
3343         newEntry.pos = 0;
3344     }
3345     profileDataHashTable.AddOrReplace(newEntry);
3346 }
3347
3348 void ZapImage::LoadProfileData()
3349 {
3350     HRESULT hr = E_FAIL;
3351
3352     m_fHaveProfileData = false;
3353     m_pRawProfileData  = NULL;
3354     m_cRawProfileData  = 0;
3355
3356     EX_TRY
3357     {
3358         hr = LocateProfileData();
3359         
3360         if (hr == S_OK)
3361         {
3362             hr = parseProfileData();
3363             if (hr == S_OK)
3364             {
3365                 hr = hashBBProfileData();
3366             }
3367         }
3368     }
3369     EX_CATCH
3370     {
3371         hr = E_FAIL;
3372     }
3373     EX_END_CATCH(SwallowAllExceptions);
3374     
3375     if (hr != S_OK)
3376     {
3377         m_fHaveProfileData = false;
3378         m_pRawProfileData = NULL;
3379         m_cRawProfileData = 0;
3380
3381         if (FAILED(hr))
3382         {
3383             m_zapper->Warning(W("Warning: Invalid profile data was ignored for %s\n"), m_pModuleFileName);
3384         }
3385     }
3386 }
3387
3388 // Initializes our form of the profile data stored in the assembly.
3389
3390 CorProfileData *  ZapImage::NewProfileData()
3391 {
3392     this->m_pCorProfileData = new CorProfileData(&m_profileDataSections[0]);
3393
3394     return this->m_pCorProfileData;
3395 }
3396
3397 // Returns the profile data stored in the assembly.
3398
3399 CorProfileData *  ZapImage::GetProfileData()
3400 {
3401     _ASSERTE(this->m_pCorProfileData != NULL);
3402
3403     return this->m_pCorProfileData;
3404 }
3405
3406 CorProfileData::CorProfileData(void *  rawProfileData)
3407 {
3408     ZapImage::ProfileDataSection * profileData =  (ZapImage::ProfileDataSection *) rawProfileData;
3409
3410     for (DWORD format = 0; format < SectionFormatCount; format++)
3411     {
3412         this->profilingTokenFlagsData[format].count = profileData[format].tableSize;
3413         this->profilingTokenFlagsData[format].data  = profileData[format].pTable;
3414     }
3415
3416     this->blobStream = (CORBBTPROF_BLOB_ENTRY *) profileData[BlobStream].pData;
3417 }
3418
3419
3420 // Determines whether a method can be called directly from another method (without
3421 // going through the prestub) in the current module.
3422 // callerFtn=NULL implies any/unspecified caller in the current module.
3423 //
3424 // Returns NULL if 'calleeFtn' cannot be called directly *at the current time*
3425 // Else returns the direct address that 'calleeFtn' can be called at.
3426
3427
3428 bool ZapImage::canIntraModuleDirectCall(
3429                         CORINFO_METHOD_HANDLE callerFtn,
3430                         CORINFO_METHOD_HANDLE targetFtn,
3431                         CorInfoIndirectCallReason *pReason,
3432                         CORINFO_ACCESS_FLAGS  accessFlags/*=CORINFO_ACCESS_ANY*/)
3433 {
3434     CorInfoIndirectCallReason reason;
3435     if (pReason == NULL)
3436         pReason = &reason;
3437     *pReason = CORINFO_INDIRECT_CALL_UNKNOWN;
3438
3439     // The caller should have checked that the method is in current loader module
3440     _ASSERTE(m_hModule == m_zapper->m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(targetFtn));
3441
3442     // No direct calls at all under some circumstances
3443
3444     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE)
3445         && !m_pPreloader->IsDynamicMethod(callerFtn))
3446     {
3447         *pReason = CORINFO_INDIRECT_CALL_PROFILING;
3448         goto CALL_VIA_ENTRY_POINT;
3449     }
3450
3451     // Does the methods's class have a cctor, etc?
3452
3453     if (!m_pPreloader->CanSkipMethodPreparation(callerFtn, targetFtn, pReason, accessFlags))
3454         goto CALL_VIA_ENTRY_POINT;
3455
3456     ZapMethodHeader * pMethod;
3457     pMethod = GetCompiledMethod(targetFtn);
3458
3459     // If we have not compiled the method then we can't call direct
3460
3461     if (pMethod == NULL)
3462     {
3463         *pReason = CORINFO_INDIRECT_CALL_NO_CODE;
3464         goto CALL_VIA_ENTRY_POINT;
3465     }
3466
3467     // Does the method have fixups?
3468
3469     if (pMethod->HasFixups() != NULL)
3470     {
3471         *pReason = CORINFO_INDIRECT_CALL_FIXUPS;
3472         goto CALL_VIA_ENTRY_POINT;
3473     }
3474
3475 #ifdef _DEBUG
3476     const char* clsName, * methodName;
3477     methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName);
3478     LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Success %s::%s\n",
3479         clsName, methodName));
3480 #endif
3481
3482     return true;
3483
3484 CALL_VIA_ENTRY_POINT:
3485
3486 #ifdef _DEBUG
3487     methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName);
3488     LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Via EntryPoint %s::%s\n",
3489          clsName, methodName));
3490 #endif
3491
3492     return false;
3493 }
3494
3495 //
3496 // Relocations
3497 //
3498
3499 void ZapImage::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type)
3500 {
3501     _ASSERTE(!IsWritingRelocs());
3502
3503     _ASSERTE(m_pBaseRelocs != NULL);
3504     m_pBaseRelocs->WriteReloc(pSrc, offset, pTarget, targetOffset, type);
3505 }
3506
3507 ZapImage * ZapImage::GetZapImage()
3508 {
3509     return this;
3510 }
3511
3512 void ZapImage::FileNotFoundError(LPCWSTR pszMessage)
3513 {
3514     SString message(pszMessage);
3515
3516     for (COUNT_T i = 0; i < fileNotFoundErrorsTable.GetCount(); i++)
3517     {
3518         // Check to see if same error has already been displayed for this ngen operation
3519         if (message.Equals(fileNotFoundErrorsTable[i]))
3520             return;
3521     }
3522
3523     CorZapLogLevel level;
3524
3525 #ifdef CROSSGEN_COMPILE
3526     // Warnings should not go to stderr during crossgen
3527     level = CORZAP_LOGLEVEL_WARNING;
3528 #else
3529     level = CORZAP_LOGLEVEL_ERROR;
3530 #endif
3531
3532     m_zapper->Print(level, W("Warning: %s.\n"), pszMessage);
3533
3534     fileNotFoundErrorsTable.Append(message);
3535 }
3536
3537 void ZapImage::Error(mdToken token, HRESULT hr, UINT resID,  LPCWSTR message)
3538 {
3539     // Missing dependencies are reported as fatal errors in code:CompilationDomain::BindAssemblySpec.
3540     // Avoid printing redundant error message for them.
3541     if (FAILED(g_hrFatalError))
3542         ThrowHR(g_hrFatalError);
3543
3544     // COM introduces the notion of a vtable gap method, which is not a real method at all but instead
3545     // aids in the explicit layout of COM interop vtables. These methods have no implementation and no
3546     // direct runtime state tracking them. Trying to lookup a method handle for a vtable gap method will
3547     // throw an exception but we choose to let that happen and filter out the warning here in the
3548     // handler because (a) vtable gap methods are rare and (b) it's not all that cheap to identify them
3549     // beforehand.
3550     if ((TypeFromToken(token) == mdtMethodDef) && IsVTableGapMethod(token))
3551     {
3552         return;
3553     }
3554
3555     CorZapLogLevel level = CORZAP_LOGLEVEL_ERROR;
3556
3557     // Some warnings are demoted to informational level
3558     if (resID == IDS_EE_SIMD_NGEN_DISALLOWED)
3559     {
3560         // Supress printing of "Target-dependent SIMD vector types may not be used with ngen."
3561         level = CORZAP_LOGLEVEL_INFO;
3562     }
3563
3564     if (resID == IDS_EE_HWINTRINSIC_NGEN_DISALLOWED)
3565     {
3566         // Supress printing of "Hardware intrinsics may not be used with ngen."
3567         level = CORZAP_LOGLEVEL_INFO;
3568     }
3569
3570 #ifdef CROSSGEN_COMPILE
3571     if ((resID == IDS_IBC_MISSING_EXTERNAL_TYPE) ||
3572         (resID == IDS_IBC_MISSING_EXTERNAL_METHOD))
3573     {
3574         // Supress printing of "The generic type/method specified by the IBC data is not available to this assembly"
3575         level = CORZAP_LOGLEVEL_INFO;
3576     }   
3577 #endif        
3578
3579     if (m_zapper->m_pOpt->m_ignoreErrors)
3580     {
3581 #ifdef CROSSGEN_COMPILE
3582         // Warnings should not go to stderr during crossgen
3583         if (level == CORZAP_LOGLEVEL_ERROR)
3584         {
3585             level = CORZAP_LOGLEVEL_WARNING;
3586         }
3587 #endif
3588         m_zapper->Print(level, W("Warning: "));
3589     }
3590     else
3591     {
3592         m_zapper->Print(level, W("Error: "));
3593     }
3594
3595     if (message != NULL)
3596         m_zapper->Print(level, W("%s"), message);
3597     else
3598         m_zapper->PrintErrorMessage(level, hr);
3599
3600     m_zapper->Print(level, W(" while resolving 0x%x - "), token);
3601     PrintTokenDescription(level, token);
3602     m_zapper->Print(level, W(".\n"));
3603
3604     if (m_zapper->m_pOpt->m_ignoreErrors)
3605         return;
3606
3607     IfFailThrow(hr);
3608 }
3609
3610 ZapNode * ZapImage::GetInnerPtr(ZapNode * pNode, SSIZE_T offset)
3611 {
3612     return m_pInnerPtrs->Get(pNode, offset);
3613 }
3614
3615 ZapNode * ZapImage::GetHelperThunk(CorInfoHelpFunc ftnNum)
3616 {
3617     ZapNode * pHelperThunk = m_pHelperThunks[ftnNum];
3618
3619     if (pHelperThunk == NULL)
3620     {
3621         pHelperThunk = new (GetHeap()) ZapHelperThunk(ftnNum);
3622 #ifdef _TARGET_ARM_
3623         pHelperThunk = GetInnerPtr(pHelperThunk, THUMB_CODE);
3624 #endif
3625         m_pHelperThunks[ftnNum] = pHelperThunk;
3626     }
3627
3628     // Ensure that the thunk is placed
3629     ZapNode * pTarget = pHelperThunk;
3630     if (pTarget->GetType() == ZapNodeType_InnerPtr)
3631         pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
3632     if (!pTarget->IsPlaced())
3633         m_pHelperTableSection->Place(pTarget);
3634
3635     return pHelperThunk;
3636 }
3637
3638 //
3639 // Compute a class-layout order based on a breadth-first traversal of 
3640 // the class graph (based on what classes contain calls to other classes).
3641 // We cannot afford time or space to build the graph, so we do processing
3642 // in place.
3643 // 
3644 void ZapImage::ComputeClassLayoutOrder()
3645 {
3646     // In order to make the computation efficient, we need to store per-class 
3647     // intermediate values in the class layout field.  These come in two forms:
3648     // 
3649     //   - An entry with the UNSEEN_CLASS_FLAG set is one that is yet to be encountered.
3650     //   - An entry with METHOD_INDEX_FLAG set is an index into the m_MethodCompilationOrder list
3651     //     indicating where the unprofiled methods of this class begin
3652     //   
3653     // Both flags begin set (by InitializeClassLayoutOrder) since the value initialized is
3654     // the method index and the class has not been encountered by the algorithm.
3655     // When a class layout has been computed, both of these flags will have been stripped.
3656
3657
3658     // Early-out in the (probably impossible) case that these bits weren't available
3659     if (m_MethodCompilationOrder.GetCount() >= UNSEEN_CLASS_FLAG ||
3660         m_MethodCompilationOrder.GetCount() >= METHOD_INDEX_FLAG)
3661     {
3662         return;
3663     }
3664
3665     // Allocate the queue for the breadth-first traversal.
3666     // Note that the use of UNSEEN_CLASS_FLAG ensures that no class is enqueued more
3667     // than once, so we can use that bound for the size of the queue.
3668     CORINFO_CLASS_HANDLE * classQueue = new CORINFO_CLASS_HANDLE[m_ClassLayoutOrder.GetCount()];
3669
3670     unsigned classOrder = 0;
3671     for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++)
3672     {
3673         unsigned classQueueNext = 0;
3674         unsigned classQueueEnd = 0;
3675         COUNT_T  methodIndex = 0;
3676
3677         //
3678         // Find an unprocessed method to seed the next breadth-first traversal.
3679         //
3680
3681         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
3682         const ClassLayoutOrderEntry * pEntry = m_ClassLayoutOrder.LookupPtr(pMethod->m_classHandle);
3683         _ASSERTE(pEntry);
3684         
3685         if ((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0)
3686         {
3687             continue;
3688         }
3689
3690         //
3691         // Enqueue the method's class and start the traversal.
3692         //
3693
3694         classQueue[classQueueEnd++] = pMethod->m_classHandle;
3695         ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG;
3696
3697         while (classQueueNext < classQueueEnd)
3698         {
3699             //
3700             // Dequeue a class and pull out the index of its first method
3701             //
3702             
3703             CORINFO_CLASS_HANDLE dequeuedClassHandle = classQueue[classQueueNext++];
3704             _ASSERTE(dequeuedClassHandle != NULL);
3705
3706             pEntry = m_ClassLayoutOrder.LookupPtr(dequeuedClassHandle);
3707             _ASSERTE(pEntry);
3708             _ASSERTE((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0);
3709             _ASSERTE((pEntry->m_order & METHOD_INDEX_FLAG) != 0);
3710
3711             methodIndex = pEntry->m_order & ~METHOD_INDEX_FLAG;
3712             _ASSERTE(methodIndex < m_MethodCompilationOrder.GetCount());
3713
3714             //
3715             // Set the real layout order of the class, and examine its unprofiled methods
3716             //
3717             
3718             ((ClassLayoutOrderEntry *)pEntry)->m_order = ++classOrder;
3719                 
3720             pMethod = m_MethodCompilationOrder[methodIndex];
3721             _ASSERTE(pMethod->m_classHandle == dequeuedClassHandle);
3722
3723             while (pMethod->m_classHandle == dequeuedClassHandle)
3724             {
3725
3726                 //
3727                 // For each unprofiled method, find target classes and enqueue any that haven't been seen
3728                 //
3729
3730                 ZapMethodHeader::PartialTargetMethodIterator it(pMethod);
3731
3732                 CORINFO_METHOD_HANDLE targetMethodHandle;
3733                 while (it.GetNext(&targetMethodHandle))
3734                 {
3735                     CORINFO_CLASS_HANDLE targetClassHandle = GetJitInfo()->getMethodClass(targetMethodHandle);
3736                     if (targetClassHandle != pMethod->m_classHandle)
3737                     {
3738                         pEntry = m_ClassLayoutOrder.LookupPtr(targetClassHandle);
3739
3740                         if (pEntry && (pEntry->m_order & UNSEEN_CLASS_FLAG) != 0)
3741                         {
3742                             _ASSERTE(classQueueEnd < m_ClassLayoutOrder.GetCount());
3743                             classQueue[classQueueEnd++] = targetClassHandle;
3744
3745                             ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG;
3746                         }
3747                     }
3748                 }
3749
3750                 if (++methodIndex == m_MethodCompilationOrder.GetCount())
3751                 {
3752                     break;
3753                 }
3754                     
3755                 pMethod = m_MethodCompilationOrder[methodIndex];
3756             }
3757         }
3758     }
3759
3760     for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++)
3761     {
3762         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
3763         pMethod->m_cachedLayoutOrder = LookupClassLayoutOrder(pMethod->m_classHandle);
3764     }
3765
3766     m_fHasClassLayoutOrder = true;
3767
3768     delete [] classQueue;
3769 }
3770
3771 static int __cdecl LayoutOrderCmp(const void* a_, const void* b_)
3772 {
3773     ZapMethodHeader * a = *((ZapMethodHeader**)a_);
3774     ZapMethodHeader * b = *((ZapMethodHeader**)b_);
3775
3776     int layoutDiff = a->GetCachedLayoutOrder() - b->GetCachedLayoutOrder();
3777     if (layoutDiff != 0)
3778         return layoutDiff;
3779
3780     // Use compilation order as secondary key to get predictable ordering within the bucket
3781     return a->GetCompilationOrder() - b->GetCompilationOrder();
3782 }
3783
3784 void ZapImage::SortUnprofiledMethodsByClassLayoutOrder()
3785 {
3786     qsort(&m_MethodCompilationOrder[m_iUntrainedMethod], m_MethodCompilationOrder.GetCount() - m_iUntrainedMethod, sizeof(ZapMethodHeader *), LayoutOrderCmp);
3787 }