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// writer.cpp
6//
7
8#include "ilasmpch.h"
9
10#include "assembler.h"
11
12#include "ceefilegenwriter.h"
13
14#ifndef _MSC_VER
15//cloned definition from ntimage.h that is removed for non MSVC builds
16typedef VOID
17(NTAPI *PIMAGE_TLS_CALLBACK) (
18 PVOID DllHandle,
19 ULONG Reason,
20 PVOID Reserved
21 );
22#endif //_MSC_VER
23
24
25HRESULT Assembler::InitMetaData()
26{
27 HRESULT hr = E_FAIL;
28
29 if(m_fInitialisedMetaData) return S_OK;
30
31 if(bClock) bClock->cMDInitBegin = GetTickCount();
32
33 hr = metaDataGetDispenser(CLSID_CorMetaDataDispenser,
34 IID_IMetaDataDispenserEx, (void **)&m_pDisp);
35 if (FAILED(hr))
36 goto exit;
37
38 if(m_wzMetadataVersion)
39 {
40 VARIANT encOption;
41 BSTR bstr;
42 V_VT(&encOption) = VT_BSTR;
43 V_BSTR(&encOption) = bstr = ::SysAllocString(m_wzMetadataVersion);
44 hr = m_pDisp->SetOption(MetaDataRuntimeVersion, &encOption);
45 ::SysFreeString(bstr);
46 }
47 hr = m_pDisp->DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataEmit2,
48 (IUnknown **)&m_pEmitter);
49 if (FAILED(hr))
50 goto exit;
51
52 m_pManifest->SetEmitter(m_pEmitter);
53 if(FAILED(hr = m_pEmitter->QueryInterface(IID_IMetaDataImport2, (void**)&m_pImporter)))
54 goto exit;
55
56
57 //m_Parser = new AsmParse(m_pEmitter);
58 m_fInitialisedMetaData = TRUE;
59
60 hr = S_OK;
61
62exit:
63 if(bClock) bClock->cMDInitEnd = GetTickCount();
64 return hr;
65}
66/*********************************************************************************/
67/* if we have any Thread local store data, make the TLS directory record for it */
68
69HRESULT Assembler::CreateTLSDirectory() {
70
71 ULONG tlsEnd;
72 HRESULT hr;
73 if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pTLSSection, &tlsEnd))) return(hr);
74
75 if (tlsEnd == 0) // No TLS data, we are done
76 return(S_OK);
77
78 // place to put the TLS directory
79 HCEESECTION tlsDirSec = m_pGlobalDataSection;
80
81 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
82 {
83 DWORD sizeofptr = (DWORD)sizeof(DWORD);
84 DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY32);
85 DWORD offsetofStartAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, StartAddressOfRawData);
86 DWORD offsetofEndAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, EndAddressOfRawData);
87 DWORD offsetofAddressOfIndex = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfIndex);
88 DWORD offsetofAddressOfCallBacks = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfCallBacks);
89
90 // Get memory for for the TLS directory block,as well as a spot for callback chain
91 IMAGE_TLS_DIRECTORY32* tlsDir;
92 if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr);
93 DWORD* callBackChain = (DWORD*) &tlsDir[1];
94 *callBackChain = 0;
95
96 // Find out where the tls directory will end up
97 ULONG tlsDirOffset;
98 if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr);
99 tlsDirOffset -= (sizeofdir + sizeofptr);
100
101 // Set the start of the TLS data (offset 0 of hte TLS section)
102 tlsDir->StartAddressOfRawData = 0;
103 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
104
105 // Set the end of the TLS data
106 tlsDir->EndAddressOfRawData = VALPTR(tlsEnd);
107 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
108
109 // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?)
110 DWORD* tlsIndex;
111 if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr);
112 *tlsIndex = 0xCCCCCCCC; // Does't really matter, the OS will fill it in
113
114 // Find out where tlsIndex index is
115 ULONG tlsIndexOffset;
116 if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr);
117 tlsIndexOffset -= sizeof(DWORD);
118
119 // Set the address of the TLS index
120 tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset);
121 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr);
122
123 // Set addres of callbacks chain
124 tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir));
125 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr);
126
127 // Set the other fields.
128 tlsDir->SizeOfZeroFill = 0;
129 tlsDir->Characteristics = 0;
130
131 hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS,
132 sizeofdir, tlsDirOffset);
133
134 if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
135 COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
136 }
137 else
138 {
139 DWORD sizeofptr = (DWORD)sizeof(__int64);
140 DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY64);
141 DWORD offsetofStartAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, StartAddressOfRawData);
142 DWORD offsetofEndAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, EndAddressOfRawData);
143 DWORD offsetofAddressOfIndex = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfIndex);
144 DWORD offsetofAddressOfCallBacks = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfCallBacks);
145
146 // Get memory for for the TLS directory block,as well as a spot for callback chain
147 IMAGE_TLS_DIRECTORY64* tlsDir;
148 if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr);
149 __int64* callBackChain = (__int64*) &tlsDir[1];
150 *callBackChain = 0;
151
152 // Find out where the tls directory will end up
153 ULONG tlsDirOffset;
154 if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr);
155 tlsDirOffset -= (sizeofdir + sizeofptr);
156
157 // Set the start of the TLS data (offset 0 of hte TLS section)
158 tlsDir->StartAddressOfRawData = 0;
159 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
160
161 // Set the end of the TLS data
162 tlsDir->EndAddressOfRawData = VALPTR(tlsEnd);
163 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
164
165 // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?)
166 DWORD* tlsIndex;
167 if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr);
168 *tlsIndex = 0xCCCCCCCC; // Does't really matter, the OS will fill it in
169
170 // Find out where tlsIndex index is
171 ULONG tlsIndexOffset;
172 if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr);
173 tlsIndexOffset -= sizeof(DWORD);
174
175 // Set the address of the TLS index
176 tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset);
177 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr);
178
179 // Set address of callbacks chain
180 tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir));
181 if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr);
182
183 // Set the other fields.
184 tlsDir->SizeOfZeroFill = 0;
185 tlsDir->Characteristics = 0;
186
187 hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS,
188 sizeofdir, tlsDirOffset);
189 }
190
191 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
192 {
193 report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
194 }
195 m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
196
197 return(hr);
198}
199
200HRESULT Assembler::CreateDebugDirectory()
201{
202 HRESULT hr = S_OK;
203 HCEESECTION sec = m_pILSection;
204 BYTE *de;
205 ULONG deOffset;
206
207 // Only emit this if we're also emitting debug info.
208 if (!(m_fGeneratePDB && m_pSymWriter))
209 return S_OK;
210
211 IMAGE_DEBUG_DIRECTORY debugDirIDD;
212 struct Param
213 {
214 DWORD debugDirDataSize;
215 BYTE *debugDirData;
216 } param;
217 param.debugDirData = NULL;
218
219 // Get the debug info from the symbol writer.
220 if (FAILED(hr=m_pSymWriter->GetDebugInfo(NULL, 0, &param.debugDirDataSize, NULL)))
221 return hr;
222
223 // Will there even be any?
224 if (param.debugDirDataSize == 0)
225 return S_OK;
226
227 // Make some room for the data.
228 PAL_TRY(Param *, pParam, &param) {
229 pParam->debugDirData = new BYTE[pParam->debugDirDataSize];
230 } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
231 hr = E_FAIL;
232 } PAL_ENDTRY
233
234 if(FAILED(hr)) return hr;
235 // Actually get the data now.
236 if (FAILED(hr = m_pSymWriter->GetDebugInfo(&debugDirIDD,
237 param.debugDirDataSize,
238 NULL,
239 param.debugDirData)))
240 goto ErrExit;
241
242 // Grab the timestamp of the PE file.
243 DWORD fileTimeStamp;
244
245 if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile,
246 &fileTimeStamp)))
247 goto ErrExit;
248
249 // Fill in the directory entry.
250 debugDirIDD.TimeDateStamp = VAL32(fileTimeStamp);
251
252 // Grab memory in the section for our stuff.
253 // Note that UpdateResource doesn't work correctly if the debug directory is
254 // in the data section. So instead we put it in the text section (same as
255 // cs compiler).
256 if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec,
257 sizeof(debugDirIDD) +
258 param.debugDirDataSize,
259 4,
260 (void**) &de)))
261 goto ErrExit;
262
263 // Where did we get that memory?
264 if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec,
265 &deOffset)))
266 goto ErrExit;
267
268 deOffset -= (sizeof(debugDirIDD) + param.debugDirDataSize);
269
270 // Setup a reloc so that the address of the raw
271 // data is setup correctly.
272 debugDirIDD.PointerToRawData = VAL32(deOffset + sizeof(debugDirIDD));
273
274 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(
275 sec,
276 deOffset +
277 offsetof(IMAGE_DEBUG_DIRECTORY,
278 PointerToRawData),
279 sec, srRelocFilePos)))
280 goto ErrExit;
281
282 debugDirIDD.AddressOfRawData = VAL32(deOffset + sizeof(debugDirIDD));
283
284 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(
285 sec,
286 deOffset +
287 offsetof(IMAGE_DEBUG_DIRECTORY,
288 AddressOfRawData),
289 sec, srRelocAbsolute)))
290 goto ErrExit;
291 // Emit the directory entry.
292 if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile,
293 sec,
294 IMAGE_DIRECTORY_ENTRY_DEBUG,
295 sizeof(debugDirIDD),
296 deOffset)))
297 goto ErrExit;
298
299 // Copy the debug directory into the section.
300 memcpy(de, &debugDirIDD, sizeof(debugDirIDD));
301 memcpy(de + sizeof(debugDirIDD), param.debugDirData,
302 param.debugDirDataSize);
303
304 if (param.debugDirData)
305 {
306 delete [] param.debugDirData;
307 }
308 return S_OK;
309
310ErrExit:
311 if (param.debugDirData)
312 {
313 delete [] param.debugDirData;
314 }
315 return hr;
316}
317//#ifdef EXPORT_DIR_ENABLED
318HRESULT Assembler::CreateExportDirectory()
319{
320 HRESULT hr = S_OK;
321 DWORD Nentries = m_EATList.COUNT();
322 if(Nentries == 0) return S_OK;
323
324 IMAGE_EXPORT_DIRECTORY exportDirIDD;
325 DWORD exportDirDataSize;
326 BYTE *exportDirData;
327 EATEntry *pEATE;
328 unsigned i, L, ordBase = 0xFFFFFFFF, Ldllname;
329 // get the DLL name from output file name
330 char* pszDllName;
331 Ldllname = (unsigned)wcslen(m_wzOutputFileName)*3+3;
332 char* szOutputFileName = new char[Ldllname];
333 memset(szOutputFileName,0,wcslen(m_wzOutputFileName)*3+3);
334 WszWideCharToMultiByte(CP_ACP,0,m_wzOutputFileName,-1,szOutputFileName,Ldllname,NULL,NULL);
335 pszDllName = strrchr(szOutputFileName,'\\');
336 if(pszDllName == NULL) pszDllName = strrchr(szOutputFileName,':');
337 if(pszDllName == NULL) pszDllName = szOutputFileName;
338 Ldllname = (unsigned)strlen(pszDllName)+1;
339
340 // Allocate buffer for tables
341 for(i = 0, L=0; i < Nentries; i++) L += 1+(unsigned)strlen(m_EATList.PEEK(i)->szAlias);
342 exportDirDataSize = Nentries*5*sizeof(WORD) + L + Ldllname;
343 exportDirData = new BYTE[exportDirDataSize];
344 memset(exportDirData,0,exportDirDataSize);
345
346 // Export address table
347 DWORD* pEAT = (DWORD*)exportDirData;
348 // Name pointer table
349 DWORD* pNPT = pEAT + Nentries;
350 // Ordinal table
351 WORD* pOT = (WORD*)(pNPT + Nentries);
352 // Export name table
353 char* pENT = (char*)(pOT + Nentries);
354 // DLL name
355 char* pDLLName = pENT + L;
356
357 // sort the names/ordinals
358 char** pAlias = new char*[Nentries];
359 for(i = 0; i < Nentries; i++)
360 {
361 pEATE = m_EATList.PEEK(i);
362 pOT[i] = (WORD)pEATE->dwOrdinal;
363 if(pOT[i] < ordBase) ordBase = pOT[i];
364 pAlias[i] = pEATE->szAlias;
365 }
366 bool swapped = true;
367 unsigned j;
368 char* pch;
369 while(swapped)
370 {
371 swapped = false;
372 for(i=1; i < Nentries; i++)
373 {
374 if(strcmp(pAlias[i-1],pAlias[i]) > 0)
375 {
376 swapped = true;
377 pch = pAlias[i-1];
378 pAlias[i-1] = pAlias[i];
379 pAlias[i] = pch;
380 j = pOT[i-1];
381 pOT[i-1] = pOT[i];
382 pOT[i] = j;
383 }
384 }
385 }
386 // normalize ordinals
387 for(i = 0; i < Nentries; i++) pOT[i] -= ordBase;
388 // fill the export address table
389#ifdef _PREFAST_
390#pragma warning(push)
391#pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow"
392#endif
393 for(i = 0; i < Nentries; i++)
394 {
395 pEATE = m_EATList.PEEK(i);
396 pEAT[pEATE->dwOrdinal - ordBase] = pEATE->dwStubRVA;
397 }
398#ifdef _PREFAST_
399#pragma warning(pop)
400#endif
401 // fill the export names table
402 unsigned l;
403 for(i = 0, j = 0; i < Nentries; i++)
404 {
405 pNPT[i] = j; // relative offset in the table
406 l = (unsigned)strlen(pAlias[i])+1;
407 memcpy(&pENT[j],pAlias[i],l);
408 j+=l;
409 }
410 _ASSERTE(j==L);
411 // fill the DLL name
412 memcpy(pDLLName,pszDllName,Ldllname);
413
414 // Data blob is ready pending Name Pointer Table values offsetting
415
416 memset(&exportDirIDD,0,sizeof(IMAGE_EXPORT_DIRECTORY));
417 // Grab the timestamp of the PE file.
418 DWORD fileTimeStamp;
419 if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile,&fileTimeStamp))) return hr;
420 // Fill in the directory entry.
421 // Characteristics, MajorVersion and MinorVersion play no role and stay 0
422 exportDirIDD.TimeDateStamp = VAL32(fileTimeStamp);
423 exportDirIDD.Name = VAL32(exportDirDataSize - Ldllname); // to be offset later
424 exportDirIDD.Base = VAL32(ordBase);
425 exportDirIDD.NumberOfFunctions = VAL32(Nentries);
426 exportDirIDD.NumberOfNames = VAL32(Nentries);
427 exportDirIDD.AddressOfFunctions = 0; // to be offset later
428 exportDirIDD.AddressOfNames = VAL32(Nentries*sizeof(DWORD)); // to be offset later
429 exportDirIDD.AddressOfNameOrdinals = VAL32(Nentries*sizeof(DWORD)*2); // to be offset later
430
431 // Grab memory in the section for our stuff.
432 HCEESECTION sec = m_pGlobalDataSection;
433 BYTE *de;
434 if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec,
435 sizeof(IMAGE_EXPORT_DIRECTORY) + exportDirDataSize,
436 4,
437 (void**) &de))) return hr;
438 // Where did we get that memory?
439 ULONG deOffset, deDataOffset;
440 if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec, &deDataOffset))) return hr;
441
442 deDataOffset -= exportDirDataSize;
443 deOffset = deDataOffset - sizeof(IMAGE_EXPORT_DIRECTORY);
444
445 // Add offsets and set up relocs for header entries
446 exportDirIDD.Name = VAL32(VAL32(exportDirIDD.Name) + deDataOffset);
447 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,Name),
448 sec, srRelocAbsolute))) return hr;
449 exportDirIDD.AddressOfFunctions = VAL32(VAL32(exportDirIDD.AddressOfFunctions) + deDataOffset);
450 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfFunctions),
451 sec, srRelocAbsolute))) return hr;
452 exportDirIDD.AddressOfNames = VAL32(VAL32(exportDirIDD.AddressOfNames) + deDataOffset);
453 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNames),
454 sec, srRelocAbsolute))) return hr;
455 exportDirIDD.AddressOfNameOrdinals = VAL32(VAL32(exportDirIDD.AddressOfNameOrdinals) + deDataOffset);
456 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNameOrdinals),
457 sec, srRelocAbsolute))) return hr;
458
459 // Add offsets and set up relocs for Name Pointer Table
460 j = deDataOffset + Nentries*5*sizeof(WORD); // EA, NP and O Tables come first
461 for(i = 0; i < Nentries; i++)
462 {
463 pNPT[i] += j;
464 if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,exportDirIDD.AddressOfNames+i*sizeof(DWORD),
465 sec, srRelocAbsolute))) return hr;
466 }
467
468
469 // Emit the directory entry.
470 if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile, sec, IMAGE_DIRECTORY_ENTRY_EXPORT,
471 sizeof(IMAGE_EXPORT_DIRECTORY), deOffset))) return hr;
472
473 // Copy the debug directory into the section.
474 memcpy(de, &exportDirIDD, sizeof(IMAGE_EXPORT_DIRECTORY));
475 memcpy(de + sizeof(IMAGE_EXPORT_DIRECTORY), exportDirData, exportDirDataSize);
476 delete [] pAlias;
477 delete [] exportDirData;
478 return S_OK;
479}
480
481static const BYTE ExportStubAMD64Template[] =
482{
483 // Jump through VTFixup table
484 0x48, 0xA1, // rex.w rex.b mov rax,[following address]
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of VTFixup slot
486 0xFF, 0xE0 // jmp [rax]
487};
488static const BYTE ExportStubX86Template[] =
489{
490 // Jump through VTFixup table
491 0xFF, 0x25, // jmp [following address]
492 0x00, 0x00, 0x00, 0x00 //address of VTFixup slot
493};
494static const WORD ExportStubARMTemplate[] =
495{
496 // Jump through VTFixup table
497 0xf8df, 0xf000, // ldr pc, [pc, #0]
498 0x0000, 0x0000 //address of VTFixup slot
499};
500
501DWORD Assembler::EmitExportStub(DWORD dwVTFSlotRVA)
502{
503 DWORD EXPORT_STUB_SIZE = (DWORD)(sizeof(WORD)+sizeof(DWORD));
504 DWORD OFFSET_OF_ADDR = (DWORD)sizeof(WORD);
505 DWORD STUB_ALIGNMENT = 16;
506 BYTE* STUB_TEMPLATE = NULL;
507 DWORD PEFileOffset;
508 BYTE* outBuff;
509 DWORD* pdwVTFSlotRVA;
510
511 if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64)
512 {
513 STUB_TEMPLATE = (BYTE*)&ExportStubAMD64Template[0];
514 EXPORT_STUB_SIZE = sizeof(ExportStubAMD64Template);
515 OFFSET_OF_ADDR = 2;
516 STUB_ALIGNMENT = 4;
517 }
518 else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
519 {
520 STUB_TEMPLATE = (BYTE*)&ExportStubX86Template[0];
521 EXPORT_STUB_SIZE = sizeof(ExportStubX86Template);
522 OFFSET_OF_ADDR = 2;
523 }
524 else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM)
525 {
526 STUB_TEMPLATE = (BYTE*)&ExportStubARMTemplate[0];
527 EXPORT_STUB_SIZE = sizeof(ExportStubARMTemplate);
528 OFFSET_OF_ADDR = 4;
529 STUB_ALIGNMENT = 4;
530 }
531 else
532 {
533 report->error("Unmanaged exports are not implemented for unknown platform");
534 return NULL;
535 }
536 // Addr must be aligned, not the stub!
537 if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0;
538 if((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1))
539 {
540 ULONG L = STUB_ALIGNMENT - ((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1));
541 if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, L, 1, (void **) &outBuff))) return 0;
542 memset(outBuff,0,L);
543 }
544
545 if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, EXPORT_STUB_SIZE, 1, (void **) &outBuff))) return 0;
546 memcpy(outBuff,STUB_TEMPLATE,EXPORT_STUB_SIZE);
547 pdwVTFSlotRVA = (DWORD*)(&outBuff[OFFSET_OF_ADDR]);
548 *pdwVTFSlotRVA = VAL32(dwVTFSlotRVA);
549
550 // The offset where we start, (not where the alignment bytes start!)
551 if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0;
552
553 PEFileOffset -= EXPORT_STUB_SIZE;
554 _ASSERTE(((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1))==0);
555 m_pCeeFileGen->AddSectionReloc(m_pILSection, PEFileOffset+OFFSET_OF_ADDR,m_pGlobalDataSection, srRelocHighLow);
556
557 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
558 {
559 report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
560 }
561 m_pCeeFileGen->GetMethodRVA(m_pCeeFile, PEFileOffset,&PEFileOffset);
562 return PEFileOffset;
563}
564//#endif
565
566HRESULT Assembler::GetCAName(mdToken tkCA, __out LPWSTR *ppszName)
567{
568 HRESULT hr = S_OK;
569 DWORD cchName;
570 LPWSTR name;
571
572 *ppszName = NULL;
573
574 if (TypeFromToken(tkCA) == mdtMemberRef)
575 {
576 mdToken parent;
577 if (FAILED(hr = m_pImporter->GetMemberRefProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL)))
578 return hr;
579 tkCA = parent;
580 }
581 else if (TypeFromToken(tkCA) == mdtMethodDef)
582 {
583 mdToken parent;
584 if (FAILED(hr = m_pImporter->GetMemberProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)))
585 return hr;
586 tkCA = parent;
587 }
588
589 if (TypeFromToken(tkCA) == mdtTypeRef)
590 {
591 // A TypeRef
592 if (FAILED(hr = m_pImporter->GetTypeRefProps(tkCA, NULL, NULL, 0, &cchName)))
593 return hr;
594 if ((name = new WCHAR[cchName + 1]) == NULL)
595 return E_OUTOFMEMORY;
596 hr = m_pImporter->GetTypeRefProps(tkCA, NULL, name, cchName, &cchName);
597 }
598 else
599 {
600 hr = m_pImporter->GetTypeDefProps(tkCA, NULL, 0, &cchName, NULL, NULL);
601 if (hr != S_OK)
602 return hr;
603 if ((name = new WCHAR[cchName + 1]) == NULL)
604 return E_OUTOFMEMORY;
605 hr = m_pImporter->GetTypeDefProps(tkCA, name, cchName, &cchName, NULL, NULL);
606 }
607 if (SUCCEEDED(hr))
608 *ppszName = name;
609 else
610 delete [] name;
611 return hr;
612}
613
614BYTE HexToByte (CHAR wc)
615{
616 if (!iswxdigit(wc)) return (BYTE) 0xff;
617 if (iswdigit(wc)) return (BYTE) (wc - L'0');
618 if (iswupper(wc)) return (BYTE) (wc - L'A' + 10);
619 return (BYTE) (wc - L'a' + 10);
620}
621
622
623BOOL Assembler::EmitFieldsMethods(Class* pClass)
624{
625 unsigned n;
626 BOOL ret = TRUE;
627 // emit all field definition metadata tokens
628 if((n = pClass->m_FieldDList.COUNT()))
629 {
630 FieldDescriptor* pFD;
631 if(m_fReportProgress) printf("Fields: %d;\t",n);
632 for(int j=0; (pFD = pClass->m_FieldDList.PEEK(j)); j++) // can't use POP here: we'll need field list for props
633 {
634 if(!EmitField(pFD))
635 {
636 if(!OnErrGo) return FALSE;
637 ret = FALSE;
638 }
639 pFD->m_fNew = FALSE;
640 }
641 }
642 // Fields are emitted; emit the class layout
643 {
644 COR_FIELD_OFFSET *pOffsets = NULL;
645 ULONG ul = pClass->m_ulPack;
646 ULONG N = pClass->m_dwNumFieldsWithOffset;
647
648 EmitSecurityInfo(pClass->m_cl,
649 pClass->m_pPermissions,
650 pClass->m_pPermissionSets);
651 pClass->m_pPermissions = NULL;
652 pClass->m_pPermissionSets = NULL;
653 if((pClass->m_ulSize != 0xFFFFFFFF)||(ul != 0)||(N != 0))
654 {
655 if(IsTdAutoLayout(pClass->m_Attr)) report->warn("Layout specified for auto-layout class\n");
656 if((ul > 128)||((ul & (ul-1)) !=0 ))
657 report->error("Invalid packing parameter (%d), must be 1,2,4,8...128\n",pClass->m_ulPack);
658 if(N)
659 {
660 pOffsets = new COR_FIELD_OFFSET[N+1];
661 ULONG i,j=0;
662 FieldDescriptor *pFD;
663 for(i=0; (pFD = pClass->m_FieldDList.PEEK(i)); i++)
664 {
665 if(pFD->m_ulOffset != 0xFFFFFFFF)
666 {
667 pOffsets[j].ridOfField = RidFromToken(pFD->m_fdFieldTok);
668 pOffsets[j].ulOffset = pFD->m_ulOffset;
669 j++;
670 }
671 }
672 _ASSERTE(j == N);
673 pOffsets[j].ridOfField = mdFieldDefNil;
674 }
675 m_pEmitter->SetClassLayout (
676 pClass->m_cl, // [IN] typedef
677 ul, // [IN] packing size specified as 1, 2, 4, 8, or 16
678 pOffsets, // [IN] array of layout specification
679 pClass->m_ulSize); // [IN] size of the class
680 if(pOffsets) delete [] pOffsets;
681 }
682 }
683 // emit all method definition metadata tokens
684 if((n = pClass->m_MethodList.COUNT()))
685 {
686 Method* pMethod;
687
688 if(m_fReportProgress) printf("Methods: %d;\t",n);
689 for(int i=0; (pMethod = pClass->m_MethodList.PEEK(i));i++)
690 {
691 if(!EmitMethod(pMethod))
692 {
693 if(!OnErrGo) return FALSE;
694 ret = FALSE;
695 }
696 pMethod->m_fNew = FALSE;
697 }
698 }
699 if(m_fReportProgress) printf("\n");
700 return ret;
701}
702
703HRESULT Assembler::ResolveLocalMemberRefs()
704{
705 unsigned ulTotal=0, ulDefs=0, ulRefs=0, ulUnres=0;
706 MemberRefDList* pList[2] = {&m_LocalMethodRefDList,&m_LocalFieldRefDList};
707
708 if(pList[0]->COUNT() + pList[1]->COUNT())
709 {
710 MemberRefDescriptor* pMRD;
711 mdToken tkMemberDef = 0;
712 int i,j,k;
713 Class *pSearch;
714
715 if(m_fReportProgress) printf("Resolving local member refs: ");
716 for(k=0; k<2; k++)
717 {
718 for(i=0; (pMRD = pList[k]->PEEK(i)) != NULL; i++)
719 {
720 if(pMRD->m_tkResolved) continue;
721
722 tkMemberDef = 0;
723 Method* pListMD;
724 char* pMRD_szName = pMRD->m_szName;
725 DWORD pMRD_dwName = pMRD->m_dwName;
726 ULONG pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0);
727 PCOR_SIGNATURE pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL);
728 CQuickBytes qbSig;
729
730 ulTotal++;
731
732 pSearch = NULL;
733 if(pMRD->m_tdClass == mdTokenNil)
734 pSearch = m_lstClass.PEEK(0);
735 else if((TypeFromToken(pMRD->m_tdClass) != mdtTypeDef)
736 ||((pSearch = m_lstClass.PEEK(RidFromToken(pMRD->m_tdClass)-1)) == NULL))
737 {
738 report->msg("Error: bad parent 0x%08X of local member ref '%s'\n",
739 pMRD->m_tdClass,pMRD->m_szName);
740 }
741 if(pSearch)
742 {
743 // MemberRef may reference a method or a field
744 if(k==0) //methods
745 {
746 if((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG)
747 {
748 ULONG L;
749 qbSig.Shrink(0);
750 _GetFixedSigOfVarArg(pMRD_pSig,pMRD_dwCSig,&qbSig,&L);
751 pMRD_pSig = (PCOR_SIGNATURE)(qbSig.Ptr());
752 pMRD_dwCSig = L;
753 }
754 for(j=0; (pListMD = pSearch->m_MethodList.PEEK(j)) != NULL; j++)
755 {
756 if(pListMD->m_dwName != pMRD_dwName) continue;
757 if(strcmp(pListMD->m_szName,pMRD_szName)) continue;
758 if(pListMD->m_dwMethodCSig != pMRD_dwCSig) continue;
759 if(memcmp(pListMD->m_pMethodSig,pMRD_pSig,pMRD_dwCSig)) continue;
760 tkMemberDef = pListMD->m_Tok;
761 ulDefs++;
762 break;
763 }
764 if(tkMemberDef && ((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG))
765 {
766 WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf);
767
768 if(IsMdPrivateScope(pListMD->m_Attr))
769 {
770 WCHAR* p = wcsstr(wzUniBuf,W("$PST06"));
771 if(p) *p = 0;
772 }
773
774 m_pEmitter->DefineMemberRef(tkMemberDef, wzUniBuf,
775 pMRD->m_pSigBinStr->ptr(),
776 pMRD->m_pSigBinStr->length(),
777 &tkMemberDef);
778 ulDefs--;
779 ulRefs++;
780 }
781 }
782 else // fields
783 {
784 FieldDescriptor* pListFD;
785 for(j=0; (pListFD = pSearch->m_FieldDList.PEEK(j)) != NULL; j++)
786 {
787 if(pListFD->m_dwName != pMRD_dwName) continue;
788 if(strcmp(pListFD->m_szName,pMRD_szName)) continue;
789 if(pListFD->m_pbsSig)
790 {
791 if(pListFD->m_pbsSig->length() != pMRD_dwCSig) continue;
792 if(memcmp(pListFD->m_pbsSig->ptr(),pMRD_pSig,pMRD_dwCSig)) continue;
793 }
794 else if(pMRD_dwCSig) continue;
795 tkMemberDef = pListFD->m_fdFieldTok;
796 ulDefs++;
797 break;
798 }
799 }
800 }
801 if(tkMemberDef==0)
802 { // could not resolve ref to def, make new ref and leave it this way
803 if((pSearch = pMRD->m_pClass) != NULL)
804 {
805 mdToken tkRef = MakeTypeRef(1,pSearch->m_szFQN);
806
807 if(RidFromToken(tkRef))
808 {
809 WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf);
810
811 m_pEmitter->DefineMemberRef(tkRef, wzUniBuf, pMRD_pSig,
812 pMRD_dwCSig, &tkMemberDef);
813 ulRefs++;
814 }
815 else
816 {
817 report->msg("Error: unresolved member ref '%s' of class 0x%08X\n",pMRD->m_szName,pMRD->m_tdClass);
818 ulUnres++;
819 }
820 }
821 else
822 {
823 report->msg("Error: unresolved global member ref '%s'\n",pMRD->m_szName);
824 ulUnres++;
825 }
826 }
827 pMRD->m_tkResolved = tkMemberDef;
828 }
829 }
830 for(i=0; (pMRD = m_MethodSpecList.PEEK(i)) != NULL; i++)
831 {
832 if(pMRD->m_tkResolved) continue;
833 tkMemberDef = pMRD->m_tdClass;
834 if(TypeFromToken(tkMemberDef)==0x99000000)
835 {
836 tkMemberDef = m_LocalMethodRefDList.PEEK(RidFromToken(tkMemberDef)-1)->m_tkResolved;
837 if((TypeFromToken(tkMemberDef)==mdtMethodDef)||(TypeFromToken(tkMemberDef)==mdtMemberRef))
838 {
839 ULONG pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0);
840 PCOR_SIGNATURE pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL);
841 HRESULT hr = m_pEmitter->DefineMethodSpec(tkMemberDef, pMRD_pSig, pMRD_dwCSig, &(pMRD->m_tkResolved));
842 if(FAILED(hr))
843 report->error("Unable to define method instantiation");
844 }
845 }
846 if(RidFromToken(pMRD->m_tkResolved)) ulDefs++;
847 else ulUnres++;
848 }
849 if(m_fReportProgress) printf("%d -> %d defs, %d refs, %d unresolved\n",ulTotal,ulDefs,ulRefs,ulUnres);
850 }
851 return (ulUnres ? E_FAIL : S_OK);
852}
853
854HRESULT Assembler::DoLocalMemberRefFixups()
855{
856 MemberRefDList* pList;
857 unsigned Nlmr = m_LocalMethodRefDList.COUNT() + m_LocalFieldRefDList.COUNT(),
858 Nlmrf = m_LocalMemberRefFixupList.COUNT();
859 HRESULT hr = S_OK;
860 if(Nlmr)
861 {
862 MemberRefDescriptor* pMRD;
863 LocalMemberRefFixup* pMRF;
864 int i;
865 for(i = 0; (pMRF = m_LocalMemberRefFixupList.PEEK(i)) != NULL; i++)
866 {
867 if(m_fENCMode && (!pMRF->m_fNew)) continue;
868
869 switch(TypeFromToken(pMRF->tk))
870 {
871 case 0x99000000: pList = &m_LocalMethodRefDList; break;
872 case 0x98000000: pList = &m_LocalFieldRefDList; break;
873 case 0x9A000000: pList = &m_MethodSpecList; break;
874 default: pList = NULL; break;
875 }
876 if(pList)
877 {
878 if((pMRD = pList->PEEK(RidFromToken(pMRF->tk)-1)) != NULL)
879 SET_UNALIGNED_VAL32((void *)(pMRF->offset), pMRD->m_tkResolved);
880 else
881 {
882 report->msg("Error: bad local member ref token 0x%08X in LMR fixup\n",pMRF->tk);
883 hr = E_FAIL;
884 }
885 }
886 pMRF->m_fNew = FALSE;
887 }
888 }
889 else if(Nlmrf)
890 {
891 report->msg("Error: %d local member ref fixups, no local member refs\n",Nlmrf);
892 hr = E_FAIL;
893 }
894 return hr;
895}
896void Assembler::EmitUnresolvedCustomAttributes()
897{
898 CustomDescr *pCD;
899 while((pCD = m_CustomDescrList.POP()) != NULL)
900 {
901 pCD->tkType = ResolveLocalMemberRef(pCD->tkType);
902 pCD->tkOwner = ResolveLocalMemberRef(pCD->tkOwner);
903 // Look for the class'es interfaceimpl if this CA is one of those
904 if (pCD->tkInterfacePair)
905 pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair);
906 DefineCV(new CustomDescr(pCD->tkOwner,pCD->tkType,pCD->pBlob));
907 }
908}
909
910BOOL Assembler::EmitEventsProps(Class* pClass)
911{
912 unsigned n;
913 BOOL ret = TRUE;
914 // emit all event definition metadata tokens
915 if((n = pClass->m_EventDList.COUNT()))
916 {
917 if(m_fReportProgress) printf("Events: %d;\t",n);
918 EventDescriptor* pED;
919 for(int j=0; (pED = pClass->m_EventDList.PEEK(j)); j++) // can't use POP here: we'll need event list for props
920 {
921 if(!EmitEvent(pED))
922 {
923 if(!OnErrGo) return FALSE;
924 ret = FALSE;
925 }
926 pED->m_fNew = FALSE;
927 }
928 }
929 // emit all property definition metadata tokens
930 if((n = pClass->m_PropDList.COUNT()))
931 {
932 if(m_fReportProgress) printf("Props: %d;\t",n);
933 PropDescriptor* pPD;
934
935 for(int j=0; (pPD = pClass->m_PropDList.PEEK(j)); j++)
936 {
937 if(!EmitProp(pPD))
938 {
939 if(!OnErrGo) return FALSE;
940 ret = FALSE;
941 }
942 pPD->m_fNew = FALSE;
943 }
944 }
945 if(m_fReportProgress) printf("\n");
946 return ret;
947}
948
949HRESULT Assembler::AllocateStrongNameSignature()
950{
951 HRESULT hr = S_OK;
952 HCEESECTION hSection;
953 DWORD dwDataLength;
954 DWORD dwDataOffset;
955 DWORD dwDataRVA;
956 VOID *pvBuffer;
957 AsmManStrongName *pSN = &m_pManifest->m_sStrongName;
958
959 // pSN->m_cbPublicKey is the length of the m_pbPublicKey
960 dwDataLength = ((int)pSN->m_cbPublicKey < 128 + 32) ? 128 : (int)pSN->m_cbPublicKey - 32;
961
962 // Grab memory in the section for our stuff.
963 if (FAILED(hr = m_pCeeFileGen->GetIlSection(m_pCeeFile,
964 &hSection)))
965 {
966 return hr;
967 }
968
969 if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(hSection,
970 dwDataLength,
971 4,
972 &pvBuffer)))
973 {
974 return hr;
975 }
976
977 // Where did we get that memory?
978 if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(hSection,
979 &dwDataOffset)))
980 {
981 return hr;
982 }
983
984 dwDataOffset -= dwDataLength;
985
986 // Convert to an RVA.
987 if (FAILED(hr = m_pCeeFileGen->GetMethodRVA(m_pCeeFile,
988 dwDataOffset,
989 &dwDataRVA)))
990 {
991 return hr;
992 }
993
994 // Emit the directory entry.
995 if (FAILED(hr = m_pCeeFileGen->SetStrongNameEntry(m_pCeeFile,
996 dwDataLength,
997 dwDataRVA)))
998 {
999 return hr;
1000 }
1001
1002 return S_OK;
1003}
1004
1005#ifdef _PREFAST_
1006#pragma warning(push)
1007#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1008#endif
1009HRESULT Assembler::CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename)
1010{
1011 HRESULT hr;
1012 DWORD mresourceSize = 0;
1013 BYTE* mresourceData = NULL;
1014 WCHAR* wzScopeName = NULL;
1015
1016 if(bClock) bClock->cMDEmitBegin = GetTickCount();
1017 if(m_fReportProgress) printf("Creating PE file\n");
1018 if (!m_pEmitter)
1019 {
1020 printf("Error: Cannot create a PE file with no metadata\n");
1021 return E_FAIL;
1022 }
1023 if(!(m_fDLL || m_fEntryPointPresent))
1024 {
1025 printf("Error: No entry point declared for executable\n");
1026 if(!OnErrGo) return E_FAIL;
1027 }
1028
1029 if(bClock) bClock->cMDEmit1 = GetTickCount();
1030
1031 // Allocate space for a strong name signature if we're delay or full
1032 // signing the assembly.
1033 if (m_pManifest->m_sStrongName.m_pbPublicKey)
1034 {
1035 if (FAILED(hr = AllocateStrongNameSignature()))
1036 {
1037 goto exit;
1038 }
1039 }
1040
1041 if(bClock) bClock->cMDEmit2 = GetTickCount();
1042
1043 if(m_VTFList.COUNT()==0)
1044 {
1045 Method* pMD;
1046 Class* pClass;
1047 unsigned N=0, OrdBase=0xFFFFFFFF, i, j;
1048 for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++)
1049 {
1050 for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++)
1051 {
1052 if(pMD->m_dwExportOrdinal != 0xFFFFFFFF)
1053 {
1054 N++;
1055 if(pMD->m_dwExportOrdinal < OrdBase) OrdBase = pMD->m_dwExportOrdinal;
1056 }
1057 }
1058 }
1059 if(N)
1060 {
1061 for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++)
1062 {
1063 for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++)
1064 {
1065 if(pMD->m_wVTSlot >= 0x8000)
1066 {
1067 pMD->m_wVTSlot -= 0x8000 + OrdBase - 1;
1068 }
1069 }
1070 }
1071 SetDataSection();
1072 char* sz = new char[20];
1073 strcpy_s(sz,20,"VTF_EAT_internal");
1074 EmitDataLabel(sz);
1075 sz = new char[20];
1076 strcpy_s(sz,20,"VTF_EAT_internal");
1077 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1078 {
1079 ULONGLONG *pdw = new ULONGLONG[N];
1080 for(i=0; i<N; i++) pdw[i] = UI64(0xdeadbeefdeadbeef);
1081 EmitData(pdw,sizeof(ULONGLONG)*N);
1082 m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_64BIT|COR_VTABLE_FROM_UNMANAGED,sz));
1083 delete [] pdw;
1084 }
1085 else
1086 {
1087 unsigned *pdw = new unsigned[N];
1088 for(i=0; i<N; i++) pdw[i] = 0xdeadbeef;
1089 EmitData(pdw,sizeof(unsigned)*N);
1090 m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_32BIT|COR_VTABLE_FROM_UNMANAGED,sz));
1091 delete [] pdw;
1092 }
1093 }
1094 }
1095 wzScopeName=&wzUniBuf[0];
1096 if(m_szScopeName[0]) // default: scope name = output file name
1097 {
1098 WszMultiByteToWideChar(g_uCodePage,0,m_szScopeName,-1,wzScopeName,MAX_SCOPE_LENGTH);
1099 }
1100 else
1101 {
1102 WCHAR* pwc;
1103 if ((pwc = wcsrchr(m_wzOutputFileName, '\\')) != NULL) pwc++;
1104 else if ((pwc = wcsrchr(m_wzOutputFileName, ':')) != NULL) pwc++;
1105 else pwc = m_wzOutputFileName;
1106
1107 wcsncpy_s(wzScopeName, MAX_SCOPE_LENGTH, pwc, _TRUNCATE);
1108 }
1109 hr = m_pEmitter->SetModuleProps(wzScopeName);
1110
1111 if (FAILED(hr))
1112 goto exit;
1113
1114 EmitImports();
1115 if(m_pManifest)
1116 {
1117 hr = S_OK;
1118 if(m_pManifest->m_pAsmEmitter==NULL)
1119 hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &(m_pManifest->m_pAsmEmitter));
1120
1121 if(SUCCEEDED(hr))
1122 {
1123 m_pManifest->EmitAssemblyRefs();
1124 }
1125 }
1126 // Emit classes, class members and globals:
1127 {
1128 Class *pSearch;
1129 int i;
1130 BOOL bIsUndefClass = FALSE;
1131 if(m_fReportProgress) printf("\nEmitting classes:\n");
1132 for (i=1; (pSearch = m_lstClass.PEEK(i)); i++) // 0 is <Module>
1133 {
1134 if(m_fReportProgress)
1135 printf("Class %d:\t%s\n",i,pSearch->m_szFQN);
1136
1137 if(pSearch->m_bIsMaster)
1138 {
1139 report->msg("Error: Reference to undefined class '%s'\n",pSearch->m_szFQN);
1140 bIsUndefClass = TRUE;
1141 }
1142 if(!EmitClass(pSearch))
1143 {
1144 if(!OnErrGo) return E_FAIL;
1145 }
1146 pSearch->m_fNew = FALSE;
1147 }
1148 if(bIsUndefClass && !OnErrGo) return E_FAIL;
1149
1150 if(m_fReportProgress) printf("\nEmitting fields and methods:\n");
1151 for (i=0; (pSearch = m_lstClass.PEEK(i)) != NULL; i++)
1152 {
1153 if(m_fReportProgress)
1154 {
1155 if(i == 0) printf("Global \t");
1156 else printf("Class %d\t",i);
1157 }
1158 if(!EmitFieldsMethods(pSearch))
1159 {
1160 if(!OnErrGo) return E_FAIL;
1161 }
1162 }
1163 }
1164
1165 // All ref'ed items def'ed in this file are emitted, resolve member refs to member defs:
1166 if(bClock) bClock->cRef2DefBegin = GetTickCount();
1167 hr = ResolveLocalMemberRefs();
1168 if(bClock) bClock->cRef2DefEnd = GetTickCount();
1169 if(FAILED(hr) &&(!OnErrGo)) goto exit;
1170
1171 // Local member refs resolved, emit events, props and method impls
1172 {
1173 Class *pSearch;
1174 int i;
1175
1176 if(m_fReportProgress) printf("\nEmitting events and properties:\n");
1177 for (i=0; (pSearch = m_lstClass.PEEK(i)); i++)
1178 {
1179 if(m_fReportProgress)
1180 {
1181 if(i == 0) printf("Global \t");
1182 else printf("Class %d\t",i);
1183 }
1184 if(!EmitEventsProps(pSearch))
1185 {
1186 if(!OnErrGo) return E_FAIL;
1187 }
1188 pSearch->m_fNewMembers = FALSE;
1189 }
1190 }
1191 if(bClock) bClock->cMDEmit3 = GetTickCount();
1192 if(m_MethodImplDList.COUNT())
1193 {
1194 if(m_fReportProgress) report->msg("Method Implementations (total): %d\n",m_MethodImplDList.COUNT());
1195 if(!EmitMethodImpls())
1196 {
1197 if(!OnErrGo) return E_FAIL;
1198 }
1199 }
1200 // Emit the rest of the metadata
1201 if(bClock) bClock->cMDEmit4 = GetTickCount();
1202 hr = S_OK;
1203 if(m_pManifest)
1204 {
1205 if (FAILED(hr = m_pManifest->EmitManifest())) goto exit;
1206 }
1207 ResolveLocalMemberRefs(); // in case CAs added some
1208 EmitUnresolvedCustomAttributes();
1209 // Emit typedefs as special TypeSpecs
1210 {
1211#define ELEMENT_TYPE_TYPEDEF ELEMENT_TYPE_MAX+1
1212 TypeDefDescr* pTDD;
1213 unsigned __int8* pb;
1214 unsigned namesize;
1215 while((pTDD = m_TypeDefDList.POP()))
1216 {
1217 BinStr* pbs = new BinStr();
1218 if(pbs)
1219 {
1220 namesize = 1 + (unsigned)strlen(pTDD->m_szName);
1221 pb = pbs->getBuff(namesize + 1 + sizeof(mdToken));
1222 *pb = ELEMENT_TYPE_TYPEDEF;
1223 memcpy(++pb,pTDD->m_szName,namesize);
1224 pTDD->m_tkTypeSpec = ResolveLocalMemberRef(pTDD->m_tkTypeSpec);
1225 memcpy(pb+namesize,&(pTDD->m_tkTypeSpec),sizeof(mdToken));
1226 if(TypeFromToken(pTDD->m_tkTypeSpec)==mdtCustomAttribute)
1227 {
1228 CustomDescr* pCA = pTDD->m_pCA;
1229 pbs->appendInt32(pCA->tkType);
1230 pbs->appendInt32(pCA->tkOwner);
1231 if(pCA->pBlob) pbs->append(pCA->pBlob);
1232 }
1233 ResolveTypeSpec(pbs);
1234 delete pbs;
1235 }
1236 delete pTDD;
1237 }
1238 }
1239 if(bClock) bClock->cMDEmitEnd = GetTickCount();
1240
1241 hr = DoLocalMemberRefFixups();
1242 if(FAILED(hr) &&(!OnErrGo)) goto exit;
1243 // Local member refs resolved and fixed up in BinStr method bodies. Emit the bodies.
1244 {
1245 Class* pClass;
1246 Method* pMethod;
1247 for (int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1248 {
1249 for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++)
1250 {
1251 if(!EmitMethodBody(pMethod,NULL))
1252 {
1253 report->msg("Error: failed to emit body of '%s'\n",pMethod->m_szName);
1254 hr = E_FAIL;
1255 if(!OnErrGo) goto exit;
1256 }
1257 pMethod->m_fNewBody = FALSE;
1258 }
1259 }
1260 //while(MethodBody* pMB = m_MethodBodyList.POP()) delete pMB;
1261 }
1262
1263 if (DoGlobalFixups() == FALSE)
1264 return E_FAIL;
1265
1266 if(m_wzResourceFile)
1267 {
1268#ifdef FEATURE_PAL
1269 report->msg("Warning: The Win32 resource file '%S' is ignored and not emitted on xPlatform.\n", m_wzResourceFile);
1270#else
1271 if (FAILED(hr=m_pCeeFileGen->SetResourceFileName(m_pCeeFile, m_wzResourceFile)))
1272 {
1273 report->msg("Warning: failed to set Win32 resource file name '%S', hr=0x%8.8X\n The Win32 resource is not emitted.\n",
1274 m_wzResourceFile, hr);
1275 }
1276#endif
1277 }
1278
1279 if (FAILED(hr=CreateTLSDirectory())) goto exit;
1280
1281 if (FAILED(hr=CreateDebugDirectory())) goto exit;
1282
1283 if (FAILED(hr=m_pCeeFileGen->SetOutputFileName(m_pCeeFile, pwzOutputFilename))) goto exit;
1284
1285 // Reserve a buffer for the meta-data
1286 DWORD metaDataSize;
1287 if (FAILED(hr=m_pEmitter->GetSaveSize(cssAccurate, &metaDataSize))) goto exit;
1288 BYTE* metaData;
1289 if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, metaDataSize, sizeof(DWORD), (void**) &metaData))) goto exit;
1290 ULONG metaDataOffset;
1291 if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pILSection, &metaDataOffset))) goto exit;
1292 metaDataOffset -= metaDataSize;
1293 // set managed resource entry, if any
1294 if(m_pManifest && m_pManifest->m_dwMResSizeTotal)
1295 {
1296 mresourceSize = m_pManifest->m_dwMResSizeTotal;
1297
1298 if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, mresourceSize,
1299 sizeof(DWORD), (void**) &mresourceData))) goto exit;
1300 if (FAILED(hr=m_pCeeFileGen->SetManifestEntry(m_pCeeFile, mresourceSize, 0))) goto exit;
1301 }
1302 if(m_VTFList.COUNT())
1303 {
1304 GlobalLabel *pGlobalLabel;
1305 VTFEntry* pVTFEntry;
1306
1307 if(m_pVTable) delete m_pVTable; // can't have both; list takes precedence
1308 m_pVTable = new BinStr();
1309 hr = S_OK;
1310 for(WORD k=0; (pVTFEntry = m_VTFList.POP()); k++)
1311 {
1312 if((pGlobalLabel = FindGlobalLabel(pVTFEntry->m_szLabel)))
1313 {
1314 Method* pMD;
1315 Class* pClass;
1316 m_pVTable->appendInt32(pGlobalLabel->m_GlobalOffset);
1317 m_pVTable->appendInt16(pVTFEntry->m_wCount);
1318 m_pVTable->appendInt16(pVTFEntry->m_wType);
1319 for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1320 {
1321 for(WORD j = 0; (pMD = pClass->m_MethodList.PEEK(j)); j++)
1322 {
1323 if(pMD->m_wVTEntry == k+1)
1324 {
1325 char* ptr;
1326 if(SUCCEEDED(hr = m_pCeeFileGen->ComputeSectionPointer(m_pGlobalDataSection,pGlobalLabel->m_GlobalOffset,&ptr)))
1327 {
1328 DWORD dwDelta;
1329 if((pVTFEntry->m_wType & COR_VTABLE_32BIT))
1330 {
1331 dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(DWORD);
1332 ptr += dwDelta;
1333 DWORD* mptr = (DWORD*)ptr;
1334 *mptr = (DWORD)(pMD->m_Tok);
1335 }
1336 else
1337 {
1338 dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(ULONGLONG);
1339 ptr += dwDelta;
1340 ULONGLONG* mptr = (ULONGLONG*)ptr;
1341 *mptr = (ULONGLONG)(pMD->m_Tok);
1342 }
1343 if(pMD->m_dwExportOrdinal != 0xFFFFFFFF)
1344 {
1345 EATEntry* pEATE = new EATEntry;
1346 pEATE->dwOrdinal = pMD->m_dwExportOrdinal;
1347 pEATE->szAlias = pMD->m_szExportAlias ? pMD->m_szExportAlias : pMD->m_szName;
1348 pEATE->dwStubRVA = EmitExportStub(pGlobalLabel->m_GlobalOffset+dwDelta);
1349 m_EATList.PUSH(pEATE);
1350 }
1351 }
1352 else
1353 report->msg("Error: Failed to get pointer to label '%s' inVTable fixup\n",pVTFEntry->m_szLabel);
1354 }
1355 }
1356 }
1357 }
1358 else
1359 {
1360 report->msg("Error: Unresolved label '%s' in VTable fixup\n",pVTFEntry->m_szLabel);
1361 hr = E_FAIL;
1362 }
1363 delete pVTFEntry;
1364 }
1365 if(FAILED(hr)) goto exit;
1366 }
1367 if(m_pVTable)
1368 {
1369 ULONG i, N = m_pVTable->length()/sizeof(DWORD);
1370 ULONG ulVTableOffset;
1371 m_pCeeFileGen->GetSectionDataLen (m_pILSection, &ulVTableOffset);
1372 // SetVTableEntry will align VTable on DWORD
1373 ulVTableOffset = (ulVTableOffset + (ULONG)sizeof(DWORD) - 1) & ~((ULONG)sizeof(DWORD) - 1);
1374 if (FAILED(hr=m_pCeeFileGen->SetVTableEntry64(m_pCeeFile, m_pVTable->length(),(void*)(m_pVTable->ptr())))) goto exit; // @WARNING: casting down from pointer-size to DWORD
1375 for(i = 0; i < N; i+=2)
1376 {
1377 m_pCeeFileGen->AddSectionReloc(m_pILSection,
1378 ulVTableOffset+(i*sizeof(DWORD)),
1379 m_pGlobalDataSection,
1380 srRelocAbsolute);
1381 }
1382 }
1383 if(m_EATList.COUNT())
1384 {
1385 if(FAILED(CreateExportDirectory())) goto exit;
1386 m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1387 if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
1388 COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
1389 }
1390 if (m_fWindowsCE)
1391 {
1392 if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, 2, 10))) goto exit;
1393
1394 if (FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, 0x10000))) goto exit;
1395 }
1396 else
1397 {
1398 if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM || m_fAppContainer)
1399 {
1400 // For AppContainer and ARM, you must have a minimum subsystem version of 6.02
1401 m_wSSVersionMajor = (m_wSSVersionMajor < 6) ? 6 : m_wSSVersionMajor;
1402 m_wSSVersionMinor = (m_wSSVersionMinor < 2 && m_wSSVersionMajor <= 6) ? 2 : m_wSSVersionMinor;
1403
1404 }
1405
1406 // Default the subsystem, instead the user doesn't set it to GUI or CUI
1407 if (m_dwSubsystem == (DWORD)-1)
1408 // The default for ILAsm previously was CUI, so that should be the default behavior...
1409 m_dwSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
1410
1411 if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, m_dwSubsystem, m_wSSVersionMajor, m_wSSVersionMinor))) goto exit;
1412 }
1413
1414 if (FAILED(hr=m_pCeeFileGen->ClearComImageFlags(m_pCeeFile, COMIMAGE_FLAGS_ILONLY))) goto exit;
1415 if (FAILED(hr=m_pCeeFileGen->SetComImageFlags(m_pCeeFile, m_dwComImageFlags & ~COMIMAGE_FLAGS_STRONGNAMESIGNED))) goto exit;
1416
1417 if(m_dwFileAlignment)
1418 {
1419 if(FAILED(hr=m_pCeeFileGen->SetFileAlignment(m_pCeeFile, m_dwFileAlignment))) goto exit;
1420 }
1421 if(m_stBaseAddress)
1422 {
1423
1424 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1425 {
1426 if(FAILED(hr=m_pCeeFileGen->SetImageBase64(m_pCeeFile, m_stBaseAddress))) goto exit;
1427 }
1428 else
1429 {
1430 if(FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, (size_t)m_stBaseAddress))) goto exit;
1431 }
1432 }
1433 if(m_stSizeOfStackReserve || m_fAppContainer || m_fHighEntropyVA)
1434 {
1435 PIMAGE_NT_HEADERS pNT;
1436 PIMAGE_SECTION_HEADER pSect;
1437 ULONG ulNumSect;
1438 if(FAILED(hr=m_pCeeFileGen->GetHeaderInfo(m_pCeeFile,&pNT,&pSect,&ulNumSect))) goto exit;
1439 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1440 {
1441 PIMAGE_OPTIONAL_HEADER64 pOpt = (PIMAGE_OPTIONAL_HEADER64)(&pNT->OptionalHeader);
1442 if (m_stSizeOfStackReserve)
1443 pOpt->SizeOfStackReserve = VAL64(m_stSizeOfStackReserve);
1444 if (m_fAppContainer)
1445 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER;
1446 if (m_fHighEntropyVA)
1447 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA;
1448 }
1449 else
1450 {
1451 PIMAGE_OPTIONAL_HEADER32 pOpt = (PIMAGE_OPTIONAL_HEADER32)(&pNT->OptionalHeader);
1452 if (m_stSizeOfStackReserve)
1453 pOpt->SizeOfStackReserve = (DWORD)VAL32(m_stSizeOfStackReserve);
1454 if (m_fAppContainer)
1455 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER;
1456 if (m_fHighEntropyVA)
1457 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA;
1458 }
1459 }
1460 //Compute all the RVAs
1461 if (FAILED(hr=m_pCeeFileGen->LinkCeeFile(m_pCeeFile))) goto exit;
1462
1463 // Fix up any fields that have RVA associated with them
1464 if (m_fHaveFieldsWithRvas) {
1465 hr = S_OK;
1466 ULONG dataSectionRVA;
1467 if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pGlobalDataSection, &dataSectionRVA))) goto exit;
1468
1469 ULONG tlsSectionRVA;
1470 if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pTLSSection, &tlsSectionRVA))) goto exit;
1471
1472 ULONG ilSectionRVA;
1473 if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pILSection, &ilSectionRVA))) goto exit;
1474
1475 FieldDescriptor* pListFD;
1476 Class* pClass;
1477 for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1478 {
1479 for(int j=0; (pListFD = pClass->m_FieldDList.PEEK(j)); j++)
1480 {
1481 if (pListFD->m_rvaLabel != 0)
1482 {
1483 DWORD rva;
1484 if(*(pListFD->m_rvaLabel)=='@')
1485 {
1486 rva = (DWORD)atoi(pListFD->m_rvaLabel + 1);
1487 }
1488 else
1489 {
1490 GlobalLabel *pLabel = FindGlobalLabel(pListFD->m_rvaLabel);
1491 if (pLabel == 0)
1492 {
1493 report->msg("Error:Could not find label '%s' for the field '%s'\n", pListFD->m_rvaLabel, pListFD->m_szName);
1494 hr = E_FAIL;
1495 continue;
1496 }
1497
1498 rva = pLabel->m_GlobalOffset;
1499 if (pLabel->m_Section == m_pTLSSection)
1500 rva += tlsSectionRVA;
1501 else if (pLabel->m_Section == m_pILSection)
1502 rva += ilSectionRVA;
1503 else {
1504 _ASSERTE(pLabel->m_Section == m_pGlobalDataSection);
1505 rva += dataSectionRVA;
1506 }
1507 }
1508 if (FAILED(m_pEmitter->SetFieldRVA(pListFD->m_fdFieldTok, rva))) goto exit;
1509 }
1510 }
1511 }
1512 if (FAILED(hr)) goto exit;
1513 }
1514
1515 if(bClock) bClock->cFilegenBegin = GetTickCount();
1516 // actually output the meta-data
1517 if (FAILED(hr=m_pCeeFileGen->EmitMetaDataAt(m_pCeeFile, m_pEmitter, m_pILSection, metaDataOffset, metaData, metaDataSize))) goto exit;
1518
1519 if((m_wMSVmajor < 0xFF)&&(m_wMSVminor < 0xFF))
1520 {
1521 STORAGESIGNATURE *pSSig = (STORAGESIGNATURE *)metaData;
1522 BYTE* pb = metaData;
1523 pb += 3*sizeof(DWORD)+2*sizeof(WORD)+VAL32(pSSig->iVersionString);
1524 pb = (BYTE*)(((size_t)pb + 3) & ~3);
1525 PSTORAGEHEADER pSHdr = (PSTORAGEHEADER)pb;
1526 PSTORAGESTREAM pStr = (PSTORAGESTREAM)(pSHdr+1);
1527 for(short iStr = 1; iStr <= VAL16(pSHdr->iStreams); iStr++)
1528 {
1529 if((strcmp(pStr->rcName,"#-")==0)||(strcmp(pStr->rcName,"#~")==0))
1530 {
1531 pb = metaData + VAL32(pStr->iOffset); // start of the stream header
1532 pb += sizeof(DWORD); // skip Reserved
1533 *pb = VAL16(m_wMSVmajor)&0xFF;
1534 *(pb+1) = VAL16(m_wMSVminor)&0xFF;
1535 break;
1536 }
1537 pb = (BYTE*)pStr;
1538 pb += 2*sizeof(DWORD)+strlen(pStr->rcName)+1;
1539 pb = (BYTE*)(((size_t)pb + 3) & ~3);
1540 pStr = (PSTORAGESTREAM)pb;
1541 }
1542 }
1543
1544 if(m_fTolerateDupMethods) // means that there are /ENC files
1545 {
1546 if(m_pbsMD) delete m_pbsMD;
1547 m_pbsMD = new BinStr();
1548 memcpy(m_pbsMD->getBuff(metaDataSize),metaData,metaDataSize);
1549 }
1550 // actually output the resources
1551 if(mresourceSize && mresourceData)
1552 {
1553 size_t i, N = m_pManifest->m_dwMResNum, sizeread, L;
1554 BYTE *ptr = (BYTE*)mresourceData;
1555 BOOL mrfail = FALSE;
1556 FILE* pFile = NULL;
1557 char sz[2048];
1558 for(i=0; i < N; i++)
1559 {
1560 m_pManifest->m_fMResNew[i] = FALSE;
1561 memset(sz,0,2048);
1562 WszWideCharToMultiByte(CP_ACP,0,m_pManifest->m_wzMResName[i],-1,sz,2047,NULL,NULL);
1563 L = m_pManifest->m_dwMResSize[i];
1564 sizeread = 0;
1565 memcpy(ptr,&L,sizeof(DWORD));
1566 ptr += sizeof(DWORD);
1567 if(fopen_s(&pFile,sz,"rb") == 0)
1568 {
1569 sizeread = fread((void *)ptr,1,L,pFile);
1570 fclose(pFile);
1571 ptr += sizeread;
1572 }
1573 else
1574 {
1575 report->msg("Error: failed to open mgd resource file '%ls'\n",m_pManifest->m_wzMResName[i]);
1576 mrfail = TRUE;
1577 }
1578 if(sizeread < L)
1579 {
1580 report->msg("Error: failed to read expected %d bytes from mgd resource file '%ls'\n",L,m_pManifest->m_wzMResName[i]);
1581 mrfail = TRUE;
1582 L -= sizeread;
1583 memset(ptr,0,L);
1584 ptr += L;
1585 }
1586 }
1587 if(mrfail)
1588 {
1589 hr = E_FAIL;
1590 goto exit;
1591 }
1592 }
1593 /*
1594 if((m_wRTVmajor < 0xFFFF)&&(m_wRTVminor < 0xFFFF))
1595 {
1596 IMAGE_COR20_HEADER* pCorH;
1597 if(FAILED(hr=m_pCeeFileGen->GetCorHeader(m_pCeeFile,&pCorH))) goto exit;
1598 pCorH->MajorRuntimeVersion = VAL16(m_wRTVmajor);
1599 pCorH->MinorRuntimeVersion = VAL16(m_wRTVminor);
1600 }
1601 */
1602 // Generate the file -- moved to main
1603 //if (FAILED(hr=m_pCeeFileGen->GenerateCeeFile(m_pCeeFile))) goto exit;
1604
1605
1606 hr = S_OK;
1607
1608exit:
1609 return hr;
1610}
1611#ifdef _PREFAST_
1612#pragma warning(pop)
1613#endif
1614