1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#ifndef ZAPPER_H_
6#define ZAPPER_H_
7
8#include <winwrap.h>
9#include <windows.h>
10#include <stdlib.h>
11#include <objbase.h>
12#include <stddef.h>
13#include <float.h>
14#include <limits.h>
15
16#include "sarray.h"
17#include "sstring.h"
18#include "shash.h"
19#include "utilcode.h"
20#include "corjit.h"
21#include "corcompile.h"
22#include "corhlprpriv.h"
23#include "ngen.h"
24#include "corbbtprof.h"
25#include "pedecoder.h"
26#include "mscorsvc.h"
27#include "holderinst.h"
28#include "corpriv.h"
29
30// For side by side issues, it's best to use the exported API calls to generate a
31// Zapper Object instead of creating one on your own.
32
33STDAPI NGenCreateNGenWorker(ICorSvcWorker **pCorSvcWorker, ILocalServerLifetime *pLocalServerLifetime, ICorSvcLogger *pCorSvcLogger);
34STDAPI NGenCreateZapper(HANDLE* hZapper, NGenOptions* opt);
35STDAPI NGenFreeZapper(HANDLE hZapper);
36STDAPI NGenTryEnumerateFusionCache(HANDLE hZapper, LPCWSTR assemblyName, bool fPrint, bool fDelete);
37STDAPI_(BOOL) NGenCompile(HANDLE hZapper, LPCWSTR path);
38
39
40/* --------------------------------------------------------------------------- *
41 * Zapper classes
42 * --------------------------------------------------------------------------- */
43
44class ZapperOptions;
45class ZapperAttributionStats;
46class ZapImage;
47class ZapInfo;
48
49typedef enum CorZapLogLevel
50{
51 CORZAP_LOGLEVEL_ERROR,
52 CORZAP_LOGLEVEL_WARNING,
53 CORZAP_LOGLEVEL_SUCCESS,
54 CORZAP_LOGLEVEL_INFO,
55} CorZapLogLevel;
56
57class Zapper
58{
59 friend class ZapImage;
60 friend class ZapInfo;
61 friend class ZapILMetaData;
62
63 private:
64
65 //
66 // Interfaces
67 //
68
69 ICorDynamicInfo *m_pEEJitInfo;
70 ICorCompileInfo *m_pEECompileInfo;
71 ICorJitCompiler *m_pJitCompiler;
72 IMetaDataDispenserEx *m_pMetaDataDispenser;
73 HMODULE m_hJitLib;
74#ifdef _TARGET_AMD64_
75 HMODULE m_hJitLegacy;
76#endif
77
78#ifdef ALLOW_SXS_JIT_NGEN
79 ICorJitCompiler *m_alternateJit;
80 HMODULE m_hAltJITCompiler;
81#endif // ALLOW_SXS_JIT_NGEN
82
83 //
84 // Options
85 //
86
87 ZapperOptions * m_pOpt;
88 BOOL m_fFreeZapperOptions;
89
90 SString m_exeName; // If an EXE is specified
91
92 bool m_fromDllHost;
93
94 //
95 // Current assembly info
96 //
97
98 ICorCompilationDomain *m_pDomain;
99 CORINFO_ASSEMBLY_HANDLE m_hAssembly;
100 IMDInternalImport *m_pAssemblyImport;
101
102 SString m_outputPath; // Temp folder for creating the output file
103
104 IMetaDataAssemblyEmit *m_pAssemblyEmit;
105 IMetaDataAssemblyEmit *CreateAssemblyEmitter();
106
107 //
108 //
109 // Status info
110 //
111
112 BOOL m_failed;
113 CorInfoRegionKind m_currentRegionKind;
114
115 SString m_platformAssembliesPaths;
116 SString m_trustedPlatformAssemblies;
117 SString m_platformResourceRoots;
118 SString m_appPaths;
119 SString m_appNiPaths;
120 SString m_platformWinmdPaths;
121
122#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
123 SString m_CLRJITPath;
124 bool m_fDontLoadJit;
125#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
126#if !defined(NO_NGENPDB)
127 SString m_DiasymreaderPath;
128#endif // !defined(NO_NGENPDB)
129
130 SString m_outputFilename;
131
132 public:
133
134 struct assemblyDependencies
135 {
136 struct DependencyEntry
137 {
138 BSTR bstr;
139 LoadHintEnum loadHint;
140 NGenHintEnum ngenHint;
141 };
142
143 SArray<DependencyEntry> dependencyArray;
144 NGenHintEnum ngenHint;
145 SString displayName;
146
147 assemblyDependencies()
148 {
149 Initialize();
150 ngenHint = NGenDefault;
151 }
152
153 ~assemblyDependencies()
154 {
155 Cleanup();
156 }
157
158 void Reinitialize()
159 {
160 Cleanup();
161 Initialize();
162 }
163
164 void SetNGenHint(NGenHintEnum ngenHint)
165 {
166 this->ngenHint = ngenHint;
167 }
168
169 NGenHintEnum GetNGenHint()
170 {
171 return ngenHint;
172 }
173
174 void SetDisplayName(const WCHAR *pStr)
175 {
176 displayName.Set(pStr);
177 }
178
179 const WCHAR *GetDisplayName()
180 {
181 return displayName.GetUnicode();
182 }
183
184 void Append(const WCHAR *pStr, LoadHintEnum loadHint = LoadDefault, NGenHintEnum ngenHint = NGenDefault)
185 {
186 // Don't append string if it's a duplicate
187 for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++)
188 {
189 if (wcscmp(dependencyArray[i].bstr, pStr) == 0)
190 return;
191 }
192
193 BSTRHolder bstr(::SysAllocString(pStr));
194 DependencyEntry dependencyEntry;
195 dependencyEntry.bstr = bstr.GetValue();
196 dependencyEntry.loadHint = loadHint;
197 dependencyEntry.ngenHint = ngenHint;
198
199 dependencyArray.Append(dependencyEntry);
200 bstr.SuppressRelease();
201 }
202
203 SAFEARRAY *GetSAFEARRAY()
204 {
205 SafeArrayHolder pDependencies(SafeArrayCreateVector(VT_BSTR, 0, dependencyArray.GetCount()));
206 if (pDependencies.GetValue() == NULL) ThrowLastError();
207
208 for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++)
209 {
210 LONG indices[1];
211 indices[0] = (LONG) i;
212 IfFailThrow(SafeArrayPutElement(pDependencies, indices, this->dependencyArray[i].bstr));
213 }
214
215 pDependencies.SuppressRelease();
216 return pDependencies.GetValue();
217 }
218
219 SAFEARRAY *GetLoadHintSAFEARRAY()
220 {
221 SafeArrayHolder pSettings(SafeArrayCreateVector(VT_UI4, 0, dependencyArray.GetCount()));
222 if (pSettings.GetValue() == NULL) ThrowLastError();
223
224 for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++)
225 {
226 LONG indices[1];
227 indices[0] = (LONG) i;
228 IfFailThrow(SafeArrayPutElement(pSettings, indices, &this->dependencyArray[i].loadHint));
229 }
230
231 pSettings.SuppressRelease();
232 return pSettings.GetValue();
233 }
234
235 SAFEARRAY *GetNGenHintSAFEARRAY()
236 {
237 SafeArrayHolder pSettings(SafeArrayCreateVector(VT_UI4, 0, dependencyArray.GetCount()));
238 if (pSettings.GetValue() == NULL) ThrowLastError();
239
240 for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++)
241 {
242 LONG indices[1];
243 indices[0] = (LONG) i;
244 IfFailThrow(SafeArrayPutElement(pSettings, indices, &this->dependencyArray[i].ngenHint));
245 }
246
247 pSettings.SuppressRelease();
248 return pSettings.GetValue();
249 }
250
251 private:
252 void Initialize()
253 {
254 dependencyArray.SetCount(0);
255 // Should we reinitialize ngenHint to the default value as well?
256 }
257
258 void Cleanup()
259 {
260 for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++)
261 {
262 ::SysFreeString(dependencyArray[i].bstr);
263 }
264 }
265 } m_assemblyDependencies;
266
267
268 public:
269
270 Zapper(ZapperOptions *pOpt);
271 Zapper(NGenOptions *pOpt, bool fromDllHost = false);
272
273 void Init(ZapperOptions *pOpt, bool fFreeZapperOptions= false);
274
275 static Zapper *NewZapper(NGenOptions *pOpt, bool fromDllHost = false)
276 {
277 CONTRACTL
278 {
279 THROWS;
280 GC_NOTRIGGER;
281 }
282 CONTRACTL_END;
283 return new Zapper(pOpt, fromDllHost);
284 }
285
286 ~Zapper();
287
288 // The arguments control which native image of mscorlib to use.
289 // This matters for hardbinding.
290 void InitEE(BOOL fForceDebug, BOOL fForceProfile, BOOL fForceInstrument);
291 void LoadAndInitializeJITForNgen(LPCWSTR pwzJitName, OUT HINSTANCE* phJit, OUT ICorJitCompiler** ppICorJitCompiler);
292
293
294 BOOL IsAssembly(LPCWSTR path);
295
296 void CreateDependenciesLookupDomain();
297 void ComputeDependencies(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
298 void ComputeAssemblyDependencies(CORINFO_ASSEMBLY_HANDLE hAssembly);
299
300 void CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath);
301 void CreatePdbInCurrentDomain(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath);
302
303 void DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId);
304
305 HRESULT Compile(LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig = NULL);
306 void DontUseProfileData();
307 bool HasProfileData();
308
309 void CompileAssembly(CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
310 ZapImage * CompileModule(CORINFO_MODULE_HANDLE hModule,
311 IMetaDataAssemblyEmit *pEmit);
312 void InstallCompiledAssembly(LPCWSTR szAssemblyName, LPCWSTR szNativeImagePath, HANDLE hFile, SArray<HANDLE> &hFiles);
313
314 HRESULT GetExceptionHR();
315
316 void Success(LPCWSTR format, ...);
317 void Error(LPCWSTR format, ...);
318 void Warning(LPCWSTR format, ...);
319 void Info(LPCWSTR format, ...);
320 void Print(CorZapLogLevel level, LPCWSTR format, ...);
321 void Print(CorZapLogLevel level, LPCWSTR format, va_list args);
322 void PrintErrorMessage(CorZapLogLevel level, Exception *ex);
323 void PrintErrorMessage(CorZapLogLevel level, HRESULT hr);
324
325 BOOL CheckAssemblyUpToDate(CORINFO_ASSEMBLY_HANDLE hAssembly, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
326 BOOL TryToInstallFromRepository(CORINFO_ASSEMBLY_HANDLE hAssembly, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
327 BOOL TryToInstallFromRepositoryDir(SString &strNativeImageDir,
328 SString &strSimpleName,
329 CORCOMPILE_NGEN_SIGNATURE *pNativeImageSig,
330 BOOL *pfHitMismatchedVersion,
331 BOOL *pfHitMismatchedDependencies,
332 BOOL useHardLink = FALSE);
333 void CopyAndInstallFromRepository(LPCWSTR lpszNativeImageDir,
334 LPCWSTR lpszNativeImageName,
335 CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig,
336 BOOL useHardLink = FALSE);
337 void InstallFromRepository(LPCWSTR lpszNativeImage,
338 CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
339
340 void CopyDirectory(LPCWSTR srcPath, LPCWSTR dstPath);
341 void CleanDirectory(LPCWSTR path);
342 void TryCleanDirectory(LPCWSTR path);
343 static void TryCleanDirectory(Zapper * pZapper);
344
345 void GetOutputFolder();
346
347 void SetPlatformAssembliesPaths(LPCWSTR pwzPlatformAssembliesPaths);
348 void SetTrustedPlatformAssemblies(LPCWSTR pwzTrustedPlatformAssemblies);
349 void SetPlatformResourceRoots(LPCWSTR pwzPlatformResourceRoots);
350 void SetAppPaths(LPCWSTR pwzAppPaths);
351 void SetAppNiPaths(LPCWSTR pwzAppNiPaths);
352 void SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths);
353
354#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
355 void SetCLRJITPath(LPCWSTR pwszCLRJITPath);
356 void SetDontLoadJit();
357#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
358
359#if !defined(NO_NGENPDB)
360 void SetDiasymreaderPath(LPCWSTR pwzDiasymreaderPath);
361#endif // !defined(NO_NGENPDB)
362
363 void SetOutputFilename(LPCWSTR pwszOutputFilename);
364 SString GetOutputFileName();
365
366 private:
367
368 void DestroyDomain();
369 void CleanupAssembly();
370
371 void CreateCompilationDomain();
372 void SetContextInfo(LPCWSTR assemblyName = NULL);
373
374 void InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo);
375
376 // DomainCallback is subclassed by each method that would like to compile in a given domain
377 class DomainCallback
378 {
379 public:
380 virtual void doCallback() = NULL;
381 };
382
383 static HRESULT __stdcall GenericDomainCallback(LPVOID pvArgs);
384 void InvokeDomainCallback(DomainCallback *callback);
385
386 void CompileInCurrentDomain(__in LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
387 void ComputeDependenciesInCurrentDomain(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
388 void CreateDependenciesLookupDomainInCurrentDomain();
389
390 void HangWorker(LPCWSTR hangKey, LPCWSTR insideHangKey);
391};
392
393class ZapperOptions
394{
395 public:
396 enum StatOptions
397 {
398 NO_STATS = 0,
399 DEFAULT_STATS = 1,
400 FIXUP_STATS = DEFAULT_STATS << 1,
401 CALL_STATS = FIXUP_STATS << 1,
402 ATTRIB_STATS = CALL_STATS << 1,
403 ALL_STATS = ~NO_STATS,
404 };
405
406 LPWSTR m_zapSet; // Add to zap string. Use to get a private scope of ngen images, for debugging/testing
407
408 LPCWSTR m_repositoryDir; // Directory with prebuilt native images
409 RepositoryFlags m_repositoryFlags; // Copy the native images back to NativeImagesDir
410
411 bool m_autodebug; // Use the debug setting specified by the IL module
412
413 MethodNamesList* m_onlyMethods; // only methods to process
414 MethodNamesList* m_excludeMethods; // excluded these methods
415 mdToken m_onlyOneMethod; // only compile method with matching token
416
417 bool m_silent; // Dont spew any text output
418 bool m_verbose; // Spew extra text ouput
419 bool m_ignoreErrors; // Continue in the face of errors
420 unsigned m_statOptions; // print statisitcs on number of methods, size of code ...
421 bool m_ngenProfileImage; // ngening with "/prof"
422
423 // Which optimizations should be done
424 bool m_ignoreProfileData; // Don't use profile data
425 bool m_noProcedureSplitting; // Don't do procedure splitting
426
427 bool m_fHasAnyProfileData; // true if we successfully loaded and used
428 // any profile data when compiling this assembly
429
430 bool m_fPartialNGen; // Generate partial NGen images using IBC data
431
432 bool m_fPartialNGenSet; // m_fPartialNGen has been set through the environment
433
434 bool m_fAutoNGen; // This is an automatic NGen request
435
436 bool m_fRepositoryOnly; // Install from repository only, no real NGen
437
438 bool m_fNGenLastRetry; // This is retry of the compilation
439
440 CORJIT_FLAGS m_compilerFlags;
441
442 bool m_fNoMetaData; // Do not copy metadata and IL to native image
443
444 void SetCompilerFlags(void);
445
446 ZapperOptions();
447 ~ZapperOptions();
448};
449
450#endif // ZAPPER_H_
451
452