STDMETHODIMP CCeeGen::GetSectionCreate ( const char *name, DWORD flags, HCEESECTION *section) { short sectionIdx; return getSectionCreate (name, flags, (CeeSection **)section, §ionIdx); }
STDMETHODIMP CCeeGen::GetSectionCreate ( const char *name, DWORD flags, HCEESECTION *section) { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; short sectionIdx; hr = getSectionCreate (name, flags, (CeeSection **)section, §ionIdx); END_ENTRYPOINT_NOTHROW; return hr; }
// Create the COM header - it goes at front of .meta section // Need to do this before the meta data is copied in, but don't do at // the same time because may not have metadata HRESULT CCeeGen::allocateCorHeader() { HRESULT hr = S_OK; CeeSection *corHeaderSection; if (m_corHdrIdx < 0) { hr = getSectionCreate(".text0", sdExecute, &corHeaderSection, &m_corHdrIdx); TESTANDRETURNHR(hr); } m_corHeaderOffset = corHeaderSection->dataLen(); m_corHeader = (IMAGE_COR20_HEADER*)corHeaderSection->getBlock(sizeof(IMAGE_COR20_HEADER)); if (! m_corHeader) return E_OUTOFMEMORY; memset(m_corHeader, 0, sizeof(IMAGE_COR20_HEADER)); return S_OK; }
// IAT must be first in its section, so have code here to allocate it up front // prior to knowing other info such as if dll or not. This won't work if have > 1 // function imported, but we'll burn that bridge when we get to it. HRESULT CeeFileGenWriter::allocateIAT() { m_dllCount = 1; m_iDataDlls = (IDataDllInfo *)malloc(m_dllCount * sizeof(IDataDllInfo)); if (m_iDataDlls == 0) { return E_OUTOFMEMORY; } memset(m_iDataDlls, '\0', m_dllCount * sizeof(IDataDllInfo)); m_iDataDlls[0].m_name = "mscoree.dll"; m_iDataDlls[0].m_numMethods = 1; m_iDataDlls[0].m_methodName = (char **)malloc(m_iDataDlls[0].m_numMethods * sizeof(char *)); if (! m_iDataDlls[0].m_methodName) { return E_OUTOFMEMORY; } m_iDataDlls[0].m_methodName[0] = NULL; int iDataSizeIAT = 0; for (int i=0; i < m_dllCount; i++) { m_iDataDlls[i].m_iatOffset = iDataSizeIAT; iDataSizeIAT += (m_iDataDlls[i].m_numMethods + 1) * sizeof(IMAGE_THUNK_DATA); } HRESULT hr = getSectionCreate(".text0", sdExecute, &m_iDataSectionIAT); TESTANDRETURNHR(hr); m_iDataOffsetIAT = m_iDataSectionIAT->dataLen(); _ASSERTE(m_iDataOffsetIAT == 0); m_iDataIAT = m_iDataSectionIAT->getBlock(iDataSizeIAT); if (! m_iDataIAT) { return E_OUTOFMEMORY; } memset(m_iDataIAT, '\0', iDataSizeIAT); // Don't set the IAT directory entry yet, since we may not actually end up doing // an emitExeMain. return S_OK; } // HRESULT CeeFileGenWriter::allocateIAT()
HRESULT CCeeGen::emitMetaData(IMetaDataEmit *emitter, CeeSection* section, DWORD offset, BYTE* buffer, unsigned buffLen) { HRESULT hr; if (! m_fTokenMapSupported) { IUnknown *pMapTokenIface; hr = getMapTokenIface(&pMapTokenIface, emitter); _ASSERTE(SUCCEEDED(hr)); // Set a callback for token remap and save the tokens which change. hr = emitter->SetHandler(pMapTokenIface); _ASSERTE(SUCCEEDED(hr)); } // generate the metadata IStream *metaStream; int rc = CreateStreamOnHGlobal(NULL, TRUE, &metaStream); _ASSERTE(rc == S_OK); hr = emitter->SaveToStream(metaStream, 0); _ASSERTE(SUCCEEDED(hr)); // get size of stream and get sufficient storage for it if (section == 0) { section = &getMetaSection(); STATSTG statStg; rc = metaStream->Stat(&statStg, STATFLAG_NONAME); _ASSERTE(rc == S_OK); buffLen = statStg.cbSize.u.LowPart; if(m_objSwitch) { CeeSection* pSect; DWORD flags = IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_ALIGN_1BYTES; // 0x00100A00 hr = getSectionCreate(".cormeta",flags,&pSect,&m_metaIdx); } buffer = (BYTE *)section->getBlock(buffLen, sizeof(DWORD)); TESTANDRETURN(buffer, E_OUTOFMEMORY); offset = getMetaSection().dataLen() - buffLen; } // reset seek pointer and read from stream LARGE_INTEGER disp = { {0, 0} }; rc = metaStream->Seek(disp, STREAM_SEEK_SET, NULL); _ASSERTE(rc == S_OK); ULONG metaDataLen; rc = metaStream->Read(buffer, buffLen+1, &metaDataLen); // +1 so assert below will fire. _ASSERTE(metaDataLen <= buffLen); metaStream->Release(); if (! m_fTokenMapSupported) { // Remove the handler that we set hr = emitter->SetHandler(NULL); TESTANDRETURNHR(hr); } // Set meta virtual address to offset of metadata within .meta, and // and add a reloc for this offset, which will get turned // into an rva when the pewriter writes out the file. m_corHeader->MetaData.VirtualAddress = VAL32(offset); getCorHeaderSection().addSectReloc(m_corHeaderOffset + offsetof(IMAGE_COR20_HEADER, MetaData), *section, srRelocAbsolute); m_corHeader->MetaData.Size = VAL32(metaDataLen); return S_OK; }
HRESULT CCeeGen::emitMetaData(IMetaDataEmit *emitter, CeeSection* section, DWORD offset, BYTE* buffer, unsigned buffLen) { HRESULT hr = S_OK; ReleaseHolder<IStream> metaStream(NULL); IfFailRet((HRESULT)CreateStreamOnHGlobal(NULL, TRUE, &metaStream)); if (! m_fTokenMapSupported) { IUnknown *pMapTokenIface; IfFailGoto(getMapTokenIface(&pMapTokenIface, emitter), Exit); // Set a callback for token remap and save the tokens which change. IfFailGoto(emitter->SetHandler(pMapTokenIface), Exit); } // generate the metadata IfFailGoto(emitter->SaveToStream(metaStream, 0), Exit); // get size of stream and get sufficient storage for it if (section == 0) { section = &getMetaSection(); STATSTG statStg; IfFailGoto((HRESULT)(metaStream->Stat(&statStg, STATFLAG_NONAME)), Exit); buffLen = statStg.cbSize.u.LowPart; if(m_objSwitch) { CeeSection* pSect; DWORD flags = IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_ALIGN_1BYTES; // 0x00100A00 IfFailGoto(getSectionCreate(".cormeta",flags,&pSect,&m_metaIdx), Exit); } buffer = (BYTE *)section->getBlock(buffLen, sizeof(DWORD)); IfNullGoto(buffer, Exit); offset = getMetaSection().dataLen() - buffLen; } else { _ASSERTE(buffer[buffLen-1] || true); // Dereference 'buffer' _ASSERTE(section->computeOffset(PCHAR(buffer)) == offset); } // reset seek pointer and read from stream { LARGE_INTEGER disp = { {0, 0} }; IfFailGoto((HRESULT)metaStream->Seek(disp, STREAM_SEEK_SET, NULL), Exit); } ULONG metaDataLen; IfFailGoto((HRESULT)metaStream->Read(buffer, buffLen+1, &metaDataLen), Exit); _ASSERTE(metaDataLen <= buffLen); // Set meta virtual address to offset of metadata within .meta, and // and add a reloc for this offset, which will get turned // into an rva when the pewriter writes out the file. m_corHeader->MetaData.VirtualAddress = VAL32(offset); getCorHeaderSection().addSectReloc(m_corHeaderOffset + offsetof(IMAGE_COR20_HEADER, MetaData), *section, srRelocAbsolute); m_corHeader->MetaData.Size = VAL32(metaDataLen); Exit: if (! m_fTokenMapSupported) { // Remove the handler that we set hr = emitter->SetHandler(NULL); } #ifdef _DEBUG if (FAILED(hr) && hr != E_OUTOFMEMORY) _ASSERTE(!"Unexpected Failure"); #endif return hr; }