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// File: CEEGEN.H
6//
7// ===========================================================================
8
9#ifndef _CEEGEN_H_
10#define _CEEGEN_H_
11
12#include "cor.h"
13#include "iceefilegen.h"
14#include "ceegentokenmapper.h"
15
16class CeeSection;
17class CeeSectionString;
18class CCeeGen;
19class PESectionMan;
20class PESection;
21
22typedef DWORD StringRef;
23
24#if 0
25
26 This is a description of the current implementation of these types for generating
27 CLR modules.
28
29 ICeeGen - interface to generate in-memory CLR module.
30
31 CCeeGen - implementation of ICeeGen. Currently it uses both CeeSections
32 as well as PESections (inside PESectionMan), and maintains a
33 1:1 relation between them. This is ugly.
34
35 CeeFileGenWriter - Provides functionality to write in-memory module to
36 PE format file. Uses PEWriter (m_pSectionMan) for
37 file-writing functionality
38
39 PEWriter - It can generate a PE format file. It also knows to apply
40 pointer relocs when it lays out the PESections.
41
42
43 ICeeFileGen - Interface used by compilers, ngen, etc, to generate
44 a CLR file.
45 Has a bunch of methods to emit signatures, tokens, methods,
46 etc which are not implemented. These are left over from before
47
48 +----------------------------+
49 | ICeeGen |
50 | |
51 | COM-style version of |
52 | ICeeFileGen. HCEEFILE is |
53 | replaced with "this" |
54 +-------------------------+ | |
55 | CeeSectionImpl | +----------------------------+
56 +-------------------------+ |
57 | | |
58 | | v
59 | v +---------------------------+
60 | +------------+ | CCeeGen |
61 | | | +---------------------------+
62 | | CeeSection | contains | |
63 | | |<-------------| CeeSection* m_sections |
64 | +------------+ | |
65 | /| PESectionMan m_pSectionMan|
66 | / | |
67 | +-----------------+ / +---------------------------+
68 v | PESectionMan |<----+ |
69 +-----------+ | | contains |
70 | PESection | +-----------------+ |
71 | | contains | PESection * | v
72 | |<----------| sectStart, | +------------------------------+
73 +-----------+ | sectCur, | | CeeFileGenWriter |
74 | sectEnd | +------------------------------+
75 +-----------------+ | Does meta-data specific |
76 | | stuff and then dispatches to |
77 | | m_pSectionMan.PEWriter::***()|
78 | | |
79 v +------------------------------+
80 +------------------------+ ^
81 | PEWriter | |wraps
82 +------------------------+ |
83 | Low -level file writer | +----------------------------+
84 | Knows how to do | | ICeeFileGen |
85 | pointer relocs | | |
86 | | | C-style inteface. Deals |
87 +------------------------+ | with HCEEFILE, HCEESECTION |
88 | etc. It is mostly just a |
89 | thin wrapper for a |
90 | CeeFileGenWriter |
91 +----------------------------+
92
93#endif // 0
94
95// ***** CeeSection classes
96
97class CeeSectionImpl {
98 public:
99 virtual unsigned dataLen() = 0;
100 virtual char * getBlock(
101 unsigned len,
102 unsigned align = 1) = 0;
103 virtual HRESULT addSectReloc(
104 unsigned offset,
105 CeeSection & relativeTo,
106 CeeSectionRelocType reloc = srRelocAbsolute,
107 CeeSectionRelocExtra * extra = NULL) = 0;
108 virtual HRESULT addBaseReloc(
109 unsigned offset,
110 CeeSectionRelocType reloc = srRelocHighLow,
111 CeeSectionRelocExtra * extra = NULL) = 0;
112 virtual HRESULT directoryEntry(unsigned num) = 0;
113 virtual unsigned char * name() = 0;
114 virtual char * computePointer(unsigned offset) const = 0;
115 virtual BOOL containsPointer(__in char * ptr) const = 0;
116 virtual unsigned computeOffset(__in char * ptr) const = 0;
117 virtual unsigned getBaseRVA() = 0;
118 virtual void SetInitialGrowth(unsigned growth) = 0;
119};
120
121class CeeSection {
122 // m_ceeFile allows inter-section communication
123 CCeeGen &m_ceeFile;
124
125 // abstract away implementation to allow inheritance from CeeSection
126 CeeSectionImpl &m_impl;
127
128 public:
129 enum RelocFlags {
130 RELOC_NONE = 0,
131
132 // address should be fixed up to be a RVA not a normal address
133 RELOC_RVA = 1
134 };
135
136 CeeSection(CCeeGen &ceeFile, CeeSectionImpl &impl)
137 : m_ceeFile(ceeFile), m_impl(impl) { LIMITED_METHOD_CONTRACT; }
138
139 virtual ~CeeSection() {LIMITED_METHOD_CONTRACT; }
140
141 // bytes in this section at present
142 unsigned dataLen();
143
144 // section base, after linking
145 unsigned getBaseRVA();
146
147 // get a block to write on (use instead of write to avoid copy)
148 char* getBlock(unsigned len, unsigned align=1);
149
150 // Indicates that the DWORD at 'offset' in the current section should
151 // have the base of section 'relativeTo added to it
152 HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo,
153 CeeSectionRelocType = srRelocAbsolute, CeeSectionRelocExtra *extra = 0);
154 // Add a base reloc for the given offset in the current section
155 virtual HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0);
156
157
158 // this section will be directory entry 'num'
159 HRESULT directoryEntry(unsigned num);
160
161 // return section name
162 unsigned char *name();
163
164 // simulate the base + offset with a more complex data storage
165 char * computePointer(unsigned offset) const;
166 BOOL containsPointer(__in char *ptr) const;
167 unsigned computeOffset(__in char *ptr) const;
168
169 CeeSectionImpl &getImpl();
170 CCeeGen &ceeFile();
171 void SetInitialGrowth(unsigned growth);
172};
173
174// ***** CCeeGen class
175// Only handles in memory stuff
176// Base class for CeeFileGenWriter (which actually generates PEFiles)
177
178class CCeeGen : public ICeeGen, ICeeGenInternal {
179 LONG m_cRefs;
180 BOOL m_encMode;
181 protected:
182 short m_textIdx; // m_sections[] index for the .text section
183 short m_metaIdx; // m_sections[] index for metadata (.text, or .cormeta for obj files)
184 short m_corHdrIdx; // m_sections[] index for the COM+ header (.text0)
185 short m_stringIdx; // m_sections[] index for strings (.text, or .rdata for EnC)
186 short m_ilIdx; // m_sections[] index for IL (.text)
187 bool m_objSwitch;
188
189 CeeGenTokenMapper *m_pTokenMap;
190 BOOLEAN m_fTokenMapSupported; // temporary to support both models
191 IMapToken *m_pRemapHandler;
192
193 CeeSection **m_sections;
194 short m_numSections;
195 short m_allocSections;
196
197 PESectionMan * m_peSectionMan;
198
199 IMAGE_COR20_HEADER *m_corHeader;
200 DWORD m_corHeaderOffset;
201
202 HRESULT allocateCorHeader();
203
204 HRESULT addSection(CeeSection *section, short *sectionIdx);
205
206 HRESULT setEnCMode();
207
208// Init process: Call static CreateNewInstance() , not operator new
209 protected:
210 HRESULT Init();
211 CCeeGen();
212
213 public:
214
215 virtual ~CCeeGen() {}
216
217 static HRESULT CreateNewInstance(CCeeGen* & pCeeFileGen); // call this to instantiate
218
219 virtual HRESULT Cleanup();
220
221 // ICeeGen interfaces
222
223 ULONG STDMETHODCALLTYPE AddRef();
224 ULONG STDMETHODCALLTYPE Release();
225 STDMETHODIMP QueryInterface(
226 REFIID riid,
227 void **ppInterface);
228
229 STDMETHODIMP EmitString (
230 __in LPWSTR lpString, // [IN] String to emit
231 ULONG *RVA);
232
233 STDMETHODIMP GetString (
234 ULONG RVA,
235 __inout LPWSTR *lpString);
236
237 STDMETHODIMP AllocateMethodBuffer (
238 ULONG cchBuffer, // [IN] Length of string to emit
239 UCHAR **lpBuffer, // [OUT] Returned buffer
240 ULONG *RVA);
241
242 STDMETHODIMP GetMethodBuffer (
243 ULONG RVA,
244 UCHAR **lpBuffer);
245
246 STDMETHODIMP GetIMapTokenIface (
247 IUnknown **pIMapToken);
248
249 STDMETHODIMP GenerateCeeFile ();
250
251 STDMETHODIMP GetIlSection (
252 HCEESECTION *section);
253
254 STDMETHODIMP GetStringSection (
255 HCEESECTION *section);
256
257 STDMETHODIMP AddSectionReloc (
258 HCEESECTION section,
259 ULONG offset,
260 HCEESECTION relativeTo,
261 CeeSectionRelocType relocType);
262
263 STDMETHODIMP GetSectionCreate (
264 const char *name,
265 DWORD flags,
266 HCEESECTION *section);
267
268 STDMETHODIMP GetSectionDataLen (
269 HCEESECTION section,
270 ULONG *dataLen);
271
272 STDMETHODIMP GetSectionBlock (
273 HCEESECTION section,
274 ULONG len,
275 ULONG align=1,
276 void **ppBytes=0);
277
278 STDMETHODIMP TruncateSection (
279 HCEESECTION section,
280 ULONG len);
281
282 STDMETHODIMP GenerateCeeMemoryImage (void **ppImage);
283
284 STDMETHODIMP ComputePointer (
285 HCEESECTION section,
286 ULONG RVA, // [IN] RVA for method to return
287 UCHAR **lpBuffer); // [OUT] Returned buffer
288
289
290 STDMETHODIMP AddNotificationHandler(IUnknown *pHandler);
291
292 // Write the metadata in "emitter" to the default metadata section is "section" is 0
293 // If 'section != 0, it will put the data in 'buffer'. This
294 // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen'
295 // (should use GetSaveSize to insure that buffer is big enough
296 virtual HRESULT emitMetaData(IMetaDataEmit *emitter,
297 CeeSection* section=0, DWORD offset=0, BYTE* buffer=0, unsigned buffLen=0);
298 virtual HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA);
299
300 STDMETHODIMP SetInitialGrowth(DWORD growth);
301
302 CeeSection &getTextSection();
303 CeeSection &getMetaSection();
304 CeeSection &getCorHeaderSection();
305 CeeSectionString &getStringSection();
306 CeeSection &getIlSection();
307
308 virtual HRESULT getSectionCreate (const char *name, DWORD flags, CeeSection **section=NULL, short *sectionIdx = NULL);
309
310 PESectionMan* getPESectionMan() {
311 LIMITED_METHOD_CONTRACT;
312 return m_peSectionMan;
313 }
314
315 virtual HRESULT getMapTokenIface(IUnknown **pIMapToken, IMetaDataEmit *emitter=0);
316
317 CeeGenTokenMapper *getTokenMapper() {
318 LIMITED_METHOD_CONTRACT;
319 return m_pTokenMap;
320 }
321
322 virtual HRESULT addNotificationHandler(IUnknown *pHandler);
323
324 //Clone is actually a misnomer here. This method will copy all of the
325 //instance variables and then do a deep copy (as necessary) of the sections.
326 //Section data will be appended onto any information already in the section.
327 //This is done to support the DynamicIL -> PersistedIL transform.
328 virtual HRESULT cloneInstance(CCeeGen *destination);
329
330#ifdef EMIT_FIXUPS
331public:
332 virtual HRESULT addFixup(CeeSection& sectionSource, unsigned offset, CeeSectionRelocType reloc, CeeSection * sectionTarget = NULL, CeeSectionRelocExtra *extra = 0) {
333 LIMITED_METHOD_CONTRACT;
334
335 return(E_NOTIMPL);
336 }
337#endif
338};
339
340// ***** CeeSection inline methods
341
342inline unsigned CeeSection::dataLen() {
343 WRAPPER_NO_CONTRACT;
344 return m_impl.dataLen(); }
345
346inline unsigned CeeSection::getBaseRVA() {
347 WRAPPER_NO_CONTRACT;
348 return m_impl.getBaseRVA(); }
349
350inline char *CeeSection::getBlock(unsigned len, unsigned align) {
351 WRAPPER_NO_CONTRACT;
352 return m_impl.getBlock(len, align); }
353
354inline HRESULT CeeSection::addSectReloc(
355 unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) {
356 WRAPPER_NO_CONTRACT;
357 return(m_impl.addSectReloc(offset, relativeTo, reloc, extra));
358}
359
360inline HRESULT CeeSection::addBaseReloc(unsigned offset, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) {
361 WRAPPER_NO_CONTRACT;
362 return(m_impl.addBaseReloc(offset, reloc, extra));
363}
364
365
366inline HRESULT CeeSection::directoryEntry(unsigned num) {
367 WRAPPER_NO_CONTRACT;
368 TESTANDRETURN(num < IMAGE_NUMBEROF_DIRECTORY_ENTRIES, E_INVALIDARG);
369 m_impl.directoryEntry(num);
370 return S_OK;
371}
372
373inline CCeeGen &CeeSection::ceeFile() {
374 LIMITED_METHOD_CONTRACT;
375 return m_ceeFile; }
376
377inline CeeSectionImpl &CeeSection::getImpl() {
378 LIMITED_METHOD_CONTRACT;
379 return m_impl; }
380
381inline unsigned char *CeeSection::name() {
382 WRAPPER_NO_CONTRACT;
383 return m_impl.name();
384}
385
386inline char * CeeSection::computePointer(unsigned offset) const
387{
388 WRAPPER_NO_CONTRACT;
389 return m_impl.computePointer(offset);
390}
391
392inline BOOL CeeSection::containsPointer(__in char *ptr) const
393{
394 WRAPPER_NO_CONTRACT;
395 return m_impl.containsPointer(ptr);
396}
397
398inline unsigned CeeSection::computeOffset(__in char *ptr) const
399{
400 WRAPPER_NO_CONTRACT;
401 return m_impl.computeOffset(ptr);
402}
403
404inline void CeeSection::SetInitialGrowth(unsigned growth)
405{
406 WRAPPER_NO_CONTRACT;
407 m_impl.SetInitialGrowth(growth);
408}
409
410// ***** CCeeGen inline methods
411
412inline CeeSection &CCeeGen::getTextSection() {
413 LIMITED_METHOD_CONTRACT;
414
415 return *m_sections[m_textIdx]; }
416
417inline CeeSection &CCeeGen::getMetaSection() {
418 LIMITED_METHOD_CONTRACT;
419
420 return *m_sections[m_metaIdx]; }
421
422inline CeeSection &CCeeGen::getCorHeaderSection() {
423 LIMITED_METHOD_CONTRACT;
424 _ASSERTE(m_corHdrIdx >= 0);
425 return *m_sections[m_corHdrIdx]; }
426
427inline CeeSectionString &CCeeGen::getStringSection() {
428 LIMITED_METHOD_CONTRACT;
429
430 return *(CeeSectionString*)m_sections[m_stringIdx]; }
431
432inline CeeSection &CCeeGen::getIlSection() {
433 LIMITED_METHOD_CONTRACT;
434
435 return *m_sections[m_ilIdx]; }
436
437#endif
438