diff options
Diffstat (limited to 'src/inc/pesectionman.h')
-rw-r--r-- | src/inc/pesectionman.h | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/inc/pesectionman.h b/src/inc/pesectionman.h new file mode 100644 index 0000000000..f031ca34bf --- /dev/null +++ b/src/inc/pesectionman.h @@ -0,0 +1,213 @@ +// 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. +// Section Manager for portable executables +// Common to both Memory Only and Static (EXE making) code + + +#ifndef PESectionMan_H +#define PESectionMan_H + +#include "windef.h" + +#include "ceegen.h" +#include "blobfetcher.h" + +class PESection; +struct PESectionReloc; + +struct _IMAGE_SECTION_HEADER; + +class PESectionMan +{ +public: + + virtual ~PESectionMan() {} + + HRESULT Init(); + HRESULT Cleanup(); + + // Finds section with given name, or creates a new one + HRESULT getSectionCreate( + const char *name, + unsigned flags, // IMAGE_SCN_* flags. eg. IMAGE_SCN_CNT_INITIALIZED_DATA + PESection **section); + + // Since we allocate, we must delete (Bug in VC, see knowledge base Q122675) + void sectionDestroy(PESection **section); + + // Apply all the relocs for in memory conversion + HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); + + HRESULT cloneInstance(PESectionMan *destination); + +protected: + + // 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 = 1); + + // Keep proctected & no accessors, so that derived class PEWriter + // is the ONLY one with access + + PESection **sectStart; + PESection **sectCur; + PESection **sectEnd; +}; // class PESectionMan + +/*************************************************************** + * This represents a section of a ICeeFileGen. Multiple sections + * can be created with pointers to one another. These will + * automatically get fixed up when the ICeeFileGen is "baked". + * + * It is implemented using CBlobFetcher as a list of blobs. + * Thus it can grow arbitrarily. At the same time, it can appear + * as a flat consecutive piece of memory which can be indexed into + * using offsets. + */ + +class PESection : public CeeSectionImpl { + public: + // bytes in this section at present + unsigned dataLen(); + + // Apply all the relocs for in memory conversion + HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); + + // get a block to write on (use instead of write to avoid copy) + char* getBlock(unsigned len, unsigned align=1); + + // writes 'val' (which is offset into section 'relativeTo') + // and adds a relocation fixup for that section + void writeSectReloc(unsigned val, CeeSection& relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // Indicates that the DWORD at 'offset' in the current section should + // have the base of section 'relativeTo' added to it + HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // If relativeTo is NULL, it is treated as a base reloc. + // ie. the value only needs to be fixed at load time if the module gets rebased. + HRESULT addSectReloc(unsigned offset, PESection *relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // Add a base reloc for the given offset in the current section + HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra = 0); + + // section name + unsigned char *name() { + LIMITED_METHOD_CONTRACT; + return (unsigned char *) m_name; + } + + // section flags + unsigned flags() { + LIMITED_METHOD_CONTRACT; + return m_flags; + } + + // virtual base + unsigned getBaseRVA() { + LIMITED_METHOD_CONTRACT; + return m_baseRVA; + } + + // return the dir entry for this section + int getDirEntry() { + LIMITED_METHOD_CONTRACT; + return dirEntry; + } + // this section will be directory entry 'num' + HRESULT directoryEntry(unsigned num); + + // Indexes offset as if this were an array + // Returns a pointer into the correct blob + virtual char * computePointer(unsigned offset) const; + + // Checks to see if pointer is in section + virtual BOOL containsPointer(__in char *ptr) const; + + // Given a pointer pointing into this section, + // computes an offset as if this were an array + virtual unsigned computeOffset(__in char *ptr) const; + + // Make 'destination' a copy of the current PESection + HRESULT cloneInstance(PESection *destination); + + // Cause the section to allocate memory in smaller chunks + void SetInitialGrowth(unsigned growth); + + virtual ~PESection(); +private: + + // purposely not defined, + PESection(); + + // purposely not defined, + PESection(const PESection&); + + // purposely not defined, + PESection& operator=(const PESection& x); + + // this dir entry points to this section + int dirEntry; + +protected: + friend class PEWriter; + friend class PEWriterSection; + friend class PESectionMan; + + PESection(const char* name, unsigned flags, + unsigned estSize, unsigned estRelocs); + + // Blob fetcher handles getBlock() and fetching binary chunks. + CBlobFetcher m_blobFetcher; + + PESectionReloc* m_relocStart; + PESectionReloc* m_relocCur; + PESectionReloc* m_relocEnd; + + // These will be set while baking (finalizing) the file + unsigned m_baseRVA; // RVA into the file of this section. + unsigned m_filePos; // Start offset into the file (treated as a data image) + unsigned m_filePad; // Padding added to the end of the section for alignment + + char m_name[8+6]; // extra room for digits + unsigned m_flags; + + struct _IMAGE_SECTION_HEADER* m_header; // Corresponding header. Assigned after link() +}; + +/***************************************************************/ +/* implementation section */ + +inline HRESULT PESection::directoryEntry(unsigned num) { + WRAPPER_NO_CONTRACT; + TESTANDRETURN(num < 16, E_INVALIDARG); + dirEntry = num; + return S_OK; +} + +// This remembers the location where a reloc needs to be applied. +// It is relative to the contents of a PESection + +struct PESectionReloc { + CeeSectionRelocType type; // type of reloc + unsigned offset; // offset within the current PESection where the reloc is to be applied + CeeSectionRelocExtra extra; + PESection* section; // target PESection. NULL implies that the target is a fixed address outside the module +}; + +#endif // #define PESectionMan_H |