JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / zap / zapwriter.h
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.h
6 //
7
8 //
9 // Infrastructure for writing PE files. (Not NGEN specific)
10 //
11 // ======================================================================================
12
13
14
15 #ifndef __ZAPWRITER_H__
16 #define __ZAPWRITER_H__
17
18 #include "zapnodetype.h"
19
20 class ZapWriter;
21 class ZapHeap;
22
23 // This is maximum size of anything in the image written by ZapWriter. Used for overflow checking.
24 #define ZAPWRITER_MAX_SIZE 0x3FFFFFFF
25
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);
29
30 //
31 // ZapHeap does not support deallocation. Empty operators delete avoids deallocating memory
32 // if the constructor fails
33 //
34 inline void operator delete(void *, ZapHeap * pZapHeap)
35 {
36     // Memory allocated by ZapHeap is never freed
37 }
38 inline void operator delete[](void *, ZapHeap * pZapHeap)
39 {
40     // Memory allocated by ZapHeap is never freed
41 }
42
43
44 //------------------------------------------------------------------------------------------------------
45 // ZapNode is the basic building block of the native image. Every ZapNode must know how to persist itself.
46 //
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.
50 //
51 // See file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for an overview.
52 //
53 class ZapNode
54 {
55     friend class ZapWriter;
56
57     DWORD m_RVA;
58
59 public:
60     void SetRVA(DWORD dwRVA)
61     {
62         _ASSERTE(m_RVA == 0 || m_RVA == (DWORD)-1);
63         m_RVA = dwRVA;
64     }
65
66     ZapNode()
67     {
68         // All ZapNodes are expected to be allocate from ZapWriter::GetHeap() that returns zero filled memory
69         _ASSERTE(m_RVA == 0);
70     }
71
72     // This constructor should be used to allocate temporary ZapNodes on the stack only
73     ZapNode(DWORD rva)
74         : m_RVA(rva)
75     {
76     }
77
78     virtual ~ZapNode()
79     {
80     }
81
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()
84     {
85 #if defined(_MSC_VER) //UNREACHABLE doesn't work in GCC, when the method has a non-void return
86         UNREACHABLE();
87 #else
88         _ASSERTE(!"Unreachable");
89         return 0;
90 #endif
91     }
92
93     // Alignment for this node.
94     virtual UINT GetAlignment()
95     {
96         return 1;
97     }
98
99     // Returns the type of the ZapNode. All nodes should override this method.
100     virtual ZapNodeType GetType()
101     {
102         return ZapNodeType_Unknown;
103     }
104
105     // Assign RVA to this node. dwPos is current RVA, returns updated current RVA.
106     virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos);
107
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)
111     {
112         UNREACHABLE();
113     }
114
115     // Returns the RVA of the node. Valid only after ComputeRVA phase
116     DWORD GetRVA()
117     {
118         _ASSERTE(m_RVA != 0 && m_RVA != (DWORD)-1);
119         return m_RVA;
120     }
121
122     // Returns whether the node was placed into a virtual section
123     BOOL IsPlaced()
124     {
125         return m_RVA != 0;
126     }
127 };
128
129 //---------------------------------------------------------------------------------------
130 // Virtual section of PE image.
131 class ZapVirtualSection : public ZapNode
132 {
133     friend class ZapWriter;
134
135     DWORD m_dwAlignment;
136
137     SArray<ZapNode *> m_Nodes;
138
139     // State initialized once the section is placed
140     DWORD m_dwSize;
141
142     DWORD m_dwSectionType;
143
144     BYTE m_defaultFill;
145
146     ZapVirtualSection(DWORD dwAlignment)
147         : m_dwAlignment(dwAlignment)
148     {
149     }
150
151 public:
152     virtual DWORD GetSize()
153     {
154         return m_dwSize;
155     }
156
157     virtual ZapNodeType GetType()
158     {
159         return ZapNodeType_VirtualSection;
160     }
161
162     DWORD GetSectionType()
163     {
164         return m_dwSectionType;
165     }
166
167     void SetSectionType(DWORD dwSectionType)
168     {
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;
174     }
175
176     void SetDefaultFill(BYTE fill)
177     {
178         m_defaultFill = fill;
179     }
180
181     void Place(ZapNode * pNode)
182     {
183         _ASSERTE(!pNode->IsPlaced());
184         m_Nodes.Append(pNode);
185         pNode->SetRVA((DWORD)-1);
186     }
187
188     COUNT_T GetNodeCount()
189     {
190         return m_Nodes.GetCount();
191     }
192
193     ZapNode * GetNode(COUNT_T iNode)
194     {
195         return m_Nodes[iNode];
196     }
197 };
198
199 //---------------------------------------------------------------------------------------
200 // The named physical section of the PE Image. It contains one or more virtual sections.
201 class ZapPhysicalSection : public ZapNode
202 {
203     friend class ZapWriter;
204
205     SArray<ZapVirtualSection *> m_Sections;
206
207     LPCSTR m_pszName;
208     DWORD m_dwCharacteristics;
209
210     // Number of zero filled sections (zero filled sections are always last in m_Sections array)
211     COUNT_T m_nBssSections;
212
213     // State initialized once the section is placed
214     DWORD m_dwSize;
215     DWORD m_dwFilePos;
216     DWORD m_dwSizeOfRawData;
217
218     ZapPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics)
219         : m_pszName(pszName),
220           m_dwCharacteristics(dwCharacteristics)
221     {
222     }
223
224 public:
225     ~ZapPhysicalSection()
226     {
227         for (COUNT_T iVirtualSection = 0; iVirtualSection < m_Sections.GetCount(); iVirtualSection++)
228         {
229             ZapVirtualSection * pVirtualSection = m_Sections[iVirtualSection];
230             pVirtualSection->~ZapVirtualSection();
231         }
232     }
233
234     virtual DWORD GetSize()
235     {
236         return m_dwSize;
237     }
238
239     virtual ZapNodeType GetType()
240     {
241         return ZapNodeType_PhysicalSection;
242     }
243
244     DWORD GetFilePos()
245     {
246         _ASSERTE(m_dwFilePos != 0);
247         return m_dwFilePos;
248     }
249
250     COUNT_T GetVirtualSectionCount()
251     {
252         return m_Sections.GetCount();
253     }
254
255     ZapVirtualSection * GetVirtualSection(COUNT_T iSection)
256     {
257         return m_Sections[iSection];
258     }
259
260 };
261
262 //---------------------------------------------------------------------------------------
263 //
264 // The ZapWriter
265 //
266 // Notice that ZapWriter implements IStream that can be passed to APIs that write to stream
267 //
268 // The main API in a ZapWriter is (not suprisingly) the code:ZapWriter.Write method.
269 //
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.
273 //
274 class ZapWriter : public IStream
275 {
276     ZapHeap * m_pHeap;
277
278     SArray<ZapPhysicalSection *> m_Sections;
279
280     ZapNode * m_DirectoryEntries[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
281     DWORD     m_dwTimeDateStamp;
282     ULONGLONG m_BaseAddress;
283     ULONGLONG m_SizeOfStackReserve;
284     ULONGLONG m_SizeOfStackCommit;
285     USHORT    m_Subsystem;
286     USHORT    m_DllCharacteristics;
287     BOOL      m_isDll;
288     DWORD     m_FileAlignment;
289
290     // Current state of the writer for debug checks
291     INDEBUG(BOOL m_fSaving;)
292
293     DWORD m_dwCurrentRVA;
294     BOOL m_fWritingRelocs; // Set to true once we start reloc sections at the end of the file
295
296     void SaveContent();
297
298     DWORD GetSizeOfNTHeaders();
299     void SaveHeaders();
300
301     // Simple buffered writer
302     void InitializeWriter(IStream * pStream);
303
304     IStream * m_pStream;
305     PBYTE m_pBuffer;
306     ULONG m_nBufferPos;
307     INDEBUG(DWORD m_dwWriterFilePos;)
308
309     //
310     // NT Headers
311     //
312
313     BOOL Is64Bit()
314     {
315 #ifdef _TARGET_64BIT_
316         return TRUE;
317 #else // !_TARGET_64BIT_
318         return FALSE;
319 #endif // !_TARGET_64BIT_
320     }
321
322     USHORT GetMachine()
323     {
324         return IMAGE_FILE_MACHINE_NATIVE_NI;
325     }
326
327     void SaveDosHeader();
328     void SaveSignature();
329     void SaveFileHeader();
330     void SaveOptionalHeader();
331     void SaveSections();
332
333     // IStream support - the only actually implemented method is IStream::Write
334
335     // IUnknown methods
336     STDMETHODIMP_(ULONG) AddRef()
337     {
338         return 1;
339     }
340
341     STDMETHODIMP_(ULONG) Release()
342     {
343         return 1;
344     }
345
346     STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)
347     {
348         HRESULT hr = S_OK;
349         if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) {
350             *ppv = static_cast<IStream *>(this);
351         }
352         else {
353             *ppv = NULL;
354             hr = E_NOINTERFACE;
355         }
356         return hr;
357     }
358
359     // ISequentialStream methods:
360     STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead)
361     {
362         _ASSERTE(false);
363         return E_NOTIMPL;
364     }
365
366     STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten);
367
368     // IStream methods:
369     STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
370     {
371         // IMetaDataEmit::SaveToStream calls Seek(0) but ignores the returned error
372         //_ASSERTE(false);
373         return E_NOTIMPL;
374     }
375
376     STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize)
377     {
378         _ASSERTE(false);
379         return E_NOTIMPL;
380     }
381
382     STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
383     {
384         _ASSERTE(false);
385         return E_NOTIMPL;
386     }
387
388     STDMETHODIMP Commit(DWORD grfCommitFlags)
389     {
390         _ASSERTE(false);
391         return E_NOTIMPL;
392     }
393
394     STDMETHODIMP Revert()
395     {
396         _ASSERTE(false);
397         return E_NOTIMPL;
398     }
399
400     STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
401     {
402         _ASSERTE(false);
403         return E_NOTIMPL;
404     }
405
406     STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
407     {
408         _ASSERTE(false);
409         return E_NOTIMPL;
410     }
411
412     STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag)
413     {
414         _ASSERTE(false);
415         return E_NOTIMPL;
416     }
417
418     STDMETHODIMP Clone(IStream **ppIStream)
419     {
420         _ASSERTE(false);
421         return E_NOTIMPL;
422     }
423
424 public:
425     ZapWriter();
426     ~ZapWriter();
427
428     void Initialize();
429
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)
432     {
433         _ASSERTE(!IsSaving());
434         ZapPhysicalSection * pSection = new (GetHeap()) ZapPhysicalSection(pszName, dwCharacteristics);
435         m_Sections.Append(pSection);
436         return pSection;
437     }
438
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)
442     {
443         _ASSERTE(!IsSaving());
444         ZapVirtualSection * pSection = new (GetHeap()) ZapVirtualSection(dwAlignment);
445         if (pInsertAfter != NULL)
446         {
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++)
450             {
451                 if (pPhysicalSection->m_Sections[iSection] == pInsertAfter)
452                 {
453                     pPhysicalSection->m_Sections.Insert(pPhysicalSection->m_Sections+(iSection+1));
454                     pPhysicalSection->m_Sections[iSection+1] = pSection;
455                     return pSection;                    
456                 }
457             }
458             _ASSERTE(false);
459         }
460
461         pPhysicalSection->m_Sections.Append(pSection);
462         return pSection;
463     }
464
465     void MarkBssSection(ZapPhysicalSection * pPhysicalSection, ZapVirtualSection * pSection)
466     {
467         _ASSERTE(!IsSaving());
468         _ASSERTE(pPhysicalSection->m_Sections[pPhysicalSection->m_Sections.GetCount() - 1] == pSection);
469         pPhysicalSection->m_nBssSections++;
470     }
471
472     void Append(ZapVirtualSection * pVirtualSection, ZapNode * pNode)
473     {
474         _ASSERTE(!IsSaving());
475         pVirtualSection->m_Nodes.Append(pNode);
476     }
477
478     // Set the directory entry in the image to match the given ZapNode
479     void SetDirectoryEntry(DWORD entry, ZapNode * pNode)
480     {
481         _ASSERTE(!IsSaving());
482         _ASSERTE(entry < IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
483         _ASSERTE(m_DirectoryEntries[entry] == NULL);
484         m_DirectoryEntries[entry] = pNode;
485     }
486
487     // Set the timedate stamp of the image
488     void SetTimeDateStamp(DWORD dwTimeDateStamp)
489     {
490         _ASSERTE(!IsSaving());
491         m_dwTimeDateStamp = dwTimeDateStamp;
492     }
493
494     // Set the base address of the image
495     void SetBaseAddress(ULONGLONG baseAddress)
496     {
497         _ASSERTE(!IsSaving());
498         m_BaseAddress = baseAddress;
499     }
500
501     ULONGLONG GetBaseAddress()
502     {
503         _ASSERTE(m_BaseAddress != 0);
504         return m_BaseAddress;
505     }
506
507     void SetSizeOfStackReserve(ULONGLONG sizeOfStackReserve)
508     {
509         _ASSERTE(!IsSaving());
510         m_SizeOfStackReserve = sizeOfStackReserve;
511     }
512
513     void SetSizeOfStackCommit(ULONGLONG sizeOfStackCommit)
514     {
515         _ASSERTE(!IsSaving());
516         m_SizeOfStackCommit = sizeOfStackCommit;
517     }
518
519     void SetSubsystem(USHORT subsystem)
520     {
521         _ASSERTE(!IsSaving());
522         m_Subsystem = subsystem;
523     }
524
525     void SetDllCharacteristics(USHORT dllCharacteristics)
526     {
527         _ASSERTE(!IsSaving());
528         m_DllCharacteristics = dllCharacteristics;
529     }
530
531     void SetIsDll(BOOL isDLL)
532     {
533         m_isDll = isDLL;
534     }
535
536     void SetFileAlignment(DWORD fileAlignment)
537     {
538         m_FileAlignment = fileAlignment;
539     }
540
541     // Compute RVAs for everything in the file
542     void ComputeRVAs();
543
544     // Save the content into stream
545     void Save(IStream * pStream);
546
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.
549     ZapHeap * GetHeap()
550     {
551         return m_pHeap;
552     }
553
554     COUNT_T GetPhysicalSectionCount()
555     {
556         return m_Sections.GetCount();
557     }
558
559     ZapPhysicalSection * GetPhysicalSection(COUNT_T iSection)
560     {
561         return m_Sections[iSection];
562     }
563
564 #ifdef _DEBUG
565     // Certain methods can be called only during the save phase
566     BOOL IsSaving()
567     {
568         return m_fSaving;
569     }
570 #endif
571
572     DWORD GetCurrentRVA()
573     {
574         _ASSERTE(IsSaving());
575         return m_dwCurrentRVA;
576     }
577
578
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);
581
582     // Writes padding
583     void WritePad(DWORD size, BYTE fill = 0);
584
585     // Flush any buffered data
586     void FlushWriter();
587
588     BOOL IsWritingRelocs()
589     {
590         return m_fWritingRelocs;
591     }
592
593     void SetWritingRelocs()
594     {
595         m_fWritingRelocs = TRUE;
596     }
597
598     // Convenience helper to initialize IMAGE_DATA_DIRECTORY
599     static void SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode);
600 };
601
602 //---------------------------------------------------------------------------------------
603 // ZapBlob
604 //
605 // Generic node for unstructured sequence of bytes.
606 // Includes SHash support (ZapBlob::SHashTraits)
607 //
608 class ZapBlob : public ZapNode
609 {
610     DWORD m_cbSize;
611
612 protected:
613     ZapBlob(SIZE_T cbSize)
614         : m_cbSize((DWORD)cbSize)
615     {
616         if (cbSize > ZAPWRITER_MAX_SIZE)
617             ThrowHR(COR_E_OVERFLOW);
618     }
619
620 public:
621     class SHashKey
622     {
623         PBYTE   m_pData;
624         SIZE_T  m_cbSize;
625
626     public:
627         SHashKey(PVOID pData, SIZE_T cbSize)
628             : m_pData((PBYTE)pData), m_cbSize(cbSize)
629         {
630         }
631
632         PBYTE GetData() const
633         {
634             return m_pData;
635         }
636
637         SIZE_T GetBlobSize() const
638         {
639             return m_cbSize;
640         }
641     };
642
643     class SHashTraits : public DefaultSHashTraits<ZapBlob *>
644     {
645     public:
646         typedef const ZapBlob::SHashKey key_t;
647
648         static key_t GetKey(element_t e)
649         {
650             LIMITED_METHOD_CONTRACT;
651             return key_t(e->GetData(), e->GetBlobSize());
652         }
653         static BOOL Equals(key_t k1, key_t k2)
654         {
655             LIMITED_METHOD_CONTRACT;
656             if (k1.GetBlobSize() != k2.GetBlobSize())
657                 return FALSE;
658             return memcmp(k1.GetData(), k2.GetData(), k1.GetBlobSize()) == 0;
659         }
660         static count_t Hash(key_t k)
661         {
662             LIMITED_METHOD_CONTRACT;
663             count_t hash = 5381 + (count_t)(k.GetBlobSize() << 7);
664
665             PBYTE pbData = k.GetData();
666             PBYTE pbDataEnd = pbData + k.GetBlobSize();
667
668             for (/**/ ; pbData < pbDataEnd; pbData++)
669             {
670                 hash = ((hash << 5) + hash) ^ *pbData;
671             }
672             return hash;
673         }
674     };
675
676     virtual PBYTE GetData()
677     {
678         return (PBYTE)(this + 1);
679     }
680
681     // Used to shrink the size of the blob
682     void AdjustBlobSize(SIZE_T cbSize)
683     {
684         _ASSERTE(cbSize <= m_cbSize);
685         _ASSERTE(cbSize != 0);
686         m_cbSize = (DWORD)cbSize;
687     }
688
689     // Raw size of the blob
690     DWORD GetBlobSize()
691     {
692         return m_cbSize;
693     }
694
695     virtual DWORD GetSize()
696     {
697         return m_cbSize;
698     }
699
700     virtual ZapNodeType GetType()
701     {
702         return ZapNodeType_Blob;
703     }
704
705     virtual void Save(ZapWriter * pZapWriter);
706
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);
709
710     // Create new aligned zap blob node.
711     static ZapBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment);
712 };
713
714 class ZapBlobPtr : public ZapBlob
715 {
716     PBYTE m_pData;
717
718 public:
719     ZapBlobPtr(PVOID pData, SIZE_T cbSize)
720         : ZapBlob(cbSize), m_pData((PBYTE)pData)
721     {
722     }
723
724     virtual PBYTE GetData()
725     {
726         return m_pData;
727     }
728 };
729
730 class ZapDummyNode : public ZapNode
731 {
732     DWORD m_cbSize;
733
734 public:
735     ZapDummyNode(DWORD cbSize)
736         : m_cbSize(cbSize)
737     {
738     }
739
740     virtual DWORD GetSize()
741     {
742         return m_cbSize;
743     }
744 };
745
746 #endif // __ZAPWRITER_H__