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// ZapWriter.cpp
6//
7
8//
9// Infrastructure for writing PE files. (Not NGEN specific)
10//
11// ======================================================================================
12
13#include "common.h"
14
15//---------------------------------------------------------------------------------------
16// ZapNode
17
18void * operator new(size_t size, ZapHeap * pHeap)
19{
20 return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size));
21}
22
23void * operator new[](size_t size, ZapHeap * pHeap)
24{
25 return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size));
26}
27
28//---------------------------------------------------------------------------------------
29// ZapWriter
30
31ZapWriter::ZapWriter()
32{
33}
34
35ZapWriter::~ZapWriter()
36{
37 for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++)
38 {
39 ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection];
40 pPhysicalSection->~ZapPhysicalSection();
41 }
42 delete (LoaderHeap*)m_pHeap;
43}
44
45void ZapWriter::Initialize()
46{
47 const DWORD dwReserveSize = 0x1000000;
48 const DWORD dwCommitSize = 0x10000;
49
50 m_pHeap = reinterpret_cast<ZapHeap*>(new LoaderHeap(dwReserveSize, dwCommitSize));
51
52 m_isDll = true;
53
54 // Default file alignment
55 m_FileAlignment = 0x200;
56}
57
58#if defined(FEATURE_PAL) && defined(_TARGET_64BIT_)
59#define SECTION_ALIGNMENT m_FileAlignment
60#define PAL_MAX_PAGE_SIZE 0x10000
61#else
62#define SECTION_ALIGNMENT 0x1000
63#define PAL_MAX_PAGE_SIZE 0
64#endif
65
66void ZapWriter::Save(IStream * pStream)
67{
68 INDEBUG(m_fSaving = TRUE;)
69
70 InitializeWriter(pStream);
71
72 _ASSERTE(m_Sections.GetCount() > 0);
73
74 ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1];
75
76 ULARGE_INTEGER estimatedFileSize;
77 estimatedFileSize.QuadPart = pLastPhysicalSection->m_dwFilePos + pLastPhysicalSection->m_dwSizeOfRawData;
78
79 if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenSimulateDiskFull) != 0)
80 {
81 ThrowHR(HRESULT_FROM_WIN32(ERROR_DISK_FULL));
82 }
83
84 // Set the file size upfront to reduce disk fragmentation
85 IfFailThrow(pStream->SetSize(estimatedFileSize));
86
87 LARGE_INTEGER zero;
88 zero.QuadPart = 0;
89
90 // Write the content of all sections
91 IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL));
92 SaveContent();
93 FlushWriter();
94
95 // Finally write the NT headers
96 IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL));
97 SaveHeaders();
98 FlushWriter();
99}
100
101DWORD ZapNode::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos)
102{
103 dwPos = AlignUp(dwPos, GetAlignment());
104
105 SetRVA(dwPos);
106
107 dwPos += GetSize();
108
109 return dwPos;
110}
111
112void ZapWriter::ComputeRVAs()
113{
114 DWORD dwHeaderSize = GetSizeOfNTHeaders();
115
116 DWORD dwPos = dwHeaderSize;
117 DWORD dwFilePos = dwHeaderSize;
118
119 for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++)
120 {
121 ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection];
122
123 DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment);
124 dwFilePos = dwAlignedFilePos;
125
126 pPhysicalSection->m_dwFilePos = dwFilePos;
127
128 dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE;
129 pPhysicalSection->SetRVA(dwPos);
130
131 DWORD dwEndOfRawData = dwPos;
132
133#ifdef REDHAWK
134 printf("Physical Section \"%s\" {\n", pPhysicalSection->m_pszName);
135#endif // REDHAWK
136
137 for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount(); iVirtualSection++)
138 {
139 ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection];
140
141 // Do not bother with empty virtual sections
142 if (pVirtualSection->m_Nodes.GetCount() == 0)
143 continue;
144
145 dwPos = AlignUp(dwPos, pVirtualSection->m_dwAlignment);
146 pVirtualSection->SetRVA(dwPos);
147
148 for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++)
149 {
150 ZapNode * pNode = pVirtualSection->m_Nodes[iNode];
151
152 DWORD dwNextPos = pNode->ComputeRVA(this, dwPos);
153 _ASSERTE(dwNextPos >= dwPos);
154
155 if (dwNextPos < dwPos || dwNextPos > ZAPWRITER_MAX_SIZE)
156 ThrowHR(COR_E_OVERFLOW);
157
158 dwPos = dwNextPos;
159 }
160
161 pVirtualSection->m_dwSize = dwPos - pVirtualSection->GetRVA();
162
163 if (iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections)
164 dwEndOfRawData = dwPos;
165#ifdef REDHAWK
166 if (pVirtualSection->m_dwSize > 0)
167 {
168 printf(" %08x (%6u bytes): %s\n", pVirtualSection->GetRVA(), pVirtualSection->m_dwSize, pVirtualSection->m_pszTag);
169 }
170#endif // REDHAWK
171 }
172
173 pPhysicalSection->m_dwSize = dwPos - pPhysicalSection->GetRVA();
174
175 pPhysicalSection->m_dwSizeOfRawData = dwEndOfRawData - pPhysicalSection->GetRVA();
176
177 dwFilePos += pPhysicalSection->m_dwSizeOfRawData;
178
179#ifdef REDHAWK
180 printf(" %08x: end\n", dwPos);
181 printf("}\n");
182#endif // REDHAWK
183 }
184}
185
186void ZapWriter::SaveContent()
187{
188 DWORD dwHeaderSize = GetSizeOfNTHeaders();
189
190 WritePad(dwHeaderSize);
191
192 DWORD dwPos = dwHeaderSize;
193 DWORD dwFilePos = dwHeaderSize;
194
195 for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++)
196 {
197 ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection];
198 DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment);
199 WritePad(dwAlignedFilePos - dwFilePos);
200 dwFilePos = dwAlignedFilePos;
201
202 dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE;
203
204 if (m_fWritingRelocs)
205 {
206 pPhysicalSection->m_RVA = dwPos;
207 pPhysicalSection->m_dwFilePos = dwFilePos;
208 }
209 _ASSERTE(pPhysicalSection->GetRVA() == dwPos);
210 _ASSERTE(pPhysicalSection->m_dwFilePos == dwFilePos);
211 _ASSERTE(m_dwWriterFilePos == dwFilePos);
212
213 for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections; iVirtualSection++)
214 {
215 ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection];
216
217 // Do not bother with empty virtual sections
218 if (pVirtualSection->m_Nodes.GetCount() == 0)
219 continue;
220
221 if (m_fWritingRelocs)
222 {
223 pVirtualSection->m_RVA = dwPos;
224
225 _ASSERTE(pVirtualSection->m_Nodes.GetCount() == 1);
226 pVirtualSection->m_Nodes[0]->m_RVA = dwPos;
227 }
228
229 DWORD dwVirtualSectionPos = pVirtualSection->GetRVA();
230 if (dwVirtualSectionPos != dwPos)
231 WritePad(dwVirtualSectionPos - dwPos);
232 dwPos = dwVirtualSectionPos;
233
234 for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++)
235 {
236 ZapNode * pNode = pVirtualSection->m_Nodes[iNode];
237
238 DWORD dwNodePos = pNode->GetRVA();
239 if (dwNodePos != dwPos)
240 WritePad(dwNodePos - dwPos, pVirtualSection->m_defaultFill);
241 dwPos = dwNodePos;
242
243 m_dwCurrentRVA = dwPos;
244 pNode->Save(this);
245
246#ifdef _DEBUG
247 if (dwPos + pNode->GetSize() != m_dwCurrentRVA)
248 {
249 _ASSERTE(!"Mismatch between ZapNode::GetSize() and ZapNode::Save() implementations");
250 pNode->GetSize();
251 pNode->Save(this);
252 }
253#endif
254
255 dwPos = m_dwCurrentRVA;
256 }
257
258 DWORD dwVirtualSectionSize = dwPos - pVirtualSection->GetRVA();
259 if (m_fWritingRelocs)
260 {
261 pVirtualSection->m_dwSize = dwVirtualSectionSize;
262 }
263 _ASSERTE(pVirtualSection->m_dwSize == dwVirtualSectionSize);
264 }
265
266 DWORD dwPhysicalSectionSize = dwPos - pPhysicalSection->GetRVA();
267 if (m_fWritingRelocs)
268 {
269 pPhysicalSection->m_dwSize = dwPhysicalSectionSize;
270 pPhysicalSection->m_dwSizeOfRawData = dwPhysicalSectionSize;
271 }
272 _ASSERTE(pPhysicalSection->m_dwSizeOfRawData == dwPhysicalSectionSize);
273
274 dwPos = pPhysicalSection->GetRVA() + pPhysicalSection->m_dwSize;
275
276 dwFilePos += pPhysicalSection->m_dwSizeOfRawData;
277 }
278
279 WritePad(AlignmentPad(dwFilePos, m_FileAlignment));
280}
281
282//---------------------------------------------------------------------------------------
283//
284// ZapVirtualSection
285//
286#ifdef REDHAWK
287UINT32 ZapVirtualSection::FillInNodeOffsetMap(MapSHash<ZapNode *, UINT32> * pMap)
288{
289 UINT32 dataSize = 0;
290 for (int i = 0; i < m_Nodes.GetCount(); i++)
291 {
292 ZapNode* pNode = m_Nodes[i];
293 pMap->Add(pNode, dataSize);
294 dataSize += pNode->GetSize();
295 }
296
297 return dataSize;
298}
299#endif // REDHAWK
300
301//---------------------------------------------------------------------------------------
302// Simple buffered writer
303
304#define WRITE_BUFFER_SIZE 0x10000
305
306void ZapWriter::InitializeWriter(IStream * pStream)
307{
308 m_pBuffer = new (GetHeap()) BYTE[WRITE_BUFFER_SIZE];
309 m_nBufferPos = 0;
310
311 m_pStream = pStream;
312
313 INDEBUG(m_dwWriterFilePos = 0;)
314}
315
316void ZapWriter::FlushWriter()
317{
318 if (m_nBufferPos > 0)
319 {
320 ULONG cbWritten;
321 IfFailThrow(m_pStream->Write(m_pBuffer, m_nBufferPos, &cbWritten));
322 _ASSERTE(cbWritten == m_nBufferPos);
323
324 m_nBufferPos = 0;
325 }
326}
327
328void ZapWriter::Write(PVOID p, DWORD dwSize)
329{
330 m_dwCurrentRVA += dwSize;
331 INDEBUG(m_dwWriterFilePos += dwSize;)
332
333 if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE)
334 ThrowHR(COR_E_OVERFLOW);
335
336 DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos);
337
338 memcpy(m_pBuffer + m_nBufferPos, p, cbAvailable);
339 p = (PBYTE)p + cbAvailable;
340 dwSize -= cbAvailable;
341
342 m_nBufferPos += cbAvailable;
343
344 if (m_nBufferPos < WRITE_BUFFER_SIZE)
345 return;
346
347 FlushWriter();
348
349 if (dwSize == 0)
350 return;
351
352 cbAvailable = AlignDown(dwSize, WRITE_BUFFER_SIZE);
353
354 if (cbAvailable > 0)
355 {
356 ULONG cbWritten;
357 IfFailThrow(m_pStream->Write(p, cbAvailable, &cbWritten));
358 _ASSERTE(cbWritten == cbAvailable);
359
360 p = (PBYTE)p + cbAvailable;
361 dwSize -= cbAvailable;
362 }
363
364 _ASSERTE(m_nBufferPos == 0);
365 memcpy(m_pBuffer, p, dwSize);
366 m_nBufferPos = dwSize;
367}
368
369void ZapWriter::WritePad(DWORD dwSize, BYTE fill)
370{
371 m_dwCurrentRVA += dwSize;
372 INDEBUG(m_dwWriterFilePos += dwSize;)
373
374 if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE)
375 ThrowHR(COR_E_OVERFLOW);
376
377 DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos);
378
379 memset(m_pBuffer + m_nBufferPos, fill, cbAvailable);
380 dwSize -= cbAvailable;
381
382 m_nBufferPos += cbAvailable;
383
384 if (m_nBufferPos < WRITE_BUFFER_SIZE)
385 return;
386
387 FlushWriter();
388
389 if (dwSize == 0)
390 return;
391
392 memset(m_pBuffer, fill, min(WRITE_BUFFER_SIZE, dwSize));
393
394 while (dwSize >= WRITE_BUFFER_SIZE)
395 {
396 ULONG cbWritten;
397 cbAvailable = min(WRITE_BUFFER_SIZE, dwSize);
398 IfFailThrow(m_pStream->Write(m_pBuffer, cbAvailable, &cbWritten));
399 _ASSERTE(cbWritten == cbAvailable);
400
401 dwSize -= cbAvailable;
402 }
403
404 m_nBufferPos = dwSize;
405}
406
407STDMETHODIMP ZapWriter::Write(void const *pv, ULONG cb, ULONG *pcbWritten)
408{
409 HRESULT hr = S_OK;
410
411 EX_TRY
412 {
413 Write((PVOID)pv, cb);
414
415 if (pcbWritten != 0)
416 *pcbWritten = cb;
417 }
418 EX_CATCH_HRESULT(hr)
419
420 return hr;
421}
422
423//---------------------------------------------------------------------------------------
424// NT Headers
425
426void ZapWriter::SaveHeaders()
427{
428 SaveDosHeader();
429 SaveSignature();
430 SaveFileHeader();
431 SaveOptionalHeader();
432 SaveSections();
433}
434
435void ZapWriter::SaveDosHeader()
436{
437 IMAGE_DOS_HEADER header;
438
439 ZeroMemory(&header, sizeof(header));
440
441 header.e_magic = VAL16(IMAGE_DOS_SIGNATURE);
442 header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER));
443
444 // Legacy tools depend on e_lfarlc to be 0x40
445 header.e_lfarlc = VAL16(0x40);
446
447 // We put the PE Signature at 0x80 so that we are the same offset for IL Images
448
449 header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER) + 0x40);
450 Write(&header, sizeof(header));
451
452 // Write out padding to get to offset 0x80
453 WritePad(0x40);
454}
455
456void ZapWriter::SaveSignature()
457{
458 ULONG Signature = VAL32(IMAGE_NT_SIGNATURE);
459 Write(&Signature, sizeof(Signature));
460}
461
462void ZapWriter::SaveFileHeader()
463{
464 IMAGE_FILE_HEADER fileHeader;
465 ZeroMemory(&fileHeader, sizeof(fileHeader));
466
467 fileHeader.Machine = VAL16(GetMachine());
468 fileHeader.TimeDateStamp = VAL32(m_dwTimeDateStamp);
469 fileHeader.SizeOfOptionalHeader = Is64Bit() ? VAL16(sizeof(IMAGE_OPTIONAL_HEADER64)) : VAL16(sizeof(IMAGE_OPTIONAL_HEADER32));
470
471 // Count the number of non-empty physical sections
472 int nSections = 0;
473 for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++)
474 {
475 if (m_Sections[iPhysicalSection]->m_dwSize != 0)
476 nSections++;
477 }
478 fileHeader.NumberOfSections = VAL16(nSections);
479
480 fileHeader.Characteristics = VAL16(IMAGE_FILE_EXECUTABLE_IMAGE |
481 (Is64Bit() ? 0 : IMAGE_FILE_32BIT_MACHINE) |
482 (m_isDll ? IMAGE_FILE_DLL : 0) |
483 (Is64Bit() ? IMAGE_FILE_LARGE_ADDRESS_AWARE : 0) );
484
485 Write(&fileHeader, sizeof(fileHeader));
486}
487
488void ZapWriter::SaveOptionalHeader()
489{
490 // Write the correct flavor of the optional header
491 union
492 {
493 IMAGE_OPTIONAL_HEADER32 header32;
494 IMAGE_OPTIONAL_HEADER64 header64;
495 }
496 optionalHeader;
497
498 ZeroMemory(&optionalHeader, sizeof(optionalHeader));
499
500 PIMAGE_OPTIONAL_HEADER pHeader = (PIMAGE_OPTIONAL_HEADER)&optionalHeader;
501
502 // Common fields between 32-bit and 64-bit
503
504 // Linker version should be consistent with current VC level
505 pHeader->MajorLinkerVersion = 11;
506
507 pHeader->SectionAlignment = VAL32(SECTION_ALIGNMENT);
508 pHeader->FileAlignment = VAL32(m_FileAlignment);
509
510 // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images
511 pHeader->MajorOperatingSystemVersion = VAL16(5);
512 pHeader->MinorOperatingSystemVersion = Is64Bit() ? VAL16(2) : VAL16(0);
513
514 pHeader->MajorSubsystemVersion = pHeader->MajorOperatingSystemVersion;
515 pHeader->MinorSubsystemVersion = pHeader->MinorOperatingSystemVersion;
516
517#ifdef REDHAWK
518 pHeader->AddressOfEntryPoint = m_entryPointRVA;
519#endif
520
521 ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1];
522 pHeader->SizeOfImage = VAL32(AlignUp(pLastPhysicalSection->GetRVA() + pLastPhysicalSection->m_dwSize, SECTION_ALIGNMENT));
523
524 pHeader->SizeOfHeaders = VAL32(AlignUp(GetSizeOfNTHeaders(), m_FileAlignment));
525
526 pHeader->Subsystem = VAL16(m_Subsystem);
527 pHeader->DllCharacteristics = VAL16(m_DllCharacteristics);
528
529
530 // Different fields between 32-bit and 64-bit
531
532 PIMAGE_DATA_DIRECTORY pDataDirectory;
533
534 if (Is64Bit())
535 {
536 PIMAGE_OPTIONAL_HEADER64 pHeader64 = (PIMAGE_OPTIONAL_HEADER64)pHeader;
537
538 pHeader64->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC);
539
540 pHeader64->ImageBase = VAL64(m_BaseAddress);
541 pHeader64->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
542
543 pHeader64->SizeOfStackReserve = VAL64(m_SizeOfStackReserve);
544 pHeader64->SizeOfStackCommit = VAL64(m_SizeOfStackCommit);
545
546 pDataDirectory = pHeader64->DataDirectory;
547 }
548 else
549 {
550 PIMAGE_OPTIONAL_HEADER32 pHeader32 = (PIMAGE_OPTIONAL_HEADER32)pHeader;
551
552 pHeader32->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC);
553
554 pHeader32->ImageBase = VAL32((ULONG)m_BaseAddress);
555 pHeader32->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
556
557 pHeader32->SizeOfStackReserve = VAL32((ULONG)m_SizeOfStackReserve);
558 pHeader32->SizeOfStackCommit = VAL32((ULONG)m_SizeOfStackCommit);
559
560 pDataDirectory = pHeader32->DataDirectory;
561 }
562
563 for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
564 {
565 SetDirectoryData(&pDataDirectory[i], m_DirectoryEntries[i]);
566 }
567
568 Write(&optionalHeader, Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32));
569}
570
571void ZapWriter::SaveSections()
572{
573 for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++)
574 {
575 ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection];
576
577 // Do not save empty sections
578 if (pPhysicalSection->m_dwSize == 0)
579 continue;
580
581 IMAGE_SECTION_HEADER header;
582 ZeroMemory(&header, sizeof(header));
583
584 SIZE_T cbName = strlen(pPhysicalSection->m_pszName);
585 _ASSERTE(cbName <= sizeof(header.Name));
586 memcpy(header.Name, pPhysicalSection->m_pszName, min(sizeof(header.Name), cbName));
587
588 header.Misc.VirtualSize = VAL32(pPhysicalSection->m_dwSize);
589 header.VirtualAddress = VAL32(pPhysicalSection->GetRVA());
590
591 header.SizeOfRawData = VAL32(AlignUp(pPhysicalSection->m_dwSizeOfRawData, m_FileAlignment));
592
593 if (header.SizeOfRawData != 0)
594 header.PointerToRawData = VAL32(pPhysicalSection->m_dwFilePos);
595
596 header.Characteristics = VAL32(pPhysicalSection->m_dwCharacteristics);
597
598 Write(&header, sizeof(header));
599 }
600}
601
602DWORD ZapWriter::GetSizeOfNTHeaders()
603{
604 return sizeof(IMAGE_DOS_HEADER) + 0x40 + /* Padding for DOS Header */
605 sizeof(ULONG) +
606 sizeof(IMAGE_FILE_HEADER) +
607 (Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32)) +
608 (m_Sections.GetCount() * sizeof(IMAGE_SECTION_HEADER));
609}
610
611void ZapWriter::SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode)
612{
613 DWORD size = (pZapNode != NULL) ? pZapNode->GetSize() : 0;
614
615 if (size != 0)
616 {
617 pDir->VirtualAddress = pZapNode->GetRVA();
618 pDir->Size = size;
619 }
620 else
621 {
622 pDir->VirtualAddress = 0;
623 pDir->Size = 0;
624 }
625}
626
627//---------------------------------------------------------------------------------------
628// ZapBlob
629
630ZapBlob * ZapBlob::NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize)
631{
632 S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapBlob)) + S_SIZE_T(cbSize);
633 if(cbAllocSize.IsOverflow())
634 ThrowHR(COR_E_OVERFLOW);
635
636 void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
637
638 ZapBlob * pZapBlob = new (pMemory) ZapBlob(cbSize);
639
640 if (pData != NULL)
641 memcpy((void*)(pZapBlob + 1), pData, cbSize);
642
643 return pZapBlob;
644}
645
646template <UINT alignment>
647class ZapAlignedBlobConst : public ZapBlob
648{
649protected:
650 ZapAlignedBlobConst(SIZE_T cbSize)
651 : ZapBlob(cbSize)
652 {
653 }
654
655public:
656 virtual UINT GetAlignment()
657 {
658 return alignment;
659 }
660
661 static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize)
662 {
663 S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapAlignedBlobConst<alignment>)) + S_SIZE_T(cbSize);
664 if(cbAllocSize.IsOverflow())
665 ThrowHR(COR_E_OVERFLOW);
666
667 void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
668
669 ZapAlignedBlobConst<alignment> * pZapBlob = new (pMemory) ZapAlignedBlobConst<alignment>(cbSize);
670
671 if (pData != NULL)
672 memcpy((void *)(pZapBlob + 1), pData, cbSize);
673
674 return pZapBlob;
675 }
676};
677
678ZapBlob * ZapBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment)
679{
680 switch (cbAlignment)
681 {
682 case 4:
683 return ZapAlignedBlobConst<4>::NewBlob(pWriter, pData, cbSize);
684 case 8:
685 return ZapAlignedBlobConst<8>::NewBlob(pWriter, pData, cbSize);
686 case 16:
687 return ZapAlignedBlobConst<16>::NewBlob(pWriter, pData, cbSize);
688
689 default:
690 _ASSERTE(!"Requested alignment not supported");
691 return NULL;
692 }
693}
694
695void ZapBlob::Save(ZapWriter * pZapWriter)
696{
697 pZapWriter->Write(GetData(), GetSize());
698}
699