HRESULT CeeFileGenWriter::link() { HRESULT hr = checkForErrors(); if (! SUCCEEDED(hr)) return hr; m_corHeader->Resources.VirtualAddress = VAL32(m_dwManifestRVA); m_corHeader->Resources.Size = VAL32(m_dwManifestSize); m_corHeader->StrongNameSignature.VirtualAddress = VAL32(m_dwStrongNameRVA); m_corHeader->StrongNameSignature.Size = VAL32(m_dwStrongNameSize); m_corHeader->VTableFixups.VirtualAddress = VAL32(m_dwVTableRVA); m_corHeader->VTableFixups.Size = VAL32(m_dwVTableSize); getPEWriter().setCharacteristics( //#ifndef _WIN64 IMAGE_FILE_32BIT_MACHINE | //#endif IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED ); m_corHeader->cb = VAL32(sizeof(IMAGE_COR20_HEADER)); m_corHeader->MajorRuntimeVersion = VAL16(COR_VERSION_MAJOR); m_corHeader->MinorRuntimeVersion = VAL16(COR_VERSION_MINOR); if (m_dllSwitch) getPEWriter().setCharacteristics(IMAGE_FILE_DLL); if (m_objSwitch) getPEWriter().clearCharacteristics(IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LOCAL_SYMS_STRIPPED); m_corHeader->Flags = VAL32(m_comImageFlags); m_corHeader->EntryPointToken = VAL32(m_entryPoint); _ASSERTE(TypeFromToken(m_entryPoint) == mdtMethodDef || m_entryPoint == mdTokenNil || TypeFromToken(m_entryPoint) == mdtFile); setDirectoryEntry(getCorHeaderSection(), IMAGE_DIRECTORY_ENTRY_COMHEADER, sizeof(IMAGE_COR20_HEADER), m_corHeaderOffset); if ((m_comImageFlags & COMIMAGE_FLAGS_IL_LIBRARY) == 0 && !m_linked && !m_objSwitch) { hr = emitExeMain(); if (FAILED(hr)) return hr; } m_linked = true; IfFailRet(getPEWriter().link()); return S_OK; } // HRESULT CeeFileGenWriter::link()
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; }