in src/InstrumentationEngine/Instruction.cpp [1510:1635]
HRESULT MicrosoftInstrumentationEngine::CInstruction::GetSignatureInfoFromCallToken(
_In_ IMethodInfo* pMethodInfo,
_Out_ PCCOR_SIGNATURE* ppSig,
_Out_ DWORD* pSigLength,
_Out_ CorCallingConvention* pCallConv,
_Out_ DWORD* pParameterCount,
_Out_ CorElementType* pRetTypeElementType
)
{
HRESULT hr = S_OK;
ILOperandType operandType;
IfFailRet(GetOperandType(&operandType));
if (operandType != ILOperandType_Token)
{
CLogging::LogError(_T("CInstruction::GetStackImpact - Unexpected il operand type"));
return E_FAIL;
}
COperandInstruction* pOperandThis = (COperandInstruction*)this;
mdToken callToken = mdTokenNil;
IfFailRet(pOperandThis->GetOperandValue(sizeof(mdToken), (BYTE*)&callToken));
CComPtr<IModuleInfo> pModuleInfo;
IfFailRet(pMethodInfo->GetModuleInfo(&pModuleInfo));
CComPtr<IMetaDataImport> pMetaDataImport;
IfFailRet(pModuleInfo->GetMetaDataImport((IUnknown**)&pMetaDataImport));
// if the callToken is a methodSpec, get the parent MethodDef/MethodRef
// to later retrieve the actual method signature
if (TypeFromToken(callToken) == mdtMethodSpec)
{
CComPtr<IMetaDataImport2> pMetaDataImport2;
IfFailRet(pMetaDataImport->QueryInterface(IID_IMetaDataImport2, (LPVOID*)&pMetaDataImport2));
mdToken parentCallToken = mdTokenNil;
IfFailRet(pMetaDataImport2->GetMethodSpecProps(
callToken,
&parentCallToken,
NULL,
NULL
));
callToken = parentCallToken;
}
PCCOR_SIGNATURE pSigUntouched = nullptr;
PCCOR_SIGNATURE pSig = nullptr;
ULONG sigLength = 0;
// Get the signature for the method token
if (TypeFromToken(callToken) == mdtMemberRef)
{
mdToken targetToken = mdTokenNil;
IfFailRet(pMetaDataImport->GetMemberRefProps(
callToken,
nullptr,
nullptr,
0,
nullptr,
&pSig,
&sigLength
));
}
else if (TypeFromToken(callToken) == mdtMethodDef)
{
IfFailRet(pMetaDataImport->GetMemberProps(
callToken,
nullptr,
nullptr,
0,
nullptr,
nullptr,
&pSig,
&sigLength,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
));
}
else if (TypeFromToken(callToken) == mdtSignature)
{
IfFailRet(pMetaDataImport->GetSigFromToken(
callToken,
&pSig,
&sigLength
));
}
pSigUntouched = pSig;
// get a method signature, which looks like this: "calling Conv" + "argument Cnt" + "return Type" + "arg1" + "arg2" + ...
CorCallingConvention callConv = IMAGE_CEE_CS_CALLCONV_MAX; // = 0x10 - first invalid calling convention;
pSig += CorSigUncompressData(pSig, (ULONG *)&callConv);
if ((callConv == IMAGE_CEE_CS_CALLCONV_MAX) || (callConv == IMAGE_CEE_CS_CALLCONV_FIELD))
{
CLogging::LogError(_T("Unexpected calling convention on method"));
return E_UNEXPECTED;
}
if (IsFlagSet(callConv, IMAGE_CEE_CS_CALLCONV_GENERIC))
{
DWORD dwGenericParameterCount;
// get the generic argument count
pSig += CorSigUncompressData(pSig, &dwGenericParameterCount);
}
ULONG parameterCount = 0;
// get the argument count
pSig += CorSigUncompressData(pSig, ¶meterCount);
CorElementType retTypeElementType;
pSig += CorSigUncompressData(pSig, (ULONG *)&retTypeElementType);
*ppSig = pSigUntouched;
*pSigLength = sigLength;
*pCallConv = callConv;
*pParameterCount = parameterCount;
*pRetTypeElementType = retTypeElementType;
return hr;
}