Hello Nadav
This is what I do:
[error checking etc removed]
_pCeeFileGen->CreateCeeFile(&_hCeeFile);
_pCeeFileGen->SetOutputFileName(_hCeeFile, fileName);
//call link so we can use GetSectionRVA
_pCeeFileGen->LinkCeeFile(_hCeeFile);
//get il section
HCEESECTION hSection;
_pCeeFileGen->GetIlSection (_hCeeFile, &hSection);
ULONG rva;
_pCeeFileGen->GetSectionRVA (hSection, &rva);
ULONG codeSize =0;
char* pBytes = NULL;
//get a new block just to get a pointer to the section, get 4 bytes for
DWORD alignement
_pCeeFileGen->GetSectionBlock (hSection, 4, 1,
reinterpret_cast<void**>(&pBytes));
unsigned int offset;
_pCeeFileGen->ComputeSectionOffset(hSection, pBytes, &offset);
//this copies all IL code into a buffer (_pILBuffer), see below
//also calls SetRVA for each method
GetILCode(&codeSize, rva + offset);
//get a new block large enough to hold IL Code (codezize - 4 bytes
//allocatd above)
char* pBytes2 = NULL;
_pCeeFileGen->GetSectionBlock (hSection, codeSize - 4, 1,
reinterpret_cast<void**>(&pBytes2));
//copy IL Code to section
memcpy(pBytes, _pILBuffer, codeSize);
_pCeeFileGen->EmitMetaDataEx(_hCeeFile, _pMetaDataEmit);
_pCeeFileGen->LinkCeeFile(_hCeeFile);
_pCeeFileGen->GenerateCeeFile(_hCeeFile);
_pCeeFileGen->DestroyCeeFile(&_hCeeFile);
delete[] _pILBuffer;
//==== GetILCode
HRESULT CAssemblyWriter::GetILCode(ULONG* pCodeSize, unsigned int offset) {
HRESULT hr = NULL;
//HACK: Allocate enough memory to hold entire .text section
int bufferSize = _pReader->GetPEFile()->_sizeOfTextSection;
_pILBuffer = new BYTE[bufferSize];
ZeroMemory(_pILBuffer, bufferSize);
int codeSize = 0;
//get all method of all types and add ILCode to buffer
std::vector<CTypeDef*> typeDefs = _pReader->_typeDefs;
for (unsigned int ii=0; ii < _pReader->_typeDefs.size(); ii++) {
CTypeDef* pType = _pReader->_typeDefs[ii];
for (unsigned jj = 0; jj < pType->_methodDefs.size(); jj++) {
CMethodDef* pMethod = pType->_methodDefs[jj];
if (pMethod->_codeSize > 0) {
int methodSize = pMethod->_codeSize + pMethod->_codeHeaderSize;
memcpy(_pILBuffer + codeSize, pMethod->_pCodeHeader, methodSize);
hr = _pMetaDataEmit->SetRVA(pMethod->_token, offset + codeSize);
if (!SUCCEEDED(hr)) {
return hr;
}
//HACK
if (pMethod->_name == L"Main") {
hr = _pCeeFileGen->SetEntryPoint(_hCeeFile, pMethod->_token);
if (!SUCCEEDED(hr)) {
return hr;
}
}
codeSize += methodSize;
codeSize = _ALIGN4(codeSize);
if (pMethod->_pStartExtraSections) {
memcpy(_pILBuffer + codeSize, pMethod->_pStartExtraSections,
pMethod->_sizeExtraSections);
codeSize += pMethod->_sizeExtraSections;
codeSize = _ALIGN4(codeSize);
}
}
}
}
*pCodeSize = codeSize;
return hr;
}
as you can see, I have all TypeDefs and methods in std::vectors
pMethod->_codeSize is the size of the IL Code and pMethod->_pCodeHeader
points to the start of the ILCode Header (CorILMethod_SmallFormat etc)
pMethod->_pStartExtraSections points to the extrasections like exception
handling if present
(
http://msdn.microsoft.com/msdnmag/issues/03/09/NETProfilingAPI/default.aspx)
to translate the rva obtained from GetMethodProps I call
ImageRvaToVa(pNTHeaders, pBase, rva, NULL);
hth