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 | |