in src/InstrumentationEngine/AssemblyInjector.cpp [529:762]
HRESULT MicrosoftInstrumentationEngine::AssemblyInjector::ImportMethodDef(_In_ mdMethodDef sourceMethodDef, _Out_ mdMethodDef *pTargetMethodDef)
{
HRESULT hr = S_OK;
IfFalseRet(sourceMethodDef != mdTokenNil && sourceMethodDef != mdMethodDefNil, E_FAIL);
TokenMap::const_iterator itr = m_methodDefMap.find(sourceMethodDef);
if (itr != m_methodDefMap.end())
{
*pTargetMethodDef = itr->second;
return hr;
}
CLogging::XmlDumpHelper dumpLogHelper(L"ImportMethodDef", 1);
dumpLogHelper.WriteUlongNode(L"token", sourceMethodDef);
mdTypeDef tkClass = mdTypeDefNil;
WCHAR szName[MAX_NAME] = { 0 };
ULONG cchName = 0;
DWORD dwAttr = 0;
PCCOR_SIGNATURE pvSigBlob = nullptr;
ULONG cbSigBlob = 0;
ULONG ulCodeRVA = 0;
DWORD dwImplFlags = 0;
IfFailRet(m_pSourceImport->GetMethodProps(sourceMethodDef,
&tkClass,
szName,
_countof(szName),
&cchName,
&dwAttr,
&pvSigBlob,
&cbSigBlob,
&ulCodeRVA,
&dwImplFlags));
dumpLogHelper.WriteStringNode(L"Name", szName);
dumpLogHelper.WriteUlongNode(L"Class", tkClass);
mdTypeDef targetTypeDef = mdTypeDefNil;
IfFailRet(ImportTypeDef(tkClass, &targetTypeDef));
IfFailRet(ConvertNonTypeSignatureCached(&pvSigBlob, &cbSigBlob));
//this type might already have method def if type was merged. Use existing methods in this situation
HRESULT hrFound = m_pTargetImport->FindMethod(targetTypeDef, szName, pvSigBlob, cbSigBlob, pTargetMethodDef);
if (hrFound == CLDB_E_RECORD_NOTFOUND)
{
IfFailRet(m_pTargetEmit->DefineMethod(targetTypeDef,
szName,
dwAttr,
pvSigBlob,
cbSigBlob,
0,
dwImplFlags,
pTargetMethodDef));
}
else if (FAILED(hrFound))
{
IfFailRet(hrFound);
}
else
{
dumpLogHelper.WriteStringNode(L"UseExisting", L"true");
}
m_methodDefMap[sourceMethodDef] = *pTargetMethodDef;
dumpLogHelper.WriteUlongNode(L"targetToken", *pTargetMethodDef);
CMetadataEnumCloser<IMetaDataImport2> spHCorEnum(m_pSourceImport, nullptr);
mdParamDef curSourceParam = mdParamDefNil;
while (S_OK == (hr = m_pSourceImport->EnumParams(spHCorEnum.Get(), sourceMethodDef, &curSourceParam, 1, nullptr)))
{
mdParamDef curTargetParam = mdParamDefNil;
IfFailRet(ImportParam(curSourceParam, &curTargetParam));
}
IfFailRet(hr);
if ((dwAttr & mdPinvokeImpl) != 0)
{
DWORD dwMappingFlags = 0;
WCHAR szImportName[MAX_NAME] = { 0 };
ULONG cchImportName = 0;
mdModuleRef sourceImportDll = mdModuleRefNil;
IfFailRet(m_pSourceImport->GetPinvokeMap(sourceMethodDef,
&dwMappingFlags,
szImportName,
_countof(szImportName),
&cchImportName,
&sourceImportDll));
mdModuleRef targetImportDll = mdModuleRefNil;
IfFailRet(ImportModuleRef(sourceImportDll, &targetImportDll));
IfFailRet(m_pTargetEmit->DefinePinvokeMap(*pTargetMethodDef, dwMappingFlags, szImportName, targetImportDll));
}
spHCorEnum.Reset(nullptr);
mdGenericParam curSourceGenericParam = mdGenericParamNil;
while (S_OK == (hr = m_pSourceImport->EnumGenericParams(spHCorEnum.Get(), sourceMethodDef, &curSourceGenericParam, 1, nullptr)))
{
mdGenericParam targetGenericParam = mdGenericParamNil;
IfFailRet(ImportGenericParam(curSourceGenericParam, &targetGenericParam));
}
IfFailRet(hr);
if (ulCodeRVA != 0)
{
VOID* pSourceCode = (BYTE*)m_pSourceImageBaseAddress + ulCodeRVA; // lgtm[cpp/suspicious-pointer-scaling-char] lgtm[cpp/incorrect-pointer-scaling-char] lgtm[cpp/suspicious-pointer-scaling]
const IMAGE_COR_ILMETHOD_TINY* pSourceCodeTinyHeader = (IMAGE_COR_ILMETHOD_TINY*)pSourceCode;
const IMAGE_COR_ILMETHOD_FAT* pSourceCodeFatHeader = (IMAGE_COR_ILMETHOD_FAT*)pSourceCode;
bool isTinyHeader = ((pSourceCodeTinyHeader->Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat);
ULONG ilCodeSize = 0;
ULONG headerSize = 0;
ULONG ehClauseHeaderRVA = 0;
IMAGE_COR_ILMETHOD_SECT_FAT* pFatEHHeader = nullptr;
IMAGE_COR_ILMETHOD_SECT_SMALL* pSmallEHHeader = nullptr;
ULONG totalCodeBlobSize = 0;
if (isTinyHeader)
{
ilCodeSize = (((unsigned)pSourceCodeTinyHeader->Flags_CodeSize) >> (CorILMethod_FormatShift - 1));
headerSize = sizeof(IMAGE_COR_ILMETHOD_TINY);
totalCodeBlobSize = ilCodeSize + headerSize;
}
else
{
ilCodeSize = pSourceCodeFatHeader->CodeSize;
// IMAGE_COR_ILMETHOD_FAT->Size represents size in DWords of this structure (currently 3) - see cor.h for details
headerSize = pSourceCodeFatHeader->Size * 4;
if ((pSourceCodeFatHeader->Flags & CorILMethod_MoreSects) == 0)
{
totalCodeBlobSize = ilCodeSize + headerSize;
}
else
{
// EH section starts at the 4 byte aligned address after the code
ehClauseHeaderRVA = ((ulCodeRVA + headerSize + ilCodeSize - 1) & ~3) + 4;
VOID* pEHSectionHeader = (BYTE*)m_pSourceImageBaseAddress + ehClauseHeaderRVA; // lgtm[cpp/suspicious-pointer-scaling-char] lgtm[cpp/incorrect-pointer-scaling-char] lgtm[cpp/suspicious-pointer-scaling]
BYTE kind = *(BYTE*)pEHSectionHeader;
ULONG dataSize = 0;
if (kind & CorILMethod_Sect_FatFormat)
{
pFatEHHeader = (IMAGE_COR_ILMETHOD_SECT_FAT*)pEHSectionHeader;
dataSize = pFatEHHeader->DataSize;
}
else
{
pSmallEHHeader = (IMAGE_COR_ILMETHOD_SECT_SMALL*)pEHSectionHeader;
dataSize = pSmallEHHeader->DataSize;
}
// take the difference between the RVAs to ensure we account for the padding
// bytes between the end of the IL code and the start of the EH clauses
totalCodeBlobSize = (ehClauseHeaderRVA - ulCodeRVA) + dataSize;
}
}
VOID* pTargetCode = m_pTargetMethodMalloc->Alloc(totalCodeBlobSize);
//IfNullRetOOM(pTargetCode);
// convert header
memcpy_s(pTargetCode, headerSize, pSourceCode, headerSize);
if (!isTinyHeader)
{
IMAGE_COR_ILMETHOD_FAT* pTargetCodeFatHeader = (IMAGE_COR_ILMETHOD_FAT*)pTargetCode;
IfFailRet(ImportLocalVarSig(pTargetCodeFatHeader->LocalVarSigTok, &(pTargetCodeFatHeader->LocalVarSigTok)));
}
// convert IL code
IfFailRet(ConvertILCode((BYTE*)pSourceCode + headerSize, (BYTE*)pTargetCode + headerSize, ilCodeSize));
//convert EH
if (pFatEHHeader != nullptr)
{
IMAGE_COR_ILMETHOD_SECT_FAT* pTargetEHHeader = (IMAGE_COR_ILMETHOD_SECT_FAT*)((BYTE*)pTargetCode + (ehClauseHeaderRVA - ulCodeRVA));
pTargetEHHeader->Kind = pFatEHHeader->Kind;
pTargetEHHeader->DataSize = pFatEHHeader->DataSize;
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pSourceEHClause = (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)(pFatEHHeader + 1); // lgtm[cpp/suspicious-pointer-scaling]
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pTargetEHClause = (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)(pTargetEHHeader + 1); // lgtm[cpp/suspicious-pointer-scaling]
int numClauses = (pTargetEHHeader->DataSize - 4) / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT);
for (int i = 0; i < numClauses; i++)
{
pTargetEHClause->Flags = pSourceEHClause->Flags;
pTargetEHClause->TryOffset = pSourceEHClause->TryOffset;
pTargetEHClause->TryLength = pSourceEHClause->TryLength;
pTargetEHClause->HandlerOffset = pSourceEHClause->HandlerOffset;
pTargetEHClause->HandlerLength = pSourceEHClause->HandlerLength;
if ((pSourceEHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) != 0)
{
IfFailRet(ConvertToken(pSourceEHClause->ClassToken, (mdToken*)&(pTargetEHClause->ClassToken)));
}
else
{
pTargetEHClause->FilterOffset = pSourceEHClause->FilterOffset;
}
pTargetEHClause++;
pSourceEHClause++;
}
}
else if (pSmallEHHeader != nullptr)
{
IMAGE_COR_ILMETHOD_SECT_SMALL* pTargetEHHeader = (IMAGE_COR_ILMETHOD_SECT_SMALL*)((BYTE*)pTargetCode + (ehClauseHeaderRVA - ulCodeRVA));
pTargetEHHeader->Kind = pSmallEHHeader->Kind;
pTargetEHHeader->DataSize = pSmallEHHeader->DataSize;
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* pSourceEHClause = (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)(pSmallEHHeader + 1); // lgtm[cpp/suspicious-pointer-scaling]
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* pTargetEHClause = (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)(pTargetEHHeader + 1); // lgtm[cpp/suspicious-pointer-scaling]
int numClauses = (pSmallEHHeader->DataSize - 4) / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL);
for (int i = 0; i < numClauses; i++)
{
pTargetEHClause->Flags = pSourceEHClause->Flags;
pTargetEHClause->TryOffset = pSourceEHClause->TryOffset;
pTargetEHClause->TryLength = pSourceEHClause->TryLength;
pTargetEHClause->HandlerOffset = pSourceEHClause->HandlerOffset;
pTargetEHClause->HandlerLength = pSourceEHClause->HandlerLength;
if ((pSourceEHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) != 0)
{
IfFailRet(ConvertToken(pSourceEHClause->ClassToken, (mdToken*)&(pTargetEHClause->ClassToken)));
}
else
{
pTargetEHClause->FilterOffset = pSourceEHClause->FilterOffset;
}
pTargetEHClause++;
pSourceEHClause++;
}
}
//because the metadata record wasn't created with an RVA, this connects the methodDef to the code
IfFailRet(m_pProfilerInfo->SetILFunctionBody((ModuleID)m_pTargetImage, *pTargetMethodDef, (LPCBYTE)pTargetCode));
}
else
{
}
return hr;
}