summaryrefslogtreecommitdiff
path: root/src/inc/ceegen.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/ceegen.h')
-rw-r--r--src/inc/ceegen.h440
1 files changed, 440 insertions, 0 deletions
diff --git a/src/inc/ceegen.h b/src/inc/ceegen.h
new file mode 100644
index 0000000000..a2dfadfc00
--- /dev/null
+++ b/src/inc/ceegen.h
@@ -0,0 +1,440 @@
+// 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.
+// ===========================================================================
+// 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:
+
+ virtual ~CCeeGen() {}
+
+ 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