summaryrefslogtreecommitdiff
path: root/src/dlls/mscorpe/pewriter.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/dlls/mscorpe/pewriter.h')
-rw-r--r--src/dlls/mscorpe/pewriter.h337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/dlls/mscorpe/pewriter.h b/src/dlls/mscorpe/pewriter.h
new file mode 100644
index 0000000000..3a4a4fd647
--- /dev/null
+++ b/src/dlls/mscorpe/pewriter.h
@@ -0,0 +1,337 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#ifndef PEWriter_H
+#define PEWriter_H
+
+#include <crtwrap.h>
+
+#include <windows.h>
+
+#include "ceegen.h"
+
+#include "pesectionman.h"
+
+class PEWriter;
+class PEWriterSection;
+class PEDecoder;
+struct entry;
+struct _IMAGE_SECTION_HEADER;
+
+#define SUBSECTION_ALIGN 16
+
+/***************************************************************/
+// PEWriter is derived from PESectionManager. While the base class just
+// manages the sections, PEWriter can actually write them out.
+
+class PEWriter : public PESectionMan
+{
+public:
+
+ // See ICeeFileGen.h for definition of createFlags
+ HRESULT Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileName = NULL);
+ HRESULT Cleanup();
+
+ // Finds section with given name. returns 0 if not found
+ virtual PESection* getSection(const char* name);
+
+ // Create a new section
+ virtual HRESULT newSection(const char* name, PESection **section,
+ unsigned flags=sdNone, unsigned estSize=0x10000,
+ unsigned estRelocs=0x100);
+
+ HRESULT link();
+ HRESULT fixup(CeeGenTokenMapper *pMapper);
+ HRESULT write(__in LPCWSTR fileName);
+ HRESULT write(void **ppImage);
+
+ // calling these functions is optional
+ DWORD getSectionAlignment();
+ void setSectionAlignment(DWORD);
+ DWORD getFileAlignment();
+ void setFileAlignment(DWORD);
+ DWORD getImageBase32();
+ void setImageBase32(DWORD);
+ UINT64 getImageBase64();
+ void setImageBase64(UINT64);
+ void stripRelocations(bool val); // default = false
+
+ void getHeaderInfo(PIMAGE_NT_HEADERS *ppNtHeaders, PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections);
+
+ // these affect the charactertics in the NT file header
+ void setCharacteristics(unsigned mask);
+ void clearCharacteristics(unsigned mask);
+
+ // these affect the charactertics in the NT optional header
+ void setDllCharacteristics(unsigned mask);
+ void clearDllCharacteristics(unsigned mask);
+
+ // sets the SubSystem field in the optional header
+ void setSubsystem(unsigned subsystem, unsigned major, unsigned minor);
+
+ // specify the entry point as an offset into the text section. The
+ // method will convert into an RVA from the base
+ void setEntryPointTextOffset(unsigned entryPoint);
+
+ HRESULT setDirectoryEntry(PEWriterSection *section, ULONG entry, ULONG size, ULONG offset=0);
+
+
+ // get the RVA for the IL section
+ ULONG getIlRva();
+
+ // set the RVA for the IL section by supplying offset to the IL section
+ void setIlRva(DWORD offset);
+
+ unsigned getSubsystem();
+
+ size_t getImageBase();
+
+ void setEnCRvaBase(ULONG dataBase, ULONG rdataBase);
+
+ HRESULT getFileTimeStamp(DWORD *pTimeStamp);
+
+ IMAGE_NT_HEADERS32* ntHeaders32() { return (IMAGE_NT_HEADERS32*) m_ntHeaders; }
+ IMAGE_NT_HEADERS64* ntHeaders64() { return (IMAGE_NT_HEADERS64*) m_ntHeaders; }
+
+ bool isPE32() // true -> created a PE 32-bit PE file
+ // false -> created a PE+ 64-bit PE file
+ { return (m_ntHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)); }
+
+ bool isI386() // true -> target machine is i386
+ { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_I386)); }
+
+ bool isIA64() // true -> target machine is ia64
+ { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_IA64)); }
+
+ bool isAMD64() // true -> target machine is ia64
+ { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_AMD64)); }
+
+ bool isARM() // true -> target machine is ARM
+ { return (m_ntHeaders->FileHeader.Machine == VAL16(IMAGE_FILE_MACHINE_ARMNT)); }
+
+ bool createCorMainStub() // do we need the CorExeMain/CorDllMain stubs?
+ { return m_createCorMainStub; }
+
+private:
+ DWORD m_ilRVA;
+ BOOL m_encMode;
+ ULONG m_dataRvaBase;
+ ULONG m_rdataRvaBase;
+ ULONG m_codeRvaBase;
+ DWORD m_peFileTimeStamp;
+
+ HANDLE m_file;
+
+ // "Seed" file information. The new file data will be "appended" to the seed file
+ // These are valid only if m_hSeedFile is valid
+
+ HANDLE m_hSeedFile;
+ HANDLE m_hSeedFileMap;
+ PEDecoder * m_pSeedFileDecoder;
+ IMAGE_NT_HEADERS * m_pSeedFileNTHeaders;
+ unsigned m_iSeedSections;
+ IMAGE_SECTION_HEADER*m_pSeedSections;
+ IMAGE_SECTION_HEADER*m_pSeedSectionToAdd; // used only by newSection()
+
+ PEWriterSection **getSectStart() {
+ return (PEWriterSection**)sectStart;
+ }
+
+ PEWriterSection **getSectCur() {
+ return (PEWriterSection**)sectCur;
+ }
+
+ COUNT_T getSectCount() {
+ return COUNT_T(sectCur - sectStart);
+ }
+
+
+ IMAGE_DOS_HEADER m_dosHeader;
+ IMAGE_NT_HEADERS * m_ntHeaders;
+ DWORD m_ntHeadersSize; // Size of IMAGE_NT_HEADERS (not including section headers)
+
+ unsigned virtualPos;
+ unsigned filePos;
+
+ PEWriterSection * reloc;
+ PEWriterSection * strtab;
+
+ IMAGE_SECTION_HEADER *headers, *headersEnd;
+
+ struct directoryEntry {
+ PEWriterSection *section;
+ ULONG offset;
+ ULONG size;
+ };
+
+ // Directory entries in the file header
+ directoryEntry * pEntries;
+ USHORT cEntries;
+
+ bool m_createCorMainStub;
+
+ // Helpers for link()
+ HRESULT linkSortSections(entry * entries,
+ unsigned * piEntries, // OUT
+ unsigned * piUniqueSections); // OUT
+ HRESULT linkSortHeaders(entry * entries, unsigned iEntries, unsigned iUniqueSections);
+ HRESULT linkPlaceSections(entry * entries, unsigned iEntries);
+ void setSectionIndex(IMAGE_SECTION_HEADER * h, unsigned sectionIndex);
+
+ HRESULT Open(__in LPCWSTR fileName);
+ HRESULT Write(const void *data, int size);
+ HRESULT Seek(int offset);
+ HRESULT Pad(int align);
+ HRESULT Close();
+};
+
+// This class encapsulates emitting the base relocs into the
+// .reloc section of the PE file, for the case where the image
+// does not get loaded at its preferred base address.
+
+class PERelocSection
+{
+ private:
+ PEWriterSection * section;
+ unsigned relocPage;
+ unsigned relocSize;
+ DWORD * relocSizeAddr;
+ unsigned pages;
+
+#ifdef _DEBUG
+ unsigned lastRVA;
+#endif
+
+ public:
+ PERelocSection(PEWriterSection *pBaseReloc);
+ void AddBaseReloc(unsigned rva, int type, unsigned short highAdj=0);
+ void Finish(bool isPE32);
+};
+
+class PEWriterSection : public PESection {
+
+public:
+
+ PEWriterSection(const char* name, unsigned flags,
+ unsigned estSize, unsigned estRelocs)
+ : PESection(name, flags, estSize, estRelocs) {}
+
+ virtual HRESULT applyRelocs(IMAGE_NT_HEADERS * pNtHeaders,
+ PERelocSection * relocSection,
+ CeeGenTokenMapper * pTokenMapper,
+ DWORD rdataRvaBase,
+ DWORD dataRvaBase,
+ DWORD textRvaBase);
+
+ virtual HRESULT write (HANDLE file);
+ virtual unsigned writeMem (void ** pMem);
+ virtual bool isSeedSection() { return false; }
+
+};
+
+// This is for sections from the seed file. Their order needs to be maintained and
+// they need to be written to the output file.
+
+class PESeedSection : public PEWriterSection {
+
+public:
+
+ PESeedSection(PEDecoder * peDecoder, IMAGE_SECTION_HEADER * seedSection);
+
+ // PESection methods
+
+ unsigned dataLen() { return m_pSeedSectionHeader->SizeOfRawData; }
+ HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper) { return S_OK; }
+ char* getBlock(unsigned len, unsigned align) { _ASSERTE(!"PESeedSection"); return NULL; }
+ HRESULT truncate(unsigned newLen) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+ void writeSectReloc(unsigned val, CeeSection& relativeTo,
+ CeeSectionRelocType reloc,
+ CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return; }
+ HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo,
+ CeeSectionRelocType reloc,
+ CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+ HRESULT addSectReloc(unsigned offset, PESection *relativeTo,
+ CeeSectionRelocType reloc,
+ CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+ HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc,
+ CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+// unsigned char *name();
+// unsigned flags();
+// unsigned getBaseRVA();
+ int getDirEntry() { _ASSERTE(!"PESeedSection"); return 0; }
+ HRESULT directoryEntry(unsigned num) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+ char * computePointer(unsigned offset) const { _ASSERTE(!"PESeedSection"); return NULL; }
+ BOOL containsPointer(__in char *ptr) const { _ASSERTE(!"PESeedSection"); return FALSE; }
+ unsigned computeOffset(__in char *ptr) const { _ASSERTE(!"PESeedSection"); return 0; }
+ HRESULT cloneInstance(PESection *destination) { _ASSERTE(!"PESeedSection"); return E_FAIL; }
+
+ // PEWriterSection
+
+ HRESULT applyRelocs(IMAGE_NT_HEADERS * pNtHeaders,
+ PERelocSection * relocSection,
+ CeeGenTokenMapper * pTokenMapper,
+ DWORD rdataRvaBase,
+ DWORD dataRvaBase,
+ DWORD textRvaBase) { return S_OK; }
+
+ HRESULT write(HANDLE file);
+ unsigned writeMem(void ** pMem);
+ bool isSeedSection() { return true; }
+
+protected:
+
+ PEDecoder * m_pSeedFileDecoder;
+ IMAGE_SECTION_HEADER * m_pSeedSectionHeader;
+
+};
+
+inline DWORD PEWriter::getSectionAlignment() {
+ return VAL32(m_ntHeaders->OptionalHeader.FileAlignment);
+}
+
+inline void PEWriter::setSectionAlignment(DWORD SectionAlignment) {
+
+ _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE);
+ m_ntHeaders->OptionalHeader.SectionAlignment = VAL32(SectionAlignment);
+}
+
+inline DWORD PEWriter::getFileAlignment() {
+ return m_ntHeaders->OptionalHeader.FileAlignment;
+}
+
+inline void PEWriter::setFileAlignment(DWORD fileAlignment) {
+ _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE);
+ m_ntHeaders->OptionalHeader.FileAlignment = VAL32(fileAlignment);
+}
+
+inline unsigned PEWriter::getSubsystem() {
+ return VAL16(m_ntHeaders->OptionalHeader.Subsystem);
+}
+
+inline void PEWriter::setSubsystem(unsigned subsystem, unsigned major, unsigned minor) {
+ m_ntHeaders->OptionalHeader.Subsystem = VAL16(subsystem);
+ m_ntHeaders->OptionalHeader.MajorSubsystemVersion = VAL16(major);
+ m_ntHeaders->OptionalHeader.MinorSubsystemVersion = VAL16(minor);
+}
+
+inline void PEWriter::setCharacteristics(unsigned mask) {
+ m_ntHeaders->FileHeader.Characteristics |= VAL16(mask);
+}
+
+inline void PEWriter::clearCharacteristics(unsigned mask) {
+ m_ntHeaders->FileHeader.Characteristics &= VAL16(~mask);
+}
+
+inline void PEWriter::setDllCharacteristics(unsigned mask) {
+ m_ntHeaders->OptionalHeader.DllCharacteristics |= VAL16(mask);
+}
+
+inline void PEWriter::clearDllCharacteristics(unsigned mask) {
+ m_ntHeaders->OptionalHeader.DllCharacteristics &= VAL16(~mask);
+}
+
+inline void PEWriter::setEntryPointTextOffset(unsigned offset) {
+ m_ntHeaders->OptionalHeader.AddressOfEntryPoint = VAL32(offset);
+}
+
+#endif