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.
12 #include "ndpversion.h"
16 #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))
18 WCHAR* EqualOrColon(__in __nullterminated WCHAR* szArg)
20 WCHAR* pchE = wcschr(szArg,L'=');
21 WCHAR* pchC = wcschr(szArg,L':');
23 if(pchE == NULL) ret = pchC;
24 else if(pchC == NULL) ret = pchE;
25 else ret = (pchE < pchC)? pchE : pchC;
29 static DWORD g_dwSubsystem=(DWORD)-1,g_dwComImageFlags=(DWORD)-1,g_dwFileAlignment=0,g_dwTestRepeat=0;
30 static ULONGLONG g_stBaseAddress=0;
31 static size_t g_stSizeOfStackReserve=0;
32 extern unsigned int g_uConsoleCP;
37 void MakeTestFile(__in __nullterminated char* szFileName)
42 if(fopen_s(&pF,szFileName,"wt")==0 && pF != NULL)
44 printf("Making test file\n");
45 fprintf(pF,".assembly extern mscorlib {}\n");
46 fprintf(pF,".assembly test%d {}\n",g_dwTestRepeat);
47 fprintf(pF,".module test%d.exe\n",g_dwTestRepeat);
48 fprintf(pF,".method public static void Exec() { .entrypoint\n");
49 for(unsigned i=0; i<g_dwTestRepeat*1000; i++)
51 fprintf(pF,"ldc.i4.1\ncall void [mscorlib]System.Console::WriteLine(int32)\n");
53 fprintf(pF,"ret }\n");
59 void MakeProperSourceFileName(__in __nullterminated WCHAR* wzOrigName,
61 __out_ecount(MAX_FILENAME_LENGTH) WCHAR* wzProperName,
62 __out_ecount(MAX_FILENAME_LENGTH*3) char* szProperName)
64 wcscpy_s(wzProperName,MAX_FILENAME_LENGTH, wzOrigName);
65 size_t j = wcslen(wzProperName);
69 if(wzProperName[j] == '.') break;
70 if((wzProperName[j] == '\\')||(j == 0))
72 wcscat_s(wzProperName,MAX_FILENAME_LENGTH,W(".il"));
77 WszWideCharToMultiByte(uCodePage,0,wzProperName,-1,szProperName,MAX_FILENAME_LENGTH*3-1,NULL,NULL);
80 char* FullFileName(__in __nullterminated WCHAR* wzFileName, unsigned uCodePage)
82 static WCHAR wzFullPath[MAX_FILENAME_LENGTH];
84 WszGetFullPathName(wzFileName,MAX_FILENAME_LENGTH,wzFullPath,&pwz);
85 char szFullPath[MAX_FILENAME_LENGTH*3];
86 WszWideCharToMultiByte(uCodePage,0,wzFullPath,-1,szFullPath,MAX_FILENAME_LENGTH*3-1,NULL,NULL);
87 char* sz = new char[strlen(szFullPath)+1];
88 if(sz) strcpy_s(sz,strlen(szFullPath)+1,szFullPath);
92 WCHAR *pwzInputFiles[1024];
93 WCHAR *pwzDeltaFiles[1024];
95 char szInputFilename[MAX_FILENAME_LENGTH*3];
96 WCHAR wzInputFilename[MAX_FILENAME_LENGTH];
97 WCHAR wzOutputFilename[MAX_FILENAME_LENGTH];
101 #pragma warning(push)
102 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
105 extern "C" int _cdecl wmain(int argc, __in WCHAR **argv)
107 int i, NumFiles = 0, NumDeltaFiles = 0;
108 bool IsDLL = false, IsOBJ = false;
110 MappedFileStream *pIn;
114 bool bReportProgress = TRUE;
115 BOOL bNoDebug = TRUE;
116 WCHAR* wzIncludePath = NULL;
123 // SWI has requested that the exact form of the function call below be used. For details
124 // see http://swi/SWI%20Docs/Detecting%20Heap%20Corruption.doc
125 (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
127 memset(pwzInputFiles,0,1024*sizeof(WCHAR*));
128 memset(pwzDeltaFiles,0,1024*sizeof(WCHAR*));
129 memset(&cw,0,sizeof(Clockwork));
130 cw.cBegin = GetTickCount();
132 g_uConsoleCP = GetConsoleOutputCP();
133 memset(wzOutputFilename,0,sizeof(wzOutputFilename));
137 //CONTRACT_VIOLATION(ThrowsViolation);
140 if(argc < 2) goto ErrorExit;
142 #pragma warning(push)
143 #pragma warning(disable:26000) // "Suppress prefast warning about index overflow"
145 if (! wcscmp(argv[1], W("/?")) || ! wcscmp(argv[1],W("-?")))
150 printf("\nMicrosoft (R) .NET Framework IL Assembler version " VER_FILEVERSION_STR);
151 printf("\n%S\n\n", VER_LEGALCOPYRIGHT_LOGO_STR_L);
152 goto PrintUsageAndExit;
157 printf("\n\nUsage: ilasm [Options] <sourcefile> [Options]");
158 printf("\n\nOptions:");
159 printf("\n/NOLOGO Don't type the logo");
160 printf("\n/QUIET Don't report assembly progress");
161 printf("\n/NOAUTOINHERIT Disable inheriting from System.Object by default");
162 printf("\n/DLL Compile to .dll");
163 printf("\n/EXE Compile to .exe (default)");
164 printf("\n/PDB Create the PDB file without enabling debug info tracking");
165 printf("\n/APPCONTAINER Create an AppContainer exe or dll");
166 printf("\n/DEBUG Disable JIT optimization, create PDB file, use sequence points from PDB");
167 printf("\n/DEBUG=IMPL Disable JIT optimization, create PDB file, use implicit sequence points");
168 printf("\n/DEBUG=OPT Enable JIT optimization, create PDB file, use implicit sequence points");
169 printf("\n/OPTIMIZE Optimize long instructions to short");
170 printf("\n/FOLD Fold the identical method bodies into one");
171 printf("\n/CLOCK Measure and report compilation times");
172 // printf("\n/ERROR Try to create .exe or .dll file despite errors reported");
173 // printf("\n Warning! Results are unpredictable, use this option at your own risk!");
174 printf("\n/OUTPUT=<targetfile> Compile to file with specified name \n\t\t\t(user must provide extension, if any)");
175 printf("\n/KEY=<keyfile> Compile with strong signature \n\t\t\t(<keyfile> contains private key)");
176 printf("\n/KEY=@<keysource> Compile with strong signature \n\t\t\t(<keysource> is the private key source name)");
177 printf("\n/INCLUDE=<path> Set path to search for #include'd files");
178 printf("\n/SUBSYSTEM=<int> Set Subsystem value in the NT Optional header");
179 printf("\n/SSVER=<int>.<int> Set Subsystem version number in the NT Optional header");
180 printf("\n/FLAGS=<int> Set CLR ImageFlags value in the CLR header");
181 printf("\n/ALIGNMENT=<int> Set FileAlignment value in the NT Optional header");
182 printf("\n/BASE=<int> Set ImageBase value in the NT Optional header (max 2GB for 32-bit images)");
183 printf("\n/STACK=<int> Set SizeOfStackReserve value in the NT Optional header");
184 printf("\n/MDV=<version_string> Set Metadata version string");
185 printf("\n/MSV=<int>.<int> Set Metadata stream version (<major>.<minor>)");
186 printf("\n/PE64 Create a 64bit image (PE32+)");
187 printf("\n/HIGHENTROPYVA Set High Entropy Virtual Address capable PE32+ images (default for /APPCONTAINER)");
188 printf("\n/NOCORSTUB Suppress generation of CORExeMain stub");
189 printf("\n/STRIPRELOC Indicate that no base relocations are needed");
190 printf("\n/X64 Target processor: 64bit AMD processor");
191 printf("\n/ARM Target processor: ARM (AArch32) processor");
192 printf("\n/ARM64 Target processor: ARM64 (AArch64) processor");
193 printf("\n/32BITPREFERRED Create a 32BitPreferred image (PE32)");
194 printf("\n/ENC=<file> Create Edit-and-Continue deltas from specified source file");
196 printf("\n\nKey may be '-' or '/'\nOptions are recognized by first 3 characters (except ARM/ARM64)\nDefault source file extension is .il\n");
198 printf("\nTarget defaults:");
199 printf("\n/PE64 => /PE64 /X64");
200 printf("\n/X64 => /PE64 /X64");
201 printf("\n/ARM64 => /PE64 /ARM64");
208 WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W(""));
209 WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W(""));
210 if((pAsm = new Assembler()))
212 pAsm->SetCodePage(uCodePage);
215 pAsm->SetStdMapping(1);
216 //-------------------------------------------------
217 for (i = 1; i < argc; i++)
220 if(argv[i][0] == L'-')
222 if((argv[i][0] == L'/') || (argv[i][0] == L'-'))
225 char szOpt[3 + 1] = { 0 };
226 WszWideCharToMultiByte(uCodePage, 0, &argv[i][1], 3, szOpt, sizeof(szOpt), NULL, NULL);
227 if (!_stricmp(szOpt, "NOA"))
229 pAsm->m_fAutoInheritFromObject = FALSE;
231 else if (!_stricmp(szOpt, "QUI"))
233 pAsm->m_fReportProgress = FALSE;
234 bReportProgress = FALSE;
237 else if (!_stricmp(szOpt, "NOL"))
241 else if (!_stricmp(szOpt, "FOL"))
243 pAsm->m_fFoldCode = TRUE;
245 else if (!_stricmp(szOpt, "DEB"))
247 pAsm->m_dwIncludeDebugInfo = 0x101;
248 // PDB is ignored under 'DEB' option for ilasm on CoreCLR.
249 // https://github.com/dotnet/coreclr/issues/2982
252 WCHAR *pStr = EqualOrColon(argv[i]);
255 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
256 if(wcslen(pStr)==0) goto InvalidOption; //if no suboption
260 wcsncpy_s(wzSubOpt,8,pStr,3);
262 if(0 == _wcsicmp(wzSubOpt,W("OPT")))
263 pAsm->m_dwIncludeDebugInfo = 0x3;
264 else if(0 == _wcsicmp(wzSubOpt,W("IMP")))
265 pAsm->m_dwIncludeDebugInfo = 0x103;
268 const WCHAR *pFmt =((*pStr == '0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
269 if(swscanf_s(pStr,pFmt,&(pAsm->m_dwIncludeDebugInfo))!=1)
270 goto InvalidOption; // bad subooption
275 else if (!_stricmp(szOpt, "PDB"))
277 // 'PDB' option is ignored for ilasm on CoreCLR.
278 // https://github.com/dotnet/coreclr/issues/2982
281 else if (!_stricmp(szOpt, "CLO"))
286 else if (!_stricmp(szOpt, "DLL"))
288 IsDLL = true; IsOBJ = false;
290 else if (!_stricmp(szOpt, "OBJ"))
292 //IsOBJ = true; IsDLL = false;
293 printf("Option /OBJECT is not supported.\n");
296 else if (!_stricmp(szOpt, "ERR"))
298 pAsm->OnErrGo = true;
300 else if (!_stricmp(szOpt, "EXE"))
304 else if (!_stricmp(szOpt, "APP"))
306 pAsm->m_fAppContainer = TRUE;
308 else if (!_stricmp(szOpt, "HIG"))
310 pAsm->m_fHighEntropyVA = TRUE;
312 else if (!_stricmp(szOpt, "OPT"))
314 pAsm->m_fOptimize = TRUE;
316 else if (!_stricmp(szOpt, "X64"))
318 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
319 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64;
321 else if (!_stricmp(szOpt, "ARM"))
323 // szOpt is only 3 characters long. That is not enough to distinguish "ARM" and "ARM64".
324 // We could change it to be longer, but that would affect the existing usability (ARM64 was
325 // added much later). Thus, just distinguish the two here.
326 char szOpt2[5 + 1] = { 0 };
327 WszWideCharToMultiByte(uCodePage, 0, &argv[i][1], 5, szOpt2, sizeof(szOpt2), NULL, NULL);
328 if (!_stricmp(szOpt2, "ARM"))
330 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
331 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM;
333 else if (!_stricmp(szOpt2, "ARM64"))
335 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
336 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM64;
343 else if (!_stricmp(szOpt, "32B"))
345 if (g_dwComImageFlags == (DWORD)-1)
346 g_dwComImageFlags = pAsm->m_dwComImageFlags;
347 COR_SET_32BIT_PREFERRED(g_dwComImageFlags);
349 else if (!_stricmp(szOpt, "PE6"))
351 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32;
352 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64;
354 else if (!_stricmp(szOpt, "NOC"))
356 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_CORMAIN_STUB;
358 else if (!_stricmp(szOpt, "STR"))
360 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_STRIP_RELOCS;
362 else if (!_stricmp(szOpt, "OPT"))
364 pAsm->m_fOptimize = TRUE;
366 else if (!_stricmp(szOpt, "LIS"))
368 printf("Option /LISTING is not supported, use ILDASM.EXE\n");
370 else if (!_stricmp(szOpt, "RES"))
372 if(pAsm->m_wzResourceFile==NULL)
374 WCHAR *pStr = EqualOrColon(argv[i]);
375 if(pStr == NULL) goto ErrorExit;
376 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
377 if(wcslen(pStr)==0) goto InvalidOption; //if no file name
378 pAsm->m_wzResourceFile = pStr;
381 printf("Multiple resource files not allowed. Option %ls skipped\n",argv[i]);
383 else if (!_stricmp(szOpt, "KEY"))
385 WCHAR *pStr = EqualOrColon(argv[i]);
386 if(pStr == NULL) goto InvalidOption;
387 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
388 if(wcslen(pStr)==0) goto InvalidOption; //if no file name
389 pAsm->m_wzKeySourceName = pStr;
391 else if (!_stricmp(szOpt, "INC"))
393 WCHAR *pStr = EqualOrColon(argv[i]);
394 if(pStr == NULL) goto InvalidOption;
395 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
396 if(wcslen(pStr)==0) goto InvalidOption; //if no file name
397 wzIncludePath = pStr;
399 else if (!_stricmp(szOpt, "OUT"))
401 WCHAR *pStr = EqualOrColon(argv[i]);
402 if(pStr == NULL) goto InvalidOption;
403 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
404 if(wcslen(pStr)==0) goto InvalidOption; //if no file name
405 if(wcslen(pStr) >= MAX_FILENAME_LENGTH)
407 fprintf(stderr,"\nError: Output file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1);
410 wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pStr);
412 else if (!_stricmp(szOpt, "MDV"))
414 WCHAR *pStr = EqualOrColon(argv[i]);
415 if(pStr == NULL) goto InvalidOption;
416 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
417 if(wcslen(pStr)==0) goto InvalidOption; //if no version string
418 pAsm->m_wzMetadataVersion = pStr;
420 else if (!_stricmp(szOpt, "MSV"))
422 WCHAR *pStr = EqualOrColon(argv[i]);
423 if(pStr == NULL) goto InvalidOption;
424 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
425 if(wcslen(pStr)==0) goto InvalidOption; //if no version
427 int major=-1,minor=-1;
428 if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2)
430 if((major >= 0)&&(major < 0xFF))
431 pAsm->m_wMSVmajor = (WORD)major;
432 if((minor >= 0)&&(minor < 0xFF))
433 pAsm->m_wMSVminor = (WORD)minor;
437 else if (!_stricmp(szOpt, "ENC"))
439 WCHAR *pStr = EqualOrColon(argv[i]);
440 if(pStr == NULL) goto InvalidOption;
441 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
442 if(wcslen(pStr)==0) goto InvalidOption; //if no file name
443 pwzDeltaFiles[NumDeltaFiles++] = pStr;
444 pAsm->m_fTolerateDupMethods = TRUE;
446 else if (!_stricmp(szOpt, "SUB"))
448 WCHAR *pStr = EqualOrColon(argv[i]);
449 if(pStr == NULL) goto InvalidOption;
451 const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
452 if(swscanf_s(pStr,pFmt,&g_dwSubsystem)!=1) goto InvalidOption;
454 else if (!_stricmp(szOpt, "SSV"))
456 WCHAR *pStr = EqualOrColon(argv[i]);
457 if(pStr == NULL) goto InvalidOption;
458 for(pStr++; *pStr == L' '; pStr++); //skip the blanks
459 if(wcslen(pStr)==0) goto InvalidOption; //if no version
461 int major=-1,minor=-1;
462 if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2)
464 if((major >= 0)&&(major < 0xFFFF))
465 pAsm->m_wSSVersionMajor = (WORD)major;
466 if((minor >= 0)&&(minor < 0xFFFF))
467 pAsm->m_wSSVersionMinor = (WORD)minor;
472 else if (!_stricmp(szOpt, "ALI"))
474 WCHAR *pStr = EqualOrColon(argv[i]);
475 if(pStr == NULL) goto InvalidOption;
477 const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
478 if(swscanf_s(pStr,pFmt,&g_dwFileAlignment)!=1) goto InvalidOption;
479 if((g_dwFileAlignment & (g_dwFileAlignment-1))
480 || (g_dwFileAlignment < 0x200) || (g_dwFileAlignment > 0x10000))
482 fprintf(stderr,"\nFile Alignment must be power of 2 from 0x200 to 0x10000\n");
483 if(!pAsm->OnErrGo) goto InvalidOption;
486 else if (!_stricmp(szOpt, "FLA"))
488 WCHAR *pStr = EqualOrColon(argv[i]);
489 if(pStr == NULL) goto InvalidOption;
491 const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
492 if(swscanf_s(pStr,pFmt,&g_dwComImageFlags)!=1) goto InvalidOption;
494 else if (!_stricmp(szOpt, "BAS"))
496 WCHAR *pStr = EqualOrColon(argv[i]);
497 if(pStr == NULL) goto InvalidOption;
499 const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%I64x") : W("%I64d");
500 if(swscanf_s(pStr,pFmt,&g_stBaseAddress)!=1) goto InvalidOption;
501 if(g_stBaseAddress & 0xFFFF)
503 fprintf(stderr,"\nBase address must be 0x10000-aligned\n");
504 if(!pAsm->OnErrGo) goto InvalidOption;
507 else if (!_stricmp(szOpt, "STA"))
509 WCHAR *pStr = EqualOrColon(argv[i]);
510 if(pStr == NULL) goto InvalidOption;
512 const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
513 if(swscanf_s(pStr,pFmt,&g_stSizeOfStackReserve)!=1) goto InvalidOption;
515 #ifdef _SPECIAL_INTERNAL_USE_ONLY
516 else if (!_stricmp(szOpt, "TES"))
518 WCHAR *pStr = EqualOrColon(argv[i]);
519 if(pStr == NULL) goto InvalidOption;
521 WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%ld";
522 if(swscanf_s(pStr,pFmt,&g_dwTestRepeat)!=1) goto InvalidOption;
528 fprintf(stderr, "Error : Invalid Option: %LS\n", argv[i]);
534 if(wcslen(argv[i]) >= MAX_FILENAME_LENGTH)
536 printf("\nError: Input file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1);
539 pwzInputFiles[NumFiles++] = argv[i];
542 MakeProperSourceFileName(argv[i], uCodePage, wzInputFilename, szInputFilename);
552 if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
554 if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
555 ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM))
557 printf("\nMachine type /ARM64 or /X64 must be specified for 64 bit targets.");
560 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
561 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64;
562 printf(" Type set to X64.");
569 if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM64)
570 ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64))
572 printf("\n64 bit target must be specified for machine type /ARM64 or /X64.");
575 pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32;
576 pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64;
577 printf(" Target set to 64 bit.");
582 if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
584 if(g_stBaseAddress > 0x80000000)
586 fprintf(stderr,"Invalid Image Base specified for 32-bit target\n");
591 if (COR_IS_32BIT_PREFERRED(pAsm->m_dwComImageFlags) &&
592 ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64) ||
593 ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) == 0) ||
594 ((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386) == 0) ||
595 ((pAsm->m_dwComImageFlags & COMIMAGE_FLAGS_ILONLY) == 0)))
597 fprintf(stderr,"/32BITPREFERRED valid only with PE32/X86/ILONLY images\n");
603 fprintf(stderr,"Failed to initialize Assembler\n");
608 MakeTestFile(szInputFilename);
610 if(wzOutputFilename[0] == 0)
612 wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pwzInputFiles[0]);
613 size_t j = wcslen(wzOutputFilename);
617 if(wzOutputFilename[j] == L'.')
619 wzOutputFilename[j] = 0;
624 wcscat_s(wzOutputFilename, MAX_FILENAME_LENGTH,(IsDLL ? W(".dll") : (IsOBJ ? W(".obj") : W(".exe"))));
626 if(wzIncludePath == NULL)
628 PathString wzIncludePathBuffer;
629 if (0 != WszGetEnvironmentVariable(W("ILASM_INCLUDE"), wzIncludePathBuffer))
631 wzIncludePath = wzIncludePathBuffer.GetCopyOfUnicodeString();
635 //------------ Assembler initialization done. Now, to business -----------------------
636 if((pParser = new AsmParse(NULL, pAsm)))
639 pAsm->SetCodePage(uCodePage);
640 pParser->SetIncludePath(wzIncludePath);
641 //======================================================================
644 printf("\nMicrosoft (R) .NET Framework IL Assembler. Version " VER_FILEVERSION_STR);
645 printf("\n%S", VER_LEGALCOPYRIGHT_LOGO_STR_L);
650 wcscpy_s(pAsm->m_wzOutputFileName,MAX_FILENAME_LENGTH,wzOutputFilename);
651 strcpy_s(pAsm->m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szInputFilename);
653 if (SUCCEEDED(pAsm->InitMetaData()))
656 BOOL fAllFilesPresent = TRUE;
657 if(bClock) cw.cParsBegin = GetTickCount();
658 for(iFile = 0; iFile < NumFiles; iFile++)
661 pAsm->SetCodePage(uCodePage);
662 if(iFile) // for the first file, it's already done
664 MakeProperSourceFileName(pwzInputFiles[iFile], uCodePage, wzInputFilename, szInputFilename);
666 if(pAsm->m_fReportProgress)
668 pParser->msg("\nAssembling '%s' ", szInputFilename);
669 if(pAsm->m_fCPlusPlus) pParser->msg(" C++");
670 if(pAsm->m_fWindowsCE) pParser->msg(" WINCE");
671 if(!pAsm->m_fAutoInheritFromObject) pParser->msg(" NOAUTOINHERIT");
672 pParser->msg(IsDLL ? " to DLL" : (IsOBJ? " to OBJ" : " to EXE"));
673 //======================================================================
674 if (pAsm->m_fStdMapping == FALSE)
675 pParser->msg(", with REFERENCE mapping");
678 char szOutputFilename[MAX_FILENAME_LENGTH*3];
679 memset(szOutputFilename,0,sizeof(szOutputFilename));
680 WszWideCharToMultiByte(uCodePage,0,wzOutputFilename,-1,szOutputFilename,MAX_FILENAME_LENGTH*3-1,NULL,NULL);
681 pParser->msg(" --> '%s'\n", szOutputFilename);
685 pIn = new MappedFileStream(wzInputFilename);
687 if ((!pIn) || !(pIn->IsValid()))
689 pParser->msg("Could not open %s\n", szInputFilename);
690 fAllFilesPresent = FALSE;
696 if(GetBinaryTypeA(szInputFilename,&dwBinType))
698 pParser->msg("%s is not a text file\n",szInputFilename);
699 fAllFilesPresent = FALSE;
704 pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument!
706 pParser->ParseFile(pIn);
711 pIn->set_namew(NULL);
715 if(bClock) cw.cParsEnd = GetTickCount();
716 if ((pParser->Success() && fAllFilesPresent) || pAsm->OnErrGo)
719 if(g_dwSubsystem != (DWORD)-1) pAsm->m_dwSubsystem = g_dwSubsystem;
720 if(g_dwComImageFlags != (DWORD)-1) pAsm->m_dwComImageFlags = g_dwComImageFlags;
721 if(g_dwFileAlignment) pAsm->m_dwFileAlignment = g_dwFileAlignment;
722 if(g_stBaseAddress) pAsm->m_stBaseAddress = g_stBaseAddress;
723 if(g_stSizeOfStackReserve) pAsm->m_stSizeOfStackReserve = g_stSizeOfStackReserve;
724 if(FAILED(hr=pAsm->CreatePEFile(wzOutputFilename)))
725 pParser->msg("Could not create output file, error code=0x%08X\n",hr);
728 if(pAsm->m_fFoldCode && pAsm->m_fReportProgress)
729 pParser->msg("%d methods folded\n",pAsm->m_dwMethodsFolded);
730 if(pParser->Success() && fAllFilesPresent) exitval = 0;
733 pParser->msg("Output file contains errors\n");
734 if(pAsm->OnErrGo) exitval = 0;
736 if(exitval == 0) // Write the output file
738 if(bClock) cw.cFilegenEnd = GetTickCount();
739 if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE");
741 if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile)))
744 pParser->msg("Failed to write output file, error code=0x%08X\n",hr);
746 if(bClock) cw.cEnd = GetTickCount();
750 pAsm->m_fENCMode = TRUE;
751 WCHAR wzNewOutputFilename[MAX_FILENAME_LENGTH+16];
752 for(iFile = 0; iFile < NumDeltaFiles; iFile++)
754 wcscpy_s(wzNewOutputFilename,MAX_FILENAME_LENGTH+16,wzOutputFilename);
755 exitval = _snwprintf_s(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32, _TRUNCATE,
757 MakeProperSourceFileName(pwzDeltaFiles[iFile], uCodePage, wzInputFilename, szInputFilename);
758 if(pAsm->m_fReportProgress)
760 pParser->msg("\nAssembling delta '%s' ", szInputFilename);
761 if(pAsm->m_fCPlusPlus) pParser->msg(" C++");
762 if(pAsm->m_fWindowsCE) pParser->msg(" WINCE");
763 if(!pAsm->m_fAutoInheritFromObject) pParser->msg(" NOAUTOINHERIT");
764 pParser->msg(" to DMETA,DIL");
765 //======================================================================
766 if (pAsm->m_fStdMapping == FALSE)
767 pParser->msg(", with REFERENCE mapping");
769 pParser->msg(" --> '%S.*'\n", wzNewOutputFilename);
772 pIn = new MappedFileStream(wzInputFilename);
774 if ((!pIn) || !(pIn->IsValid()))
776 pParser->msg("Could not open %s\n", szInputFilename);
777 fAllFilesPresent = FALSE;
783 if(GetBinaryTypeA(szInputFilename,&dwBinType))
785 pParser->msg("%s is not a text file\n",szInputFilename);
786 fAllFilesPresent = FALSE;
790 if (SUCCEEDED(pAsm->InitMetaDataForENC(wzNewOutputFilename)))
792 pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument!
794 pParser->ParseFile(pIn);
795 if (pParser->Success() || pAsm->OnErrGo)
798 if(FAILED(hr=pAsm->CreateDeltaFiles(wzNewOutputFilename)))
799 pParser->msg("Could not create output delta files, error code=0x%08X\n",hr);
802 if(pAsm->m_fFoldCode && pAsm->m_fReportProgress)
803 pParser->msg("%d methods folded\n",pAsm->m_dwMethodsFolded);
804 if(pParser->Success()) exitval = 0;
805 else pParser->msg("Output delta files contain errors\n");
807 #ifdef GENERATE_SUMMARY_PE_FILE
808 if(pAsm->OnErrGo) exitval = 0;
810 //if(FAILED(hr=pAsm->CreatePEFile(wzOutputFilename)))
811 // pParser->msg("Could not create output file, error code=0x%08X\n",hr);
814 if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE");
816 if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile)))
819 pParser->msg("Failed to write output file, error code=0x%08X\n",hr);
821 else if (pAsm->m_pManifest->m_sStrongName.m_fFullSign)
823 // Strong name sign the resultant assembly.
824 if(pAsm->m_fReportProgress) pParser->msg("Signing file with strong name\n");
825 if (FAILED(hr=pAsm->StrongNameSign()))
828 pParser->msg("Failed to strong name sign output file, error code=0x%08X\n",hr);
834 } // end if (pParser->Success() || pAsm->OnErrGo)
835 } //end if (SUCCEEDED(pAsm->InitMetaDataForENC()))
836 } // end if ((!pIn) || !(pIn->IsValid())) -- else
839 pIn->set_namew(NULL);
843 } // end if(exitval==0)
849 else pParser->msg("Failed to initialize Meta Data\n");
852 else printf("Could not create parser\n");
854 //else printf("Failed to initialize Assembler\n");
857 else printf("Insufficient memory\n");
859 WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W(""));
860 WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W(""));
862 if(exitval || bNoDebug)
864 // PE file was not created, or no debug info required. Kill PDB if any
865 WCHAR* pc = wcsrchr(wzOutputFilename,L'.');
868 pc = &wzOutputFilename[wcslen(wzOutputFilename)];
871 wcscpy_s(pc+1,4,W("PDB"));
873 DeleteFileW(wzOutputFilename);
877 if(bReportProgress) printf("Operation completed successfully\n");
880 printf("Timing (msec): Total run %d\n",(cw.cEnd-cw.cBegin));
881 printf(" Startup %d\n",(cw.cParsBegin-cw.cBegin));
882 printf(" - MD initialization %d\n",(cw.cMDInitEnd - cw.cMDInitBegin));
883 printf(" Parsing %d\n",(cw.cParsEnd - cw.cParsBegin));
884 printf(" Emitting MD %d\n",(cw.cMDEmitEnd - cw.cRef2DefEnd)+(cw.cRef2DefBegin - cw.cMDEmitBegin));
885 //printf(" - global fixups %d\n",(cw.cMDEmit1 - cw.cMDEmitBegin));
886 printf(" - SN sig alloc %d\n",(cw.cMDEmit2 - cw.cMDEmitBegin));
887 printf(" - Classes,Methods,Fields %d\n",(cw.cRef2DefBegin - cw.cMDEmit2));
888 printf(" - Events,Properties %d\n",(cw.cMDEmit3 - cw.cRef2DefEnd));
889 printf(" - MethodImpls %d\n",(cw.cMDEmit4 - cw.cMDEmit3));
890 printf(" - Manifest,CAs %d\n",(cw.cMDEmitEnd - cw.cMDEmit4));
891 printf(" Ref to Def resolution %d\n",(cw.cRef2DefEnd - cw.cRef2DefBegin));
892 printf(" Fixup and linking %d\n",(cw.cFilegenBegin - cw.cMDEmitEnd));
893 printf(" CEE file generation %d\n",(cw.cFilegenEnd - cw.cFilegenBegin));
894 printf(" PE file writing %d\n",(cw.cEnd - cw.cFilegenEnd));
899 printf("\n***** FAILURE ***** \n");
910 int main(int argc, char* str[])
912 g_pszExeFile = str[0];
913 if (0 != PAL_Initialize(argc, str))
915 fprintf(stderr,"Error: Fail to PAL_Initialize\n");
919 WCHAR **argv = new WCHAR*[argc];
920 for (int i = 0; i < argc; i++) {
921 int length = MultiByteToWideChar(CP_ACP, 0, str[i], -1, NULL, 0);
922 ASSERTE_ALL_BUILDS(length != 0);
924 LPWSTR result = new (nothrow) WCHAR[length];
925 ASSERTE_ALL_BUILDS(result != NULL);
927 length = MultiByteToWideChar(CP_ACP, 0, str[i], -1, result, length);
928 ASSERTE_ALL_BUILDS (length != 0);
933 int ret = wmain(argc, argv);
935 for (int i = 0 ; i < argc; i++) {
942 #endif // FEATURE_PAL