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.
9 // Infrastructure for writing PE files. (Not NGEN specific)
11 // ======================================================================================
15 #ifndef __ZAPWRITER_H__
16 #define __ZAPWRITER_H__
18 #include "zapnodetype.h"
23 // This is maximum size of anything in the image written by ZapWriter. Used for overflow checking.
24 #define ZAPWRITER_MAX_SIZE 0x3FFFFFFF
26 // All ZapNodes should be allocated from ZapHeap returned by ZapWriter::GetHeap()
27 void *operator new(size_t size, ZapHeap * pZapHeap);
28 void *operator new[](size_t size, ZapHeap * pZapHeap);
31 // ZapHeap does not support deallocation. Empty operators delete avoids deallocating memory
32 // if the constructor fails
34 inline void operator delete(void *, ZapHeap * pZapHeap)
36 // Memory allocated by ZapHeap is never freed
38 inline void operator delete[](void *, ZapHeap * pZapHeap)
40 // Memory allocated by ZapHeap is never freed
44 //------------------------------------------------------------------------------------------------------
45 // ZapNode is the basic building block of the native image. Every ZapNode must know how to persist itself.
47 // The basic contract for a ZapNode is that it understands its allocations requirements (size and alignment),
48 // and knows how to save itself (given a ZapWriter). At some point a ZapNode is given a location in the
49 // executable (an RVA), which it is responsible remembering.
51 // See file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for an overview.
55 friend class ZapWriter;
60 void SetRVA(DWORD dwRVA)
62 _ASSERTE(m_RVA == 0 || m_RVA == (DWORD)-1);
68 // All ZapNodes are expected to be allocate from ZapWriter::GetHeap() that returns zero filled memory
72 // This constructor should be used to allocate temporary ZapNodes on the stack only
82 // Returns the size of the node in the image. All nodes that are written into the image should override this method.
83 virtual DWORD GetSize()
85 #if defined(_MSC_VER) //UNREACHABLE doesn't work in GCC, when the method has a non-void return
88 _ASSERTE(!"Unreachable");
93 // Alignment for this node.
94 virtual UINT GetAlignment()
99 // Returns the type of the ZapNode. All nodes should override this method.
100 virtual ZapNodeType GetType()
102 return ZapNodeType_Unknown;
105 // Assign RVA to this node. dwPos is current RVA, returns updated current RVA.
106 virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos);
108 // All nodes that are written into the image should override this method. The implementation should write exactly GetSize() bytes
109 // using ZapWriter::Write method
110 virtual void Save(ZapWriter * pZapWriter)
115 // Returns the RVA of the node. Valid only after ComputeRVA phase
118 _ASSERTE(m_RVA != 0 && m_RVA != (DWORD)-1);
122 // Returns whether the node was placed into a virtual section
129 //---------------------------------------------------------------------------------------
130 // Virtual section of PE image.
131 class ZapVirtualSection : public ZapNode
133 friend class ZapWriter;
137 SArray<ZapNode *> m_Nodes;
139 // State initialized once the section is placed
142 DWORD m_dwSectionType;
146 ZapVirtualSection(DWORD dwAlignment)
147 : m_dwAlignment(dwAlignment)
152 virtual DWORD GetSize()
157 virtual ZapNodeType GetType()
159 return ZapNodeType_VirtualSection;
162 DWORD GetSectionType()
164 return m_dwSectionType;
167 void SetSectionType(DWORD dwSectionType)
169 _ASSERTE((dwSectionType & IBCTypeReservedFlag) != 0 || !"IBCType flag is not specified");
170 _ASSERTE((dwSectionType & RangeTypeReservedFlag) != 0 || !"RangeType flag is not specified");
171 _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) != 0 || !"VirtualSectionType flag is not specified");
172 _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) < CORCOMPILE_SECTION_TYPE_COUNT || !"Invalid VirtualSectionType flag");
173 m_dwSectionType = dwSectionType;
176 void SetDefaultFill(BYTE fill)
178 m_defaultFill = fill;
181 void Place(ZapNode * pNode)
183 _ASSERTE(!pNode->IsPlaced());
184 m_Nodes.Append(pNode);
185 pNode->SetRVA((DWORD)-1);
188 COUNT_T GetNodeCount()
190 return m_Nodes.GetCount();
193 ZapNode * GetNode(COUNT_T iNode)
195 return m_Nodes[iNode];
199 //---------------------------------------------------------------------------------------
200 // The named physical section of the PE Image. It contains one or more virtual sections.
201 class ZapPhysicalSection : public ZapNode
203 friend class ZapWriter;
205 SArray<ZapVirtualSection *> m_Sections;
208 DWORD m_dwCharacteristics;
210 // Number of zero filled sections (zero filled sections are always last in m_Sections array)
211 COUNT_T m_nBssSections;
213 // State initialized once the section is placed
216 DWORD m_dwSizeOfRawData;
218 ZapPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics)
219 : m_pszName(pszName),
220 m_dwCharacteristics(dwCharacteristics)
225 ~ZapPhysicalSection()
227 for (COUNT_T iVirtualSection = 0; iVirtualSection < m_Sections.GetCount(); iVirtualSection++)
229 ZapVirtualSection * pVirtualSection = m_Sections[iVirtualSection];
230 pVirtualSection->~ZapVirtualSection();
234 virtual DWORD GetSize()
239 virtual ZapNodeType GetType()
241 return ZapNodeType_PhysicalSection;
246 _ASSERTE(m_dwFilePos != 0);
250 COUNT_T GetVirtualSectionCount()
252 return m_Sections.GetCount();
255 ZapVirtualSection * GetVirtualSection(COUNT_T iSection)
257 return m_Sections[iSection];
262 //---------------------------------------------------------------------------------------
266 // Notice that ZapWriter implements IStream that can be passed to APIs that write to stream
268 // The main API in a ZapWriter is (not suprisingly) the code:ZapWriter.Write method.
270 // Relocations are handled by a higher level object, code:ZapImage, which knows about all the sections of a
271 // ngen image and how to do relections. Every ZapWriter has an associated ZapImage which you get to by
272 // calling code:ZapImage.GetImage.
274 class ZapWriter : public IStream
278 SArray<ZapPhysicalSection *> m_Sections;
280 ZapNode * m_DirectoryEntries[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
281 DWORD m_dwTimeDateStamp;
282 ULONGLONG m_BaseAddress;
283 ULONGLONG m_SizeOfStackReserve;
284 ULONGLONG m_SizeOfStackCommit;
286 USHORT m_DllCharacteristics;
288 DWORD m_FileAlignment;
290 // Current state of the writer for debug checks
291 INDEBUG(BOOL m_fSaving;)
293 DWORD m_dwCurrentRVA;
294 BOOL m_fWritingRelocs; // Set to true once we start reloc sections at the end of the file
298 DWORD GetSizeOfNTHeaders();
301 // Simple buffered writer
302 void InitializeWriter(IStream * pStream);
307 INDEBUG(DWORD m_dwWriterFilePos;)
315 #ifdef _TARGET_64BIT_
317 #else // !_TARGET_64BIT_
319 #endif // !_TARGET_64BIT_
324 return IMAGE_FILE_MACHINE_NATIVE_NI;
327 void SaveDosHeader();
328 void SaveSignature();
329 void SaveFileHeader();
330 void SaveOptionalHeader();
333 // IStream support - the only actually implemented method is IStream::Write
336 STDMETHODIMP_(ULONG) AddRef()
341 STDMETHODIMP_(ULONG) Release()
346 STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)
349 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) {
350 *ppv = static_cast<IStream *>(this);
359 // ISequentialStream methods:
360 STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead)
366 STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten);
369 STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
371 // IMetaDataEmit::SaveToStream calls Seek(0) but ignores the returned error
376 STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize)
382 STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
388 STDMETHODIMP Commit(DWORD grfCommitFlags)
394 STDMETHODIMP Revert()
400 STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
406 STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
412 STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag)
418 STDMETHODIMP Clone(IStream **ppIStream)
430 // Create new section in the PE file. The sections will be saved in the order they are created.
431 ZapPhysicalSection * NewPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics)
433 _ASSERTE(!IsSaving());
434 ZapPhysicalSection * pSection = new (GetHeap()) ZapPhysicalSection(pszName, dwCharacteristics);
435 m_Sections.Append(pSection);
439 // Create new virtual section within the physical section. The sections will be saved in the order they are created.
440 // The default virtual section alignment is 16.
441 ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL)
443 _ASSERTE(!IsSaving());
444 ZapVirtualSection * pSection = new (GetHeap()) ZapVirtualSection(dwAlignment);
445 if (pInsertAfter != NULL)
447 // pInsertAfter is workaround to get decent layout with the current scheme of virtual sections. It should not be necessary
448 // once we have better layout algorithms in place.
449 for (COUNT_T iSection = 0; iSection < pPhysicalSection->m_Sections.GetCount(); iSection++)
451 if (pPhysicalSection->m_Sections[iSection] == pInsertAfter)
453 pPhysicalSection->m_Sections.Insert(pPhysicalSection->m_Sections+(iSection+1));
454 pPhysicalSection->m_Sections[iSection+1] = pSection;
461 pPhysicalSection->m_Sections.Append(pSection);
465 void MarkBssSection(ZapPhysicalSection * pPhysicalSection, ZapVirtualSection * pSection)
467 _ASSERTE(!IsSaving());
468 _ASSERTE(pPhysicalSection->m_Sections[pPhysicalSection->m_Sections.GetCount() - 1] == pSection);
469 pPhysicalSection->m_nBssSections++;
472 void Append(ZapVirtualSection * pVirtualSection, ZapNode * pNode)
474 _ASSERTE(!IsSaving());
475 pVirtualSection->m_Nodes.Append(pNode);
478 // Set the directory entry in the image to match the given ZapNode
479 void SetDirectoryEntry(DWORD entry, ZapNode * pNode)
481 _ASSERTE(!IsSaving());
482 _ASSERTE(entry < IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
483 _ASSERTE(m_DirectoryEntries[entry] == NULL);
484 m_DirectoryEntries[entry] = pNode;
487 // Set the timedate stamp of the image
488 void SetTimeDateStamp(DWORD dwTimeDateStamp)
490 _ASSERTE(!IsSaving());
491 m_dwTimeDateStamp = dwTimeDateStamp;
494 // Set the base address of the image
495 void SetBaseAddress(ULONGLONG baseAddress)
497 _ASSERTE(!IsSaving());
498 m_BaseAddress = baseAddress;
501 ULONGLONG GetBaseAddress()
503 _ASSERTE(m_BaseAddress != 0);
504 return m_BaseAddress;
507 void SetSizeOfStackReserve(ULONGLONG sizeOfStackReserve)
509 _ASSERTE(!IsSaving());
510 m_SizeOfStackReserve = sizeOfStackReserve;
513 void SetSizeOfStackCommit(ULONGLONG sizeOfStackCommit)
515 _ASSERTE(!IsSaving());
516 m_SizeOfStackCommit = sizeOfStackCommit;
519 void SetSubsystem(USHORT subsystem)
521 _ASSERTE(!IsSaving());
522 m_Subsystem = subsystem;
525 void SetDllCharacteristics(USHORT dllCharacteristics)
527 _ASSERTE(!IsSaving());
528 m_DllCharacteristics = dllCharacteristics;
531 void SetIsDll(BOOL isDLL)
536 void SetFileAlignment(DWORD fileAlignment)
538 m_FileAlignment = fileAlignment;
541 // Compute RVAs for everything in the file
544 // Save the content into stream
545 void Save(IStream * pStream);
547 // Get the heap. The lifetime of this heap is same as the lifetime of the ZapWriter. All ZapNodes should
548 // be allocated from this heap.
554 COUNT_T GetPhysicalSectionCount()
556 return m_Sections.GetCount();
559 ZapPhysicalSection * GetPhysicalSection(COUNT_T iSection)
561 return m_Sections[iSection];
565 // Certain methods can be called only during the save phase
572 DWORD GetCurrentRVA()
574 _ASSERTE(IsSaving());
575 return m_dwCurrentRVA;
579 // This is the main entrypoint used to write the image. Every implementation of ZapNode::Save will call this method.
580 void Write(PVOID p, DWORD dwSize);
583 void WritePad(DWORD size, BYTE fill = 0);
585 // Flush any buffered data
588 BOOL IsWritingRelocs()
590 return m_fWritingRelocs;
593 void SetWritingRelocs()
595 m_fWritingRelocs = TRUE;
598 // Convenience helper to initialize IMAGE_DATA_DIRECTORY
599 static void SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode);
602 //---------------------------------------------------------------------------------------
605 // Generic node for unstructured sequence of bytes.
606 // Includes SHash support (ZapBlob::SHashTraits)
608 class ZapBlob : public ZapNode
613 ZapBlob(SIZE_T cbSize)
614 : m_cbSize((DWORD)cbSize)
616 if (cbSize > ZAPWRITER_MAX_SIZE)
617 ThrowHR(COR_E_OVERFLOW);
627 SHashKey(PVOID pData, SIZE_T cbSize)
628 : m_pData((PBYTE)pData), m_cbSize(cbSize)
632 PBYTE GetData() const
637 SIZE_T GetBlobSize() const
643 class SHashTraits : public DefaultSHashTraits<ZapBlob *>
646 typedef const ZapBlob::SHashKey key_t;
648 static key_t GetKey(element_t e)
650 LIMITED_METHOD_CONTRACT;
651 return key_t(e->GetData(), e->GetBlobSize());
653 static BOOL Equals(key_t k1, key_t k2)
655 LIMITED_METHOD_CONTRACT;
656 if (k1.GetBlobSize() != k2.GetBlobSize())
658 return memcmp(k1.GetData(), k2.GetData(), k1.GetBlobSize()) == 0;
660 static count_t Hash(key_t k)
662 LIMITED_METHOD_CONTRACT;
663 count_t hash = 5381 + (count_t)(k.GetBlobSize() << 7);
665 PBYTE pbData = k.GetData();
666 PBYTE pbDataEnd = pbData + k.GetBlobSize();
668 for (/**/ ; pbData < pbDataEnd; pbData++)
670 hash = ((hash << 5) + hash) ^ *pbData;
676 virtual PBYTE GetData()
678 return (PBYTE)(this + 1);
681 // Used to shrink the size of the blob
682 void AdjustBlobSize(SIZE_T cbSize)
684 _ASSERTE(cbSize <= m_cbSize);
685 _ASSERTE(cbSize != 0);
686 m_cbSize = (DWORD)cbSize;
689 // Raw size of the blob
695 virtual DWORD GetSize()
700 virtual ZapNodeType GetType()
702 return ZapNodeType_Blob;
705 virtual void Save(ZapWriter * pZapWriter);
707 // Create new zap blob node. The node *does* own copy of the memory.
708 static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize);
710 // Create new aligned zap blob node.
711 static ZapBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment);
714 class ZapBlobPtr : public ZapBlob
719 ZapBlobPtr(PVOID pData, SIZE_T cbSize)
720 : ZapBlob(cbSize), m_pData((PBYTE)pData)
724 virtual PBYTE GetData()
730 class ZapDummyNode : public ZapNode
735 ZapDummyNode(DWORD cbSize)
740 virtual DWORD GetSize()
746 #endif // __ZAPWRITER_H__