Merge pull request #23934 from franksinankaya/gcc_cleanup_18
[platform/upstream/coreclr.git] / src / ilasm / main.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // File:  main.cpp
5 //
6
7 //
8
9 #include "ilasmpch.h"
10
11 #include "asmparse.h"
12 #include "ndpversion.h"
13 #include "shimload.h"
14
15 #include "strsafe.h"
16 #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))
17
18 WCHAR* EqualOrColon(__in __nullterminated WCHAR* szArg)
19 {
20     WCHAR* pchE = wcschr(szArg,L'=');
21     WCHAR* pchC = wcschr(szArg,L':');
22     WCHAR* ret;
23     if(pchE == NULL) ret = pchC;
24     else if(pchC == NULL) ret = pchE;
25     else ret = (pchE < pchC)? pchE : pchC;
26     return ret;
27 }
28
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;
33 #ifdef FEATURE_PAL
34 char * g_pszExeFile;
35 #endif
36
37 void MakeTestFile(__in __nullterminated char* szFileName)
38 {
39     if(g_dwTestRepeat)
40     {
41         FILE* pF = NULL;
42         if(fopen_s(&pF,szFileName,"wt")==0 && pF != NULL)
43         {
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++)
50             {
51                 fprintf(pF,"ldc.i4.1\ncall void [mscorlib]System.Console::WriteLine(int32)\n");
52             }
53             fprintf(pF,"ret }\n");
54             fclose(pF);
55         }
56     }
57 }
58
59 void MakeProperSourceFileName(__in __nullterminated WCHAR* wzOrigName, 
60                               unsigned uCodePage, 
61                               __out_ecount(MAX_FILENAME_LENGTH) WCHAR* wzProperName, 
62                               __out_ecount(MAX_FILENAME_LENGTH*3) char* szProperName)
63 {
64     wcscpy_s(wzProperName,MAX_FILENAME_LENGTH, wzOrigName);
65     size_t j = wcslen(wzProperName);
66     do
67     {
68         j--;
69         if(wzProperName[j] == '.') break;
70         if((wzProperName[j] == '\\')||(j == 0))
71         {
72             wcscat_s(wzProperName,MAX_FILENAME_LENGTH,W(".il"));
73             break;
74         }
75     }
76     while(j);
77     WszWideCharToMultiByte(uCodePage,0,wzProperName,-1,szProperName,MAX_FILENAME_LENGTH*3-1,NULL,NULL);
78 }
79
80 char* FullFileName(__in __nullterminated WCHAR* wzFileName, unsigned uCodePage)
81 {
82     static WCHAR wzFullPath[MAX_FILENAME_LENGTH];
83     WCHAR* pwz;
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);
89     return sz;
90 }
91
92 WCHAR       *pwzInputFiles[1024];
93 WCHAR       *pwzDeltaFiles[1024];
94
95 char        szInputFilename[MAX_FILENAME_LENGTH*3];
96 WCHAR       wzInputFilename[MAX_FILENAME_LENGTH];
97 WCHAR       wzOutputFilename[MAX_FILENAME_LENGTH];
98
99
100 #ifdef _PREFAST_
101 #pragma warning(push)
102 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
103 #endif
104
105 extern "C" int _cdecl wmain(int argc, __in WCHAR **argv)
106 {
107     int         i, NumFiles = 0, NumDeltaFiles = 0;
108     bool        IsDLL = false, IsOBJ = false;
109     Assembler   *pAsm;
110     MappedFileStream *pIn;
111     AsmParse    *pParser;
112     int         exitval=1;
113     bool        bLogo = TRUE;
114     bool        bReportProgress = TRUE;
115     BOOL        bNoDebug = TRUE;
116     WCHAR*      wzIncludePath = NULL;
117     int exitcode = 0;
118     unsigned    uCodePage;
119
120     bool bClock = false;
121     Clockwork   cw;
122
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);
126
127     memset(pwzInputFiles,0,1024*sizeof(WCHAR*));
128     memset(pwzDeltaFiles,0,1024*sizeof(WCHAR*));
129     memset(&cw,0,sizeof(Clockwork));
130     cw.cBegin = GetTickCount();
131
132     g_uConsoleCP = GetConsoleOutputCP();
133     memset(wzOutputFilename,0,sizeof(wzOutputFilename));
134
135 #ifdef _DEBUG
136     DisableThrowCheck();
137     //CONTRACT_VIOLATION(ThrowsViolation);
138 #endif
139
140     if(argc < 2) goto ErrorExit;
141 #ifdef _PREFAST_
142 #pragma warning(push)
143 #pragma warning(disable:26000) // "Suppress prefast warning about index overflow"
144 #endif
145     if (! wcscmp(argv[1], W("/?")) || ! wcscmp(argv[1],W("-?")))
146 #ifdef _PREFAST_
147 #pragma warning(pop)
148 #endif    
149     {
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;
153
154     ErrorExit:
155       exitcode = 1;
156     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");
195       
196       printf("\n\nKey may be '-' or '/'\nOptions are recognized by first 3 characters (except ARM/ARM64)\nDefault source file extension is .il\n");
197
198       printf("\nTarget defaults:");
199       printf("\n/PE64      => /PE64 /X64");
200       printf("\n/X64       => /PE64 /X64");
201       printf("\n/ARM64     => /PE64 /ARM64");
202
203       printf("\n\n");
204       exit(exitcode);
205     }
206
207     uCodePage = CP_UTF8;
208     WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W(""));
209     WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W(""));
210     if((pAsm = new Assembler()))
211     {
212         pAsm->SetCodePage(uCodePage);
213         //if(pAsm->Init())
214         {
215             pAsm->SetStdMapping(1);
216             //-------------------------------------------------
217             for (i = 1; i < argc; i++)
218             {
219 #ifdef FEATURE_PAL
220                 if(argv[i][0] == L'-')
221 #else
222                 if((argv[i][0] == L'/') || (argv[i][0] == L'-'))
223 #endif
224                 {
225                     char szOpt[3 + 1] = { 0 };
226                     WszWideCharToMultiByte(uCodePage, 0, &argv[i][1], 3, szOpt, sizeof(szOpt), NULL, NULL);
227                     if (!_stricmp(szOpt, "NOA"))
228                     {
229                         pAsm->m_fAutoInheritFromObject = FALSE;
230                     }
231                     else if (!_stricmp(szOpt, "QUI"))
232                     {
233                         pAsm->m_fReportProgress = FALSE;
234                         bReportProgress = FALSE;
235                         bLogo = FALSE;
236                     }
237                     else if (!_stricmp(szOpt, "NOL"))
238                     {
239                         bLogo = FALSE;
240                     }
241                     else if (!_stricmp(szOpt, "FOL"))
242                     {
243                       pAsm->m_fFoldCode = TRUE;
244                     }
245                     else if (!_stricmp(szOpt, "DEB"))
246                     {
247                       pAsm->m_dwIncludeDebugInfo = 0x101;
248                       // PDB is ignored under 'DEB' option for ilasm on CoreCLR.
249                       // https://github.com/dotnet/coreclr/issues/2982
250                       bNoDebug = FALSE;
251
252                       WCHAR *pStr = EqualOrColon(argv[i]);
253                       if(pStr != NULL)
254                       {
255                           for(pStr++; *pStr == L' '; pStr++); //skip the blanks
256                           if(wcslen(pStr)==0) goto InvalidOption; //if no suboption
257                           else
258                           {
259                               WCHAR wzSubOpt[8];
260                               wcsncpy_s(wzSubOpt,8,pStr,3);
261                               wzSubOpt[3] = 0;
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;
266                               else 
267                               {
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
271                               }
272                           }
273                       }
274                     }
275                     else if (!_stricmp(szOpt, "PDB"))
276                     {
277                       // 'PDB' option is ignored for ilasm on CoreCLR.
278                       // https://github.com/dotnet/coreclr/issues/2982
279                       bNoDebug = FALSE;
280                     }
281                     else if (!_stricmp(szOpt, "CLO"))
282                     {
283                       bClock = true;
284                       pAsm->SetClock(&cw);
285                     }
286                     else if (!_stricmp(szOpt, "DLL"))
287                     {
288                       IsDLL = true; IsOBJ = false;
289                     }
290                     else if (!_stricmp(szOpt, "OBJ"))
291                     {
292                       //IsOBJ = true; IsDLL = false;
293                       printf("Option /OBJECT is not supported.\n");
294                       goto ErrorExit;
295                     }
296                     else if (!_stricmp(szOpt, "ERR"))
297                     {
298                       pAsm->OnErrGo = true;
299                     }
300                     else if (!_stricmp(szOpt, "EXE"))
301                     {
302                       IsDLL = false;
303                     }
304                     else if (!_stricmp(szOpt, "APP"))
305                     {
306                         pAsm->m_fAppContainer = TRUE;
307                     }
308                     else if (!_stricmp(szOpt, "HIG"))
309                     {
310                         pAsm->m_fHighEntropyVA = TRUE;
311                     }
312                     else if (!_stricmp(szOpt, "OPT"))
313                     {
314                       pAsm->m_fOptimize = TRUE;
315                     }
316                     else if (!_stricmp(szOpt, "X64"))
317                     {
318                       pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;        
319                       pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64;
320                     }
321                     else if (!_stricmp(szOpt, "ARM"))
322                     {
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"))
329                         {
330                             pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;        
331                             pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM;
332                         }
333                         else if (!_stricmp(szOpt2, "ARM64"))
334                         {
335                             pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;        
336                             pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_ARM64;
337                         }
338                         else
339                         {
340                             goto InvalidOption;
341                         }
342                     }
343                     else if (!_stricmp(szOpt, "32B"))
344                     {
345                         if (g_dwComImageFlags == (DWORD)-1)
346                             g_dwComImageFlags = pAsm->m_dwComImageFlags;
347                         COR_SET_32BIT_PREFERRED(g_dwComImageFlags);
348                     }
349                     else if (!_stricmp(szOpt, "PE6"))
350                     {
351                       pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32;
352                       pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64;
353                     }
354                     else if (!_stricmp(szOpt, "NOC"))
355                     {
356                       pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_CORMAIN_STUB;
357                     }
358                     else if (!_stricmp(szOpt, "STR"))
359                     {
360                       pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_STRIP_RELOCS;
361                     }
362                     else if (!_stricmp(szOpt, "OPT"))
363                     {
364                       pAsm->m_fOptimize = TRUE;
365                     }
366                     else if (!_stricmp(szOpt, "LIS"))
367                     {
368                         printf("Option /LISTING is not supported, use ILDASM.EXE\n");
369                     }
370                     else if (!_stricmp(szOpt, "RES"))
371                     {
372                         if(pAsm->m_wzResourceFile==NULL)
373                         {
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;
379                         }
380                         else
381                             printf("Multiple resource files not allowed. Option %ls skipped\n",argv[i]);
382                     }
383                     else if (!_stricmp(szOpt, "KEY"))
384                     {
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;
390                     }
391                     else if (!_stricmp(szOpt, "INC"))
392                     {
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;
398                     }
399                     else if (!_stricmp(szOpt, "OUT"))
400                     {
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)
406                         {
407                             fprintf(stderr,"\nError: Output file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1);
408                             goto ErrorExit;
409                         }
410                         wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pStr);
411                     }
412                     else if (!_stricmp(szOpt, "MDV"))
413                     {
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;
419                     }
420                     else if (!_stricmp(szOpt, "MSV"))
421                     {
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
426                         {
427                             int major=-1,minor=-1;
428                             if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2)
429                             {
430                                 if((major >= 0)&&(major < 0xFF))
431                                     pAsm->m_wMSVmajor = (WORD)major;
432                                 if((minor >= 0)&&(minor < 0xFF))
433                                     pAsm->m_wMSVminor = (WORD)minor;
434                             }
435                         }
436                     }
437                     else if (!_stricmp(szOpt, "ENC"))
438                     {
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;
445                     }
446                     else if (!_stricmp(szOpt, "SUB"))
447                     {
448                         WCHAR *pStr = EqualOrColon(argv[i]);
449                         if(pStr == NULL) goto InvalidOption;
450                         pStr++;
451                         const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
452                         if(swscanf_s(pStr,pFmt,&g_dwSubsystem)!=1) goto InvalidOption;
453                     }
454                     else if (!_stricmp(szOpt, "SSV"))
455                     {
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
460                         {
461                             int major=-1,minor=-1;
462                             if(swscanf_s(pStr,W("%d.%d"),&major, &minor)==2)
463                             {
464                                 if((major >= 0)&&(major < 0xFFFF))
465                                     pAsm->m_wSSVersionMajor = (WORD)major;
466                                 if((minor >= 0)&&(minor < 0xFFFF))
467                                     pAsm->m_wSSVersionMinor = (WORD)minor;
468                             } else 
469                                 goto InvalidOption;
470                         }
471                     }
472                     else if (!_stricmp(szOpt, "ALI"))
473                     {
474                         WCHAR *pStr = EqualOrColon(argv[i]);
475                         if(pStr == NULL) goto InvalidOption;
476                         pStr++;
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))
481                         {
482                             fprintf(stderr,"\nFile Alignment must be power of 2 from 0x200 to 0x10000\n");
483                             if(!pAsm->OnErrGo) goto InvalidOption;
484                         }
485                     }
486                     else if (!_stricmp(szOpt, "FLA"))
487                     {
488                         WCHAR *pStr = EqualOrColon(argv[i]);
489                         if(pStr == NULL) goto InvalidOption;
490                         pStr++;
491                         const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
492                         if(swscanf_s(pStr,pFmt,&g_dwComImageFlags)!=1) goto InvalidOption;
493                     }
494                     else if (!_stricmp(szOpt, "BAS"))
495                     {
496                         WCHAR *pStr = EqualOrColon(argv[i]);
497                         if(pStr == NULL) goto InvalidOption;
498                         pStr++;
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)
502                         {
503                             fprintf(stderr,"\nBase address must be 0x10000-aligned\n");
504                             if(!pAsm->OnErrGo) goto InvalidOption;
505                         }
506                     }
507                     else if (!_stricmp(szOpt, "STA"))
508                     {
509                         WCHAR *pStr = EqualOrColon(argv[i]);
510                         if(pStr == NULL) goto InvalidOption;
511                         pStr++;
512                         const WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? W("%lx") : W("%ld");
513                         if(swscanf_s(pStr,pFmt,&g_stSizeOfStackReserve)!=1) goto InvalidOption;
514                     }
515 #ifdef _SPECIAL_INTERNAL_USE_ONLY
516                     else if (!_stricmp(szOpt, "TES"))
517                     {
518                         WCHAR *pStr = EqualOrColon(argv[i]);
519                         if(pStr == NULL) goto InvalidOption;
520                         pStr++;
521                         WCHAR *pFmt = ((*pStr=='0')&&(*(pStr+1) == 'x'))? L"%lx" : L"%ld";
522                         if(swscanf_s(pStr,pFmt,&g_dwTestRepeat)!=1) goto InvalidOption;
523                     }
524 #endif
525                     else
526                     {
527                     InvalidOption:
528                         fprintf(stderr, "Error : Invalid Option: %LS\n", argv[i]);
529                         goto ErrorExit;
530                     }
531                 }
532                 else
533                 {
534                     if(wcslen(argv[i]) >= MAX_FILENAME_LENGTH)
535                     {
536                         printf("\nError: Input file name exceeds %d characters\n",MAX_FILENAME_LENGTH-1);
537                         goto ErrorExit;
538                     }
539                     pwzInputFiles[NumFiles++] = argv[i];
540                     if(NumFiles == 1)
541                     {
542                         MakeProperSourceFileName(argv[i], uCodePage, wzInputFilename, szInputFilename);
543                     }
544                 }
545
546             }
547             if(NumFiles == 0)
548             {
549                 delete pAsm;
550                 goto ErrorExit;
551             }
552             if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
553             {
554                 if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
555                    ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM))
556                 {
557                     printf("\nMachine type /ARM64 or /X64 must be specified for 64 bit targets.");
558                     if(!pAsm->OnErrGo)
559                     {
560                         pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_MACHINE_MASK;
561                         pAsm->m_dwCeeFileFlags |= ICEE_CREATE_MACHINE_AMD64;
562                         printf(" Type set to X64.");
563                     }
564                     printf("\n");
565                 }
566             }
567             else
568             {
569                 if((pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM64)
570                   ||(pAsm->m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64))
571                 {
572                     printf("\n64 bit target must be specified for machine type /ARM64 or /X64.");
573                     if(!pAsm->OnErrGo)
574                     {
575                         pAsm->m_dwCeeFileFlags &= ~ICEE_CREATE_FILE_PE32;
576                         pAsm->m_dwCeeFileFlags |= ICEE_CREATE_FILE_PE64;
577                         printf(" Target set to 64 bit.");
578                     }
579                     printf("\n");
580                 }
581             }
582             if(pAsm->m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
583             {
584                 if(g_stBaseAddress > 0x80000000)
585                 {
586                     fprintf(stderr,"Invalid Image Base specified for 32-bit target\n");
587                     delete pAsm;
588                     goto ErrorExit;
589                 }
590             }
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)))
596             {
597                 fprintf(stderr,"/32BITPREFERRED valid only with PE32/X86/ILONLY images\n");
598                 delete pAsm;
599                 goto ErrorExit;
600             }
601             if(!pAsm->Init())
602             {
603                 fprintf(stderr,"Failed to initialize Assembler\n");
604                 delete pAsm;
605                 goto ErrorExit;
606             }
607             if(g_dwTestRepeat)
608                 MakeTestFile(szInputFilename);
609
610             if(wzOutputFilename[0] == 0)
611             {
612                 wcscpy_s(wzOutputFilename,MAX_FILENAME_LENGTH,pwzInputFiles[0]);
613                 size_t j = wcslen(wzOutputFilename);
614                 do
615                 {
616                     j--;
617                     if(wzOutputFilename[j] == L'.')
618                     {
619                         wzOutputFilename[j] = 0;
620                         break;
621                     }
622                 }
623                 while(j);
624                 wcscat_s(wzOutputFilename, MAX_FILENAME_LENGTH,(IsDLL ? W(".dll") : (IsOBJ ? W(".obj") : W(".exe"))));
625             }
626             if(wzIncludePath == NULL)
627             {
628                 PathString wzIncludePathBuffer;
629                 if (0 != WszGetEnvironmentVariable(W("ILASM_INCLUDE"), wzIncludePathBuffer))
630                 {
631                     wzIncludePath = wzIncludePathBuffer.GetCopyOfUnicodeString();
632
633                 }
634             }
635             //------------ Assembler initialization done. Now, to business -----------------------
636             if((pParser = new AsmParse(NULL, pAsm)))
637             {
638                 uCodePage = CP_UTF8;
639                 pAsm->SetCodePage(uCodePage);
640                 pParser->SetIncludePath(wzIncludePath);
641                 //======================================================================
642                 if(bLogo)
643                 {
644                     printf("\nMicrosoft (R) .NET Framework IL Assembler.  Version " VER_FILEVERSION_STR);
645                     printf("\n%S", VER_LEGALCOPYRIGHT_LOGO_STR_L);
646                 }
647
648                 pAsm->SetDLL(IsDLL);
649                 pAsm->SetOBJ(IsOBJ);
650                 wcscpy_s(pAsm->m_wzOutputFileName,MAX_FILENAME_LENGTH,wzOutputFilename);
651                 strcpy_s(pAsm->m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szInputFilename);
652
653                 if (SUCCEEDED(pAsm->InitMetaData()))
654                 {
655                     int iFile;
656                     BOOL fAllFilesPresent = TRUE;
657                     if(bClock) cw.cParsBegin = GetTickCount();
658                     for(iFile = 0; iFile < NumFiles; iFile++)
659                     {
660                         uCodePage = CP_UTF8;
661                         pAsm->SetCodePage(uCodePage);
662                         if(iFile) // for the first file, it's already done
663                         {
664                             MakeProperSourceFileName(pwzInputFiles[iFile], uCodePage, wzInputFilename, szInputFilename);
665                         }
666                         if(pAsm->m_fReportProgress)
667                         {
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");
676
677                             {
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);
682                             }
683                         }
684                             
685                         pIn = new MappedFileStream(wzInputFilename);
686
687                         if ((!pIn) || !(pIn->IsValid()))
688                         {
689                             pParser->msg("Could not open %s\n", szInputFilename);
690                             fAllFilesPresent = FALSE;
691                         }
692                         else
693                         {
694 #ifndef FEATURE_PAL
695                             DWORD dwBinType;
696                             if(GetBinaryTypeA(szInputFilename,&dwBinType))
697                             {
698                                 pParser->msg("%s is not a text file\n",szInputFilename);
699                                 fAllFilesPresent = FALSE;
700                             }
701                             else
702 #endif
703                             {
704                                 pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument!
705
706                                 pParser->ParseFile(pIn);
707                             }
708                         }
709                         if(pIn)
710                         {
711                             pIn->set_namew(NULL);
712                             delete pIn;
713                         }
714                     } // end for(iFile)
715                     if(bClock) cw.cParsEnd = GetTickCount();
716                     if ((pParser->Success() && fAllFilesPresent) || pAsm->OnErrGo)
717                     {
718                         HRESULT hr;
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);
726                         else
727                         {
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;
731                             else
732                             {
733                                 pParser->msg("Output file contains errors\n");
734                                 if(pAsm->OnErrGo) exitval = 0;
735                             }
736                             if(exitval == 0) // Write the output file
737                             {
738                                 if(bClock) cw.cFilegenEnd = GetTickCount();
739                                 if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE");
740                                 // Generate the file
741                                 if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile)))
742                                 {
743                                     exitval = 1;
744                                     pParser->msg("Failed to write output file, error code=0x%08X\n",hr);
745                                 }
746                                 if(bClock) cw.cEnd = GetTickCount();
747 #define ENC_ENABLED
748                                 if(exitval==0)
749                                 {
750                                     pAsm->m_fENCMode = TRUE;
751                                     WCHAR wzNewOutputFilename[MAX_FILENAME_LENGTH+16];
752                                     for(iFile = 0; iFile < NumDeltaFiles; iFile++)
753                                     {
754                                         wcscpy_s(wzNewOutputFilename,MAX_FILENAME_LENGTH+16,wzOutputFilename);
755                                         exitval = _snwprintf_s(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32, _TRUNCATE,
756                                                  W(".%d"),iFile+1);
757                                         MakeProperSourceFileName(pwzDeltaFiles[iFile], uCodePage, wzInputFilename, szInputFilename);
758                                         if(pAsm->m_fReportProgress)
759                                         {
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");
768
769                                             pParser->msg(" --> '%S.*'\n", wzNewOutputFilename);
770                                         }
771                                         exitval = 0;
772                                         pIn = new MappedFileStream(wzInputFilename);
773
774                                         if ((!pIn) || !(pIn->IsValid()))
775                                         {
776                                             pParser->msg("Could not open %s\n", szInputFilename);
777                                             fAllFilesPresent = FALSE;
778                                         }
779                                         else
780                                         {
781 #ifndef FEATURE_PAL
782                                             DWORD dwBinType;
783                                             if(GetBinaryTypeA(szInputFilename,&dwBinType))
784                                             {
785                                                 pParser->msg("%s is not a text file\n",szInputFilename);
786                                                 fAllFilesPresent = FALSE;
787                                             }
788                                             else
789 #endif
790                                             if (SUCCEEDED(pAsm->InitMetaDataForENC(wzNewOutputFilename)))
791                                             {
792                                                 pAsm->SetSourceFileName(FullFileName(wzInputFilename,uCodePage)); // deletes the argument!
793
794                                                 pParser->ParseFile(pIn);
795                                                 if (pParser->Success() || pAsm->OnErrGo)
796                                                 {
797                                                     exitval = 1;
798                                                     if(FAILED(hr=pAsm->CreateDeltaFiles(wzNewOutputFilename)))
799                                                         pParser->msg("Could not create output delta files, error code=0x%08X\n",hr);
800                                                     else
801                                                     {
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");
806
807 #ifdef GENERATE_SUMMARY_PE_FILE
808                                                         if(pAsm->OnErrGo) exitval = 0;
809
810                                                         //if(FAILED(hr=pAsm->CreatePEFile(wzOutputFilename)))
811                                                         //    pParser->msg("Could not create output file, error code=0x%08X\n",hr);
812                                                         //else
813                                                         {
814                                                             if(pAsm->m_fReportProgress) pParser->msg("Writing %s file\n", pAsm->m_fOBJ ? "COFF" : "PE");
815                                                             // Generate the file
816                                                             if (FAILED(hr = pAsm->m_pCeeFileGen->GenerateCeeFile(pAsm->m_pCeeFile)))
817                                                             {
818                                                                 exitval = 1;
819                                                                 pParser->msg("Failed to write output file, error code=0x%08X\n",hr);
820                                                             }
821                                                             else if (pAsm->m_pManifest->m_sStrongName.m_fFullSign)
822                                                             {
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()))
826                                                                 {
827                                                                     exitval = 1;
828                                                                     pParser->msg("Failed to strong name sign output file, error code=0x%08X\n",hr);
829                                                                 }
830                                                             }
831                                                         }
832 #endif
833                                                     }
834                                                 } // end if (pParser->Success() || pAsm->OnErrGo)
835                                             } //end if (SUCCEEDED(pAsm->InitMetaDataForENC()))
836                                         } // end if ((!pIn) || !(pIn->IsValid())) -- else
837                                         if(pIn)
838                                         {
839                                             pIn->set_namew(NULL);
840                                             delete pIn;
841                                         }
842                                     } // end for(iFile)
843                                 } // end if(exitval==0)
844                             }
845
846                         }
847                     }
848                 }
849                 else pParser->msg("Failed to initialize Meta Data\n");
850                 delete pParser;
851             }
852             else printf("Could not create parser\n");
853         }
854         //else printf("Failed to initialize Assembler\n");
855         delete pAsm;
856     }
857     else printf("Insufficient memory\n");
858
859     WszSetEnvironmentVariable(W("COMP_ENC_OPENSCOPE"), W(""));
860     WszSetEnvironmentVariable(W("COMP_ENC_EMIT"), W(""));
861
862     if(exitval || bNoDebug)
863     {
864         // PE file was not created, or no debug info required. Kill PDB if any
865         WCHAR* pc = wcsrchr(wzOutputFilename,L'.');
866         if(pc==NULL)
867         {
868             pc = &wzOutputFilename[wcslen(wzOutputFilename)];
869             *pc = L'.';
870         }
871         wcscpy_s(pc+1,4,W("PDB"));
872 #undef DeleteFileW
873         DeleteFileW(wzOutputFilename);
874     }
875     if (exitval == 0)
876     {
877         if(bReportProgress) printf("Operation completed successfully\n");
878         if(bClock)
879         {
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));
895         }
896     }
897     else
898     {
899         printf("\n***** FAILURE ***** \n");
900     }
901     exit(exitval);
902     return exitval;
903 }
904 #ifdef _PREFAST_
905 #pragma warning(pop)
906 #endif
907
908
909 #ifdef FEATURE_PAL
910 int main(int argc, char* str[])
911 {
912     g_pszExeFile = str[0];
913     if (0 != PAL_Initialize(argc, str))
914     {
915         fprintf(stderr,"Error: Fail to PAL_Initialize\n");
916         exit(1);
917     }
918
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);
923
924         LPWSTR result = new (nothrow) WCHAR[length];
925         ASSERTE_ALL_BUILDS(result != NULL);
926
927         length = MultiByteToWideChar(CP_ACP, 0, str[i], -1, result, length);
928         ASSERTE_ALL_BUILDS (length != 0);
929
930         argv[i] = result;
931     }
932
933     int ret = wmain(argc, argv);
934
935     for (int i = 0 ; i < argc; i++) {
936         delete[] argv[i];
937     }
938     delete[] argv;
939
940     return ret;
941 }
942 #endif // FEATURE_PAL
943