summaryrefslogtreecommitdiff
path: root/src/inc/ceegen.h
blob: 13e15246016ee21960fa564454494e7997a3e28f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// ===========================================================================
// File: CEEGEN.H
//
// ===========================================================================

#ifndef _CEEGEN_H_
#define _CEEGEN_H_

#include "cor.h"
#include "iceefilegen.h"
#include "ceegentokenmapper.h"

class CeeSection;
class CeeSectionString;
class CCeeGen;
class PESectionMan;
class PESection;

typedef DWORD StringRef;

#if 0

 This is a description of the current implementation of these types for generating
 CLR modules.
 
  ICeeGen - interface to generate in-memory CLR module.

  CCeeGen - implementation of ICeeGen. Currently it uses both CeeSections
            as well as PESections (inside PESectionMan), and maintains a
            1:1 relation between them. This is ugly.

  CeeFileGenWriter - Provides functionality to write in-memory module to
                     PE format file. Uses PEWriter (m_pSectionMan) for
                     file-writing functionality

  PEWriter - It can generate a PE format file. It also knows to apply
             pointer relocs when it lays out the PESections.


  ICeeFileGen - Interface used by compilers, ngen, etc, to generate
                a CLR file.
                Has a bunch of methods to emit signatures, tokens, methods,
                etc which are not implemented. These are left over from before

  CeeFileGenWriter, PEWriter and ICeeFileGen are implemented in mscorpe.dll.
  The other types live in mscorwks.dll (src\md\CeeFileGen)
  
                                                     +----------------------------+
                                                     |       ICeeGen              |
                                                     |                            |
                                                     |  COM-style version of      |
                                                     |  ICeeFileGen. HCEEFILE is  |
                                                     |  replaced with "this"      |
        +-------------------------+                  |                            |
        |     CeeSectionImpl      |                  +----------------------------+
        +-------------------------+                                |
           |                  |                                    |
           |                  |                                    v
           |                  v                      +---------------------------+
           |             +------------+              |      CCeeGen              |
           |             |            |              +---------------------------+
           |             | CeeSection |  contains    |                           |
           |             |            |<-------------| CeeSection* m_sections    |
           |             +------------+              |                           |
           |                                        /| PESectionMan m_pSectionMan|
           |                                       / |                           |
           |             +-----------------+      /  +---------------------------+
           v             |   PESectionMan  |<----+                 |
 +-----------+           |                 |  contains             |
 | PESection |           +-----------------+                       |
 |           |  contains | PESection *     |                       v
 |           |<----------|      sectStart, |        +------------------------------+
 +-----------+           |      sectCur,   |        |       CeeFileGenWriter       |
                         |      sectEnd    |        +------------------------------+
                         +-----------------+        | Does meta-data specific      |
                                  |                 | stuff and then dispatches to |
                                  |                 | m_pSectionMan.PEWriter::***()|
                                  |                 |                              |
                                  v                 +------------------------------+
                       +------------------------+                  ^
                       |       PEWriter         |                  |wraps
                       +------------------------+                  |
                       | Low -level file writer |    +----------------------------+
                       | Knows how to do        |    |        ICeeFileGen         |
                       | pointer relocs         |    |                            |
                       |                        |    | C-style inteface. Deals    |
                       +------------------------+    | with HCEEFILE, HCEESECTION |
                                                     | etc. It is mostly just a   |
                                                     | thin wrapper for a         |
                                                     | CeeFileGenWriter           |
                                                     +----------------------------+

#endif // 0

// ***** CeeSection classes

class CeeSectionImpl {
  public:
    virtual unsigned dataLen() = 0;
    virtual char * getBlock(
        unsigned len, 
        unsigned align = 1) = 0;
    virtual HRESULT addSectReloc(
        unsigned               offset, 
        CeeSection &           relativeTo, 
        CeeSectionRelocType    reloc = srRelocAbsolute, 
        CeeSectionRelocExtra * extra = NULL) = 0;
    virtual HRESULT addBaseReloc(
        unsigned               offset, 
        CeeSectionRelocType    reloc = srRelocHighLow, 
        CeeSectionRelocExtra * extra = NULL) = 0;
    virtual HRESULT directoryEntry(unsigned num) = 0;
    virtual unsigned char * name() = 0;
    virtual char * computePointer(unsigned offset) const = 0;
    virtual BOOL containsPointer(__in char * ptr) const = 0;
    virtual unsigned computeOffset(__in char * ptr) const = 0;
    virtual unsigned getBaseRVA() = 0;
    virtual void SetInitialGrowth(unsigned growth) = 0;
};

class CeeSection {
    // m_ceeFile allows inter-section communication
    CCeeGen &m_ceeFile;

    // abstract away implementation to allow inheritance from CeeSection
    CeeSectionImpl &m_impl;

  public:
    enum RelocFlags {
        RELOC_NONE = 0,

        // address should be fixed up to be a RVA not a normal address
        RELOC_RVA = 1
    };

    CeeSection(CCeeGen &ceeFile, CeeSectionImpl &impl)
        : m_ceeFile(ceeFile), m_impl(impl) { LIMITED_METHOD_CONTRACT; }

    virtual ~CeeSection() {LIMITED_METHOD_CONTRACT;  }

    // bytes in this section at present
    unsigned dataLen();

    // section base, after linking
    unsigned getBaseRVA();

    // get a block to write on (use instead of write to avoid copy)
    char* getBlock(unsigned len, unsigned align=1);

    // 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 = srRelocAbsolute, CeeSectionRelocExtra *extra = 0);
    // Add a base reloc for the given offset in the current section
    virtual HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0);


    // this section will be directory entry 'num'
    HRESULT directoryEntry(unsigned num);

    // return section name
    unsigned char *name();

    // simulate the base + offset with a more complex data storage
    char * computePointer(unsigned offset) const;
    BOOL containsPointer(__in char *ptr) const;
    unsigned computeOffset(__in char *ptr) const;

    CeeSectionImpl &getImpl();
    CCeeGen &ceeFile();
    void SetInitialGrowth(unsigned growth);
};

// ***** CCeeGen class
// Only handles in memory stuff
// Base class for CeeFileGenWriter (which actually generates PEFiles)

class CCeeGen : public ICeeGen, ICeeGenInternal {
    LONG m_cRefs;
    BOOL m_encMode;
  protected:
    short m_textIdx;            // m_sections[] index for the .text section
    short m_metaIdx;            // m_sections[] index for metadata (.text, or .cormeta for obj files)
    short m_corHdrIdx;          // m_sections[] index for the COM+ header (.text0)
    short m_stringIdx;          // m_sections[] index for strings (.text, or .rdata for EnC)
    short m_ilIdx;              // m_sections[] index for IL (.text)
    bool m_objSwitch;

    CeeGenTokenMapper *m_pTokenMap;
    BOOLEAN m_fTokenMapSupported;   // temporary to support both models
    IMapToken *m_pRemapHandler;

    CeeSection **m_sections;
    short m_numSections;
    short m_allocSections;

    PESectionMan * m_peSectionMan;

    IMAGE_COR20_HEADER *m_corHeader;
    DWORD m_corHeaderOffset;

    HRESULT allocateCorHeader();

    HRESULT addSection(CeeSection *section, short *sectionIdx);

    HRESULT setEnCMode();

// Init process: Call static CreateNewInstance() , not operator new
  protected:
    HRESULT Init();
    CCeeGen();

  public:
    static HRESULT CreateNewInstance(CCeeGen* & pCeeFileGen); // call this to instantiate

    virtual HRESULT Cleanup();

    // ICeeGen interfaces

    ULONG STDMETHODCALLTYPE AddRef();
    ULONG STDMETHODCALLTYPE Release();
    STDMETHODIMP QueryInterface(
        REFIID riid,
        void **ppInterface);

    STDMETHODIMP EmitString (
        __in LPWSTR lpString,               // [IN] String to emit
        ULONG *RVA);

    STDMETHODIMP GetString (
        ULONG RVA,
        __inout LPWSTR *lpString);

    STDMETHODIMP AllocateMethodBuffer (
        ULONG cchBuffer,                    // [IN] Length of string to emit
        UCHAR **lpBuffer,                   // [OUT] Returned buffer
        ULONG *RVA);

    STDMETHODIMP GetMethodBuffer (
        ULONG RVA,
        UCHAR **lpBuffer);

    STDMETHODIMP GetIMapTokenIface (
        IUnknown **pIMapToken);

    STDMETHODIMP GenerateCeeFile ();

    STDMETHODIMP GetIlSection (
        HCEESECTION *section);

    STDMETHODIMP GetStringSection (
        HCEESECTION *section);

    STDMETHODIMP AddSectionReloc (
        HCEESECTION section,
        ULONG offset,
        HCEESECTION relativeTo,
        CeeSectionRelocType relocType);

    STDMETHODIMP GetSectionCreate (
        const char *name,
        DWORD flags,
        HCEESECTION *section);

    STDMETHODIMP GetSectionDataLen (
        HCEESECTION section,
        ULONG *dataLen);

    STDMETHODIMP GetSectionBlock (
        HCEESECTION section,
        ULONG len,
        ULONG align=1,
        void **ppBytes=0);

    STDMETHODIMP TruncateSection (
        HCEESECTION section,
        ULONG len);

    STDMETHODIMP GenerateCeeMemoryImage (void **ppImage);

    STDMETHODIMP ComputePointer (
        HCEESECTION section,
        ULONG RVA,                          // [IN] RVA for method to return
        UCHAR **lpBuffer);                  // [OUT] Returned buffer


    STDMETHODIMP AddNotificationHandler(IUnknown *pHandler);

    // Write the metadata in "emitter" to the default metadata section is "section" is 0
    // If 'section != 0, it will put the data in 'buffer'.  This
    // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen'
    // (should use GetSaveSize to insure that buffer is big enough
    virtual HRESULT emitMetaData(IMetaDataEmit *emitter,
                        CeeSection* section=0, DWORD offset=0, BYTE* buffer=0, unsigned buffLen=0);
    virtual HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA);

    STDMETHODIMP SetInitialGrowth(DWORD growth);

    CeeSection &getTextSection();
    CeeSection &getMetaSection();
    CeeSection &getCorHeaderSection();
    CeeSectionString &getStringSection();
    CeeSection &getIlSection();

    virtual HRESULT getSectionCreate (const char *name, DWORD flags, CeeSection **section=NULL, short *sectionIdx = NULL);

    PESectionMan* getPESectionMan() {
        LIMITED_METHOD_CONTRACT;
        return m_peSectionMan;
    }

    virtual HRESULT getMapTokenIface(IUnknown **pIMapToken, IMetaDataEmit *emitter=0);

    CeeGenTokenMapper *getTokenMapper() {
        LIMITED_METHOD_CONTRACT;
        return m_pTokenMap;
    }

    virtual HRESULT addNotificationHandler(IUnknown *pHandler);

    //Clone is actually a misnomer here.  This method will copy all of the
    //instance variables and then do a deep copy (as necessary) of the sections.
    //Section data will be appended onto any information already in the section.
    //This is done to support the DynamicIL -> PersistedIL transform.
    virtual HRESULT cloneInstance(CCeeGen *destination);

#ifdef EMIT_FIXUPS
public:
    virtual HRESULT addFixup(CeeSection& sectionSource, unsigned offset, CeeSectionRelocType reloc, CeeSection * sectionTarget = NULL, CeeSectionRelocExtra *extra = 0) {
        LIMITED_METHOD_CONTRACT;

        return(E_NOTIMPL);
    }
#endif
};

// ***** CeeSection inline methods

inline unsigned CeeSection::dataLen() {
    WRAPPER_NO_CONTRACT;
    return m_impl.dataLen(); }

inline unsigned CeeSection::getBaseRVA() {
    WRAPPER_NO_CONTRACT;
    return m_impl.getBaseRVA(); }

inline char *CeeSection::getBlock(unsigned len, unsigned align) {
    WRAPPER_NO_CONTRACT;
    return m_impl.getBlock(len, align); }

inline HRESULT CeeSection::addSectReloc(
                unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) {
    WRAPPER_NO_CONTRACT;
    return(m_impl.addSectReloc(offset, relativeTo, reloc, extra));
}

inline HRESULT CeeSection::addBaseReloc(unsigned offset, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) {
    WRAPPER_NO_CONTRACT;
    return(m_impl.addBaseReloc(offset, reloc, extra));
}


inline HRESULT CeeSection::directoryEntry(unsigned num) {
    WRAPPER_NO_CONTRACT;
    TESTANDRETURN(num < IMAGE_NUMBEROF_DIRECTORY_ENTRIES, E_INVALIDARG);
    m_impl.directoryEntry(num);
    return S_OK;
}

inline CCeeGen &CeeSection::ceeFile() {
    LIMITED_METHOD_CONTRACT;
    return m_ceeFile; }

inline CeeSectionImpl &CeeSection::getImpl() {
    LIMITED_METHOD_CONTRACT;
    return m_impl; }

inline unsigned char *CeeSection::name() {
    WRAPPER_NO_CONTRACT;
    return m_impl.name();
}

inline char * CeeSection::computePointer(unsigned offset) const
{
    WRAPPER_NO_CONTRACT;
    return m_impl.computePointer(offset);
}

inline BOOL CeeSection::containsPointer(__in char *ptr) const
{
    WRAPPER_NO_CONTRACT;
    return m_impl.containsPointer(ptr);
}

inline unsigned CeeSection::computeOffset(__in char *ptr) const
{
    WRAPPER_NO_CONTRACT;
    return m_impl.computeOffset(ptr);
}

inline void CeeSection::SetInitialGrowth(unsigned growth)
{
    WRAPPER_NO_CONTRACT;
    m_impl.SetInitialGrowth(growth);
}

// ***** CCeeGen inline methods

inline CeeSection &CCeeGen::getTextSection() {
    LIMITED_METHOD_CONTRACT;

    return *m_sections[m_textIdx]; }

inline CeeSection &CCeeGen::getMetaSection() {
    LIMITED_METHOD_CONTRACT;

    return *m_sections[m_metaIdx]; }

inline CeeSection &CCeeGen::getCorHeaderSection() {
    LIMITED_METHOD_CONTRACT;
    _ASSERTE(m_corHdrIdx >= 0);
    return *m_sections[m_corHdrIdx]; }

inline CeeSectionString &CCeeGen::getStringSection() {
    LIMITED_METHOD_CONTRACT;

    return *(CeeSectionString*)m_sections[m_stringIdx]; }

inline CeeSection &CCeeGen::getIlSection() {
    LIMITED_METHOD_CONTRACT;

    return *m_sections[m_ilIdx]; }

#endif