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