| 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 | // Section Manager for portable executables |
| 5 | // Common to both Memory Only and Static (EXE making) code |
| 6 | |
| 7 | |
| 8 | #ifndef PESectionMan_H |
| 9 | #define PESectionMan_H |
| 10 | |
| 11 | #include "windef.h" |
| 12 | |
| 13 | #include "ceegen.h" |
| 14 | #include "blobfetcher.h" |
| 15 | |
| 16 | class PESection; |
| 17 | struct PESectionReloc; |
| 18 | |
| 19 | struct ; |
| 20 | |
| 21 | class PESectionMan |
| 22 | { |
| 23 | public: |
| 24 | |
| 25 | virtual ~PESectionMan() {} |
| 26 | |
| 27 | HRESULT Init(); |
| 28 | HRESULT Cleanup(); |
| 29 | |
| 30 | // Finds section with given name, or creates a new one |
| 31 | HRESULT getSectionCreate( |
| 32 | const char *name, |
| 33 | unsigned flags, // IMAGE_SCN_* flags. eg. IMAGE_SCN_CNT_INITIALIZED_DATA |
| 34 | PESection **section); |
| 35 | |
| 36 | // Since we allocate, we must delete (Bug in VC, see knowledge base Q122675) |
| 37 | void sectionDestroy(PESection **section); |
| 38 | |
| 39 | // Apply all the relocs for in memory conversion |
| 40 | HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); |
| 41 | |
| 42 | HRESULT cloneInstance(PESectionMan *destination); |
| 43 | |
| 44 | protected: |
| 45 | |
| 46 | // Finds section with given name. returns 0 if not found |
| 47 | virtual PESection *getSection(const char *name); |
| 48 | |
| 49 | // Create a new section |
| 50 | virtual HRESULT newSection( |
| 51 | const char *name, |
| 52 | PESection **section, |
| 53 | unsigned flags = sdNone, |
| 54 | unsigned estSize = 0x10000, |
| 55 | unsigned estRelocs = 1); |
| 56 | |
| 57 | // Keep proctected & no accessors, so that derived class PEWriter |
| 58 | // is the ONLY one with access |
| 59 | |
| 60 | PESection **sectStart; |
| 61 | PESection **sectCur; |
| 62 | PESection **sectEnd; |
| 63 | }; // class PESectionMan |
| 64 | |
| 65 | /*************************************************************** |
| 66 | * This represents a section of a ICeeFileGen. Multiple sections |
| 67 | * can be created with pointers to one another. These will |
| 68 | * automatically get fixed up when the ICeeFileGen is "baked". |
| 69 | * |
| 70 | * It is implemented using CBlobFetcher as a list of blobs. |
| 71 | * Thus it can grow arbitrarily. At the same time, it can appear |
| 72 | * as a flat consecutive piece of memory which can be indexed into |
| 73 | * using offsets. |
| 74 | */ |
| 75 | |
| 76 | class PESection : public CeeSectionImpl { |
| 77 | public: |
| 78 | // bytes in this section at present |
| 79 | unsigned dataLen(); |
| 80 | |
| 81 | // Apply all the relocs for in memory conversion |
| 82 | HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); |
| 83 | |
| 84 | // get a block to write on (use instead of write to avoid copy) |
| 85 | char* getBlock(unsigned len, unsigned align=1); |
| 86 | |
| 87 | // writes 'val' (which is offset into section 'relativeTo') |
| 88 | // and adds a relocation fixup for that section |
| 89 | void (unsigned val, CeeSection& relativeTo, |
| 90 | CeeSectionRelocType reloc = srRelocHighLow, |
| 91 | CeeSectionRelocExtra *=0); |
| 92 | |
| 93 | // Indicates that the DWORD at 'offset' in the current section should |
| 94 | // have the base of section 'relativeTo' added to it |
| 95 | HRESULT (unsigned offset, CeeSection& relativeTo, |
| 96 | CeeSectionRelocType reloc = srRelocHighLow, |
| 97 | CeeSectionRelocExtra *=0); |
| 98 | |
| 99 | // If relativeTo is NULL, it is treated as a base reloc. |
| 100 | // ie. the value only needs to be fixed at load time if the module gets rebased. |
| 101 | HRESULT (unsigned offset, PESection *relativeTo, |
| 102 | CeeSectionRelocType reloc = srRelocHighLow, |
| 103 | CeeSectionRelocExtra *=0); |
| 104 | |
| 105 | // Add a base reloc for the given offset in the current section |
| 106 | HRESULT (unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, |
| 107 | CeeSectionRelocExtra * = 0); |
| 108 | |
| 109 | // section name |
| 110 | unsigned char *name() { |
| 111 | LIMITED_METHOD_CONTRACT; |
| 112 | return (unsigned char *) m_name; |
| 113 | } |
| 114 | |
| 115 | // section flags |
| 116 | unsigned flags() { |
| 117 | LIMITED_METHOD_CONTRACT; |
| 118 | return m_flags; |
| 119 | } |
| 120 | |
| 121 | // virtual base |
| 122 | unsigned getBaseRVA() { |
| 123 | LIMITED_METHOD_CONTRACT; |
| 124 | return m_baseRVA; |
| 125 | } |
| 126 | |
| 127 | // return the dir entry for this section |
| 128 | int getDirEntry() { |
| 129 | LIMITED_METHOD_CONTRACT; |
| 130 | return dirEntry; |
| 131 | } |
| 132 | // this section will be directory entry 'num' |
| 133 | HRESULT directoryEntry(unsigned num); |
| 134 | |
| 135 | // Indexes offset as if this were an array |
| 136 | // Returns a pointer into the correct blob |
| 137 | virtual char * computePointer(unsigned offset) const; |
| 138 | |
| 139 | // Checks to see if pointer is in section |
| 140 | virtual BOOL containsPointer(__in char *ptr) const; |
| 141 | |
| 142 | // Given a pointer pointing into this section, |
| 143 | // computes an offset as if this were an array |
| 144 | virtual unsigned computeOffset(__in char *ptr) const; |
| 145 | |
| 146 | // Make 'destination' a copy of the current PESection |
| 147 | HRESULT cloneInstance(PESection *destination); |
| 148 | |
| 149 | // Cause the section to allocate memory in smaller chunks |
| 150 | void SetInitialGrowth(unsigned growth); |
| 151 | |
| 152 | virtual ~PESection(); |
| 153 | private: |
| 154 | |
| 155 | // purposely not defined, |
| 156 | PESection(); |
| 157 | |
| 158 | // purposely not defined, |
| 159 | PESection(const PESection&); |
| 160 | |
| 161 | // purposely not defined, |
| 162 | PESection& operator=(const PESection& x); |
| 163 | |
| 164 | // this dir entry points to this section |
| 165 | int dirEntry; |
| 166 | |
| 167 | protected: |
| 168 | friend class PEWriter; |
| 169 | friend class PEWriterSection; |
| 170 | friend class PESectionMan; |
| 171 | |
| 172 | PESection(const char* name, unsigned flags, |
| 173 | unsigned estSize, unsigned estRelocs); |
| 174 | |
| 175 | // Blob fetcher handles getBlock() and fetching binary chunks. |
| 176 | CBlobFetcher m_blobFetcher; |
| 177 | |
| 178 | PESectionReloc* m_relocStart; |
| 179 | PESectionReloc* m_relocCur; |
| 180 | PESectionReloc* m_relocEnd; |
| 181 | |
| 182 | // These will be set while baking (finalizing) the file |
| 183 | unsigned m_baseRVA; // RVA into the file of this section. |
| 184 | unsigned m_filePos; // Start offset into the file (treated as a data image) |
| 185 | unsigned m_filePad; // Padding added to the end of the section for alignment |
| 186 | |
| 187 | char m_name[8+6]; // extra room for digits |
| 188 | unsigned m_flags; |
| 189 | |
| 190 | struct _IMAGE_SECTION_HEADER* ; // Corresponding header. Assigned after link() |
| 191 | }; |
| 192 | |
| 193 | /***************************************************************/ |
| 194 | /* implementation section */ |
| 195 | |
| 196 | inline HRESULT PESection::directoryEntry(unsigned num) { |
| 197 | WRAPPER_NO_CONTRACT; |
| 198 | TESTANDRETURN(num < 16, E_INVALIDARG); |
| 199 | dirEntry = num; |
| 200 | return S_OK; |
| 201 | } |
| 202 | |
| 203 | // This remembers the location where a reloc needs to be applied. |
| 204 | // It is relative to the contents of a PESection |
| 205 | |
| 206 | struct PESectionReloc { |
| 207 | CeeSectionRelocType type; // type of reloc |
| 208 | unsigned offset; // offset within the current PESection where the reloc is to be applied |
| 209 | CeeSectionRelocExtra ; |
| 210 | PESection* section; // target PESection. NULL implies that the target is a fixed address outside the module |
| 211 | }; |
| 212 | |
| 213 | #endif // #define PESectionMan_H |
| 214 | |