尝试通过ICorProfilerCallback接口修改System.String.Concat方法的IL,但是出错了
I tried to modify the IL of the System.String.Concat method through the ICorProfilerCallback interface, but something went wrong
我尝试通过ICorProfilerCallback接口修改System.String.Concat方法的IL,在方法执行前添加自己的跟踪代码。
我修改了其他方法的IL,添加了跟踪代码,没有任何问题。编译通过后可以运行.
....
if (!isStatic) {
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexMethodTrace); //stloc
reWriterWrapper.LoadNull(); //Ldnull
reWriterWrapper.StLocal(indexEx);
reWriterWrapper.LoadNull();
reWriterWrapper.StLocal(indexRet);
ILInstr* pTryStartInstr = reWriterWrapper.CallMember0(getInstanceMemberRef, false);
reWriterWrapper.Cast(traceAgentTypeRef); //castclass
reWriterWrapper.LoadToken(functionInfo.type.id);//ldtoken
reWriterWrapper.CallMember(moduleMetaInfo->getTypeFromHandleToken, false);
reWriterWrapper.LoadArgument(0); //ldarg 0
auto argNum = functionInfo.signature.NumberOfArguments();
reWriterWrapper.CreateArray(objectTypeRef, argNum);
auto arguments = functionInfo.signature.GetMethodArguments();
for (unsigned i = 0; i < argNum; i++) {
reWriterWrapper.BeginLoadValueIntoArray(i);
reWriterWrapper.LoadArgument(i + 1);//ldarg
auto argTypeFlags = arguments[i].GetTypeFlags(elementType);
if (argTypeFlags & TypeFlagByRef) {
reWriterWrapper.LoadIND(elementType); //ldind 中
}
if (argTypeFlags & TypeFlagBoxedType) {
auto tok = arguments[i].GetTypeTok(pEmit, corLibAssemblyRef); /
if (tok == mdTokenNil) {
return S_OK;
}
reWriterWrapper.Box(tok);
}
reWriterWrapper.EndLoadValueIntoArray(); //stelem_ref
}
reWriterWrapper.LoadInt32((INT32)function_token); //ldc_i4
reWriterWrapper.CallMember(beforeMemberRef, true); // call
reWriterWrapper.Cast(methodTraceTypeRef); //Castclass
reWriterWrapper.StLocal(rewriter.cNewLocals - 1); //STLOC
ILInstr* pRetInstr = pReWriter->NewILInstr();
pRetInstr->m_opcode = CEE_RET;
pReWriter->InsertAfter(pReWriter->GetILList()->m_pPrev, pRetInstr);
bool isVoidMethod = (retTypeFlags & TypeFlagVoid) > 0;
auto ret = functionInfo.signature.GetRet();
bool retIsBoxedType = false;
mdToken retTypeTok;
if (!isVoidMethod) {
retTypeTok = ret.GetTypeTok(pEmit, corLibAssemblyRef);
if (ret.GetTypeFlags(elementType) & TypeFlagBoxedType) {
retIsBoxedType = true;
}
}
reWriterWrapper.SetILPosition(pRetInstr);
reWriterWrapper.StLocal(indexEx); //stloc
ILInstr* pRethrowInstr = reWriterWrapper.Rethrow(); //Rethrow
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
ILInstr* pNewInstr = pReWriter->NewILInstr(); //Brfalse
pNewInstr->m_opcode = CEE_BRFALSE_S;
pReWriter->InsertBefore(pRetInstr, pNewInstr);
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
reWriterWrapper.LoadLocal(indexRet);//ldloc
reWriterWrapper.LoadLocal(indexEx); //ldloc
reWriterWrapper.CallMember(endMemberRef, true); // call [
ILInstr* pEndFinallyInstr = reWriterWrapper.EndFinally();
pNewInstr->m_pTarget = pEndFinallyInstr;
if (!isVoidMethod) {
reWriterWrapper.LoadLocal(indexRet);//ldloc
if (retIsBoxedType) {
reWriterWrapper.UnboxAny(retTypeTok);
}
else {
reWriterWrapper.Cast(retTypeTok);
}
}
for (ILInstr* pInstr = pReWriter->GetILList()->m_pNext; pInstr != pReWriter->GetILList(); pInstr = pInstr->m_pNext) {
switch (pInstr->m_opcode)
{
case CEE_RET:
{
if (pInstr != pRetInstr) {
if (!isVoidMethod) {
reWriterWrapper.SetILPosition(pInstr);
if (retIsBoxedType) {
reWriterWrapper.Box(retTypeTok);
}
reWriterWrapper.StLocal(indexRet); //ldloc
}
pInstr->m_opcode = CEE_LEAVE_S; //Leave_S
pInstr->m_pTarget = pEndFinallyInstr->m_pNext;
}
break;
}
default:
break;
}
}
EHClause exClause{};
exClause.m_Flags = COR_ILEXCEPTION_CLAUSE_NONE;
exClause.m_pTryBegin = pTryStartInstr;
exClause.m_pTryEnd = pRethrowInstr->m_pPrev;
exClause.m_pHandlerBegin = pRethrowInstr->m_pPrev;
exClause.m_pHandlerEnd = pRethrowInstr;
exClause.m_ClassToken = exTypeRef;
EHClause finallyClause{};
finallyClause.m_Flags = COR_ILEXCEPTION_CLAUSE_FINALLY;
finallyClause.m_pTryBegin = pTryStartInstr;
finallyClause.m_pTryEnd = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerBegin = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerEnd = pEndFinallyInstr;
auto m_pEHNew = new EHClause[rewriter.m_nEH + 2];
for (unsigned i = 0; i < rewriter.m_nEH; i++) {
m_pEHNew[i] = rewriter.m_pEH[i];
}
rewriter.m_nEH += 2;
m_pEHNew[rewriter.m_nEH - 2] = exClause;
m_pEHNew[rewriter.m_nEH - 1] = finallyClause;
rewriter.m_pEH = m_pEHNew;
}
else
{
//static method
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexMethodTrace); //stloc
reWriterWrapper.LoadNull(); //Ldnull
reWriterWrapper.StLocal(indexEx); //stloc
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexRet);
ILInstr* pTryStartInstr = reWriterWrapper.CallMember0(getInstanceMemberRef, false);
reWriterWrapper.Cast(traceAgentTypeRef); //castclass
reWriterWrapper.LoadNull(); //ldstr
reWriterWrapper.LoadNull();
auto argNum = functionInfo.signature.NumberOfArguments();
reWriterWrapper.CreateArray(objectTypeRef, argNum); //newarr
auto arguments = functionInfo.signature.GetMethodArguments();
for (unsigned i = 0; i < argNum; i++) {
reWriterWrapper.BeginLoadValueIntoArray(i);
reWriterWrapper.LoadArgument(i);//ldarg Static index 0
auto argTypeFlags = arguments[i].GetTypeFlags(elementType);
if (argTypeFlags & TypeFlagByRef) {
reWriterWrapper.LoadIND(elementType); //ldind
}
if (argTypeFlags & TypeFlagBoxedType) {
auto tok = arguments[i].GetTypeTok(pEmit, corLibAssemblyRef);
if (tok == mdTokenNil) {
return S_OK;
}
reWriterWrapper.Box(tok);
}
reWriterWrapper.EndLoadValueIntoArray(); //stelem_ref
}
reWriterWrapper.LoadInt32((INT32)function_token); //ldc_i4
reWriterWrapper.CallMember(beforeMemberRef, true); // call
reWriterWrapper.Cast(methodTraceTypeRef); //Castclass
reWriterWrapper.StLocal(rewriter.cNewLocals - 1); //STLOC
ILInstr* pRetInstr = pReWriter->NewILInstr();/
pRetInstr->m_opcode = CEE_RET;
pReWriter->InsertAfter(pReWriter->GetILList()->m_pPrev, pRetInstr);
bool isVoidMethod = (retTypeFlags & TypeFlagVoid) > 0;
auto ret = functionInfo.signature.GetRet();
bool retIsBoxedType = false;
mdToken retTypeTok;
if (!isVoidMethod) {
retTypeTok = ret.GetTypeTok(pEmit, corLibAssemblyRef);
if (ret.GetTypeFlags(elementType) & TypeFlagBoxedType) {
retIsBoxedType = true;
}
}
reWriterWrapper.SetILPosition(pRetInstr);
reWriterWrapper.StLocal(indexEx); //stloc
ILInstr* pRethrowInstr = reWriterWrapper.Rethrow(); //Rethrow
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
ILInstr* pNewInstr = pReWriter->NewILInstr(); //Brfalse
pNewInstr->m_opcode = CEE_BRFALSE_S;
pReWriter->InsertBefore(pRetInstr, pNewInstr);
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
reWriterWrapper.LoadLocal(indexRet);//ldloc
reWriterWrapper.LoadLocal(indexEx); //ldloc
reWriterWrapper.CallMember(endMemberRef, true); // call
ILInstr* pEndFinallyInstr = reWriterWrapper.EndFinally(); //Endfinally
pNewInstr->m_pTarget = pEndFinallyInstr;
if (!isVoidMethod) {
reWriterWrapper.LoadLocal(indexRet);//ldloc
if (retIsBoxedType) {
reWriterWrapper.UnboxAny(retTypeTok); // Unbox_Any
}
else {
reWriterWrapper.Cast(retTypeTok);
}
}
for (ILInstr* pInstr = pReWriter->GetILList()->m_pNext; pInstr != pReWriter->GetILList(); pInstr = pInstr->m_pNext) {
switch (pInstr->m_opcode)
{
case CEE_RET:
{
if (pInstr != pRetInstr) {
if (!isVoidMethod) {
reWriterWrapper.SetILPosition(pInstr);
if (retIsBoxedType) {
reWriterWrapper.Box(retTypeTok);
}
reWriterWrapper.StLocal(indexRet); //ldloc
}
pInstr->m_opcode = CEE_LEAVE_S; //Leave_S
pInstr->m_pTarget = pEndFinallyInstr->m_pNext;
}
break;
}
default:
break;
}
}
EHClause exClause{};
exClause.m_Flags = COR_ILEXCEPTION_CLAUSE_NONE;
exClause.m_pTryBegin = pTryStartInstr;
exClause.m_pTryEnd = pRethrowInstr->m_pPrev;
exClause.m_pHandlerBegin = pRethrowInstr->m_pPrev;
exClause.m_pHandlerEnd = pRethrowInstr;
exClause.m_ClassToken = exTypeRef;
EHClause finallyClause{};
finallyClause.m_Flags = COR_ILEXCEPTION_CLAUSE_FINALLY;
finallyClause.m_pTryBegin = pTryStartInstr;
finallyClause.m_pTryEnd = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerBegin = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerEnd = pEndFinallyInstr;
auto m_pEHNew = new EHClause[rewriter.m_nEH + 2];
for (unsigned i = 0; i < rewriter.m_nEH; i++) {
m_pEHNew[i] = rewriter.m_pEH[i];
}
rewriter.m_nEH += 2;
m_pEHNew[rewriter.m_nEH - 2] = exClause;
m_pEHNew[rewriter.m_nEH - 1] = finallyClause;
rewriter.m_pEH = m_pEHNew;
}
hr = rewriter.Export();
....
LocalSigCode
HRESULT ModifyLocalSig(CComPtr<IMetaDataImport2>& pImport, CComPtr<IMetaDataEmit2>& pEmit, ILRewriter& reWriter, mdTypeRef exTypeRef,mdTypeRef methodTraceTypeRef)
{
HRESULT hr;
PCCOR_SIGNATURE rgbOrigSig = NULL;
ULONG cbOrigSig = 0;
UNALIGNED INT32 temp = 0;
if (reWriter.m_tkLocalVarSig != mdTokenNil)
{
IfFailRet(pImport->GetSigFromToken(reWriter.m_tkLocalVarSig, &rgbOrigSig, &cbOrigSig));
const auto len = CorSigCompressToken(methodTraceTypeRef, &temp);
if(cbOrigSig - len > 0){
if(rgbOrigSig[cbOrigSig - len -1]== ELEMENT_TYPE_CLASS){
if (memcmp(&rgbOrigSig[cbOrigSig - len], &temp, len) == 0) {
return E_FAIL;
}
}
}
}
auto exTypeRefSize = CorSigCompressToken(exTypeRef, &temp);
auto methodTraceTypeRefSize = CorSigCompressToken(methodTraceTypeRef, &temp);
ULONG cbNewSize = cbOrigSig + 1 + 1 + methodTraceTypeRefSize + 1 + exTypeRefSize;
ULONG cOrigLocals;
ULONG cNewLocalsLen;
ULONG cbOrigLocals = 0;
if (cbOrigSig == 0) {
cbNewSize += 2;
reWriter.cNewLocals = 3;
cNewLocalsLen = CorSigCompressData(reWriter.cNewLocals, &temp);
}
else {
cbOrigLocals = CorSigUncompressData(rgbOrigSig + 1, &cOrigLocals);
reWriter.cNewLocals = cOrigLocals + 3;
cNewLocalsLen = CorSigCompressData(reWriter.cNewLocals, &temp);
cbNewSize += cNewLocalsLen - cbOrigLocals;
}
auto rgbNewSig = new COR_SIGNATURE[cbNewSize];
*rgbNewSig = IMAGE_CEE_CS_CALLCONV_LOCAL_SIG;
ULONG rgbNewSigOffset = 1;
memcpy(rgbNewSig + rgbNewSigOffset, &temp, cNewLocalsLen);
rgbNewSigOffset += cNewLocalsLen;
if (cbOrigSig > 0) {
const auto cbOrigCopyLen = cbOrigSig - 1 - cbOrigLocals;
memcpy(rgbNewSig + rgbNewSigOffset, rgbOrigSig + 1 + cbOrigLocals, cbOrigCopyLen);
rgbNewSigOffset += cbOrigCopyLen;
}
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_OBJECT;
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_CLASS;
exTypeRefSize = CorSigCompressToken(exTypeRef, &temp);
memcpy(rgbNewSig + rgbNewSigOffset, &temp, exTypeRefSize);
rgbNewSigOffset += exTypeRefSize;
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_CLASS;
methodTraceTypeRefSize = CorSigCompressToken(methodTraceTypeRef, &temp);
memcpy(rgbNewSig + rgbNewSigOffset, &temp, methodTraceTypeRefSize);
rgbNewSigOffset += methodTraceTypeRefSize;
IfFailRet(pEmit->GetTokenFromSig(&rgbNewSig[0], cbNewSize, &reWriter.m_tkLocalVarSig));
return S_OK;
}
修改方法模板:
//before fixing method
private Task DataRead(string a, int b)
{
return Task.Delay(10);
}
//After modification
private Task DataReadWrapper(string a, int b)
{
object ret = null;
Exception ex = null;
MethodTrace methodTrace = null;
try
{
methodTrace = (MethodTrace)((TraceAgent)TraceAgent.GetInstance())
.BeforeMethod(this.GetType(), this, new object[]{ a, b }, functiontoken);
ret = Task.Delay(10);
goto T;
}
catch (Exception e)
{
ex = e;
throw;
}
finally
{
if (methodTrace != null)
{
methodTrace.EndMethod(ret, ex);
}
}
T:
return (Task)ret;
}
错误:
Unhandled exception.
Cannot print exception string because Exception.ToString() failed.
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\inetpub\wwwroot\DotNetRangeCore\' failed to load coreclr. Exception message: CLR worker thread exited prematurely
如果我在其他方法中通过这段代码修改IL是没有问题的。比如:set_CommandText、System.Random.Next、System.Web.HttpContext.FinishPipelineRequest...
不知道为什么修改Concat会出错。
我通过更换解决了。如果这个IL修改后报错,我换成打包方式
我尝试通过ICorProfilerCallback接口修改System.String.Concat方法的IL,在方法执行前添加自己的跟踪代码。 我修改了其他方法的IL,添加了跟踪代码,没有任何问题。编译通过后可以运行.
....
if (!isStatic) {
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexMethodTrace); //stloc
reWriterWrapper.LoadNull(); //Ldnull
reWriterWrapper.StLocal(indexEx);
reWriterWrapper.LoadNull();
reWriterWrapper.StLocal(indexRet);
ILInstr* pTryStartInstr = reWriterWrapper.CallMember0(getInstanceMemberRef, false);
reWriterWrapper.Cast(traceAgentTypeRef); //castclass
reWriterWrapper.LoadToken(functionInfo.type.id);//ldtoken
reWriterWrapper.CallMember(moduleMetaInfo->getTypeFromHandleToken, false);
reWriterWrapper.LoadArgument(0); //ldarg 0
auto argNum = functionInfo.signature.NumberOfArguments();
reWriterWrapper.CreateArray(objectTypeRef, argNum);
auto arguments = functionInfo.signature.GetMethodArguments();
for (unsigned i = 0; i < argNum; i++) {
reWriterWrapper.BeginLoadValueIntoArray(i);
reWriterWrapper.LoadArgument(i + 1);//ldarg
auto argTypeFlags = arguments[i].GetTypeFlags(elementType);
if (argTypeFlags & TypeFlagByRef) {
reWriterWrapper.LoadIND(elementType); //ldind 中
}
if (argTypeFlags & TypeFlagBoxedType) {
auto tok = arguments[i].GetTypeTok(pEmit, corLibAssemblyRef); /
if (tok == mdTokenNil) {
return S_OK;
}
reWriterWrapper.Box(tok);
}
reWriterWrapper.EndLoadValueIntoArray(); //stelem_ref
}
reWriterWrapper.LoadInt32((INT32)function_token); //ldc_i4
reWriterWrapper.CallMember(beforeMemberRef, true); // call
reWriterWrapper.Cast(methodTraceTypeRef); //Castclass
reWriterWrapper.StLocal(rewriter.cNewLocals - 1); //STLOC
ILInstr* pRetInstr = pReWriter->NewILInstr();
pRetInstr->m_opcode = CEE_RET;
pReWriter->InsertAfter(pReWriter->GetILList()->m_pPrev, pRetInstr);
bool isVoidMethod = (retTypeFlags & TypeFlagVoid) > 0;
auto ret = functionInfo.signature.GetRet();
bool retIsBoxedType = false;
mdToken retTypeTok;
if (!isVoidMethod) {
retTypeTok = ret.GetTypeTok(pEmit, corLibAssemblyRef);
if (ret.GetTypeFlags(elementType) & TypeFlagBoxedType) {
retIsBoxedType = true;
}
}
reWriterWrapper.SetILPosition(pRetInstr);
reWriterWrapper.StLocal(indexEx); //stloc
ILInstr* pRethrowInstr = reWriterWrapper.Rethrow(); //Rethrow
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
ILInstr* pNewInstr = pReWriter->NewILInstr(); //Brfalse
pNewInstr->m_opcode = CEE_BRFALSE_S;
pReWriter->InsertBefore(pRetInstr, pNewInstr);
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
reWriterWrapper.LoadLocal(indexRet);//ldloc
reWriterWrapper.LoadLocal(indexEx); //ldloc
reWriterWrapper.CallMember(endMemberRef, true); // call [
ILInstr* pEndFinallyInstr = reWriterWrapper.EndFinally();
pNewInstr->m_pTarget = pEndFinallyInstr;
if (!isVoidMethod) {
reWriterWrapper.LoadLocal(indexRet);//ldloc
if (retIsBoxedType) {
reWriterWrapper.UnboxAny(retTypeTok);
}
else {
reWriterWrapper.Cast(retTypeTok);
}
}
for (ILInstr* pInstr = pReWriter->GetILList()->m_pNext; pInstr != pReWriter->GetILList(); pInstr = pInstr->m_pNext) {
switch (pInstr->m_opcode)
{
case CEE_RET:
{
if (pInstr != pRetInstr) {
if (!isVoidMethod) {
reWriterWrapper.SetILPosition(pInstr);
if (retIsBoxedType) {
reWriterWrapper.Box(retTypeTok);
}
reWriterWrapper.StLocal(indexRet); //ldloc
}
pInstr->m_opcode = CEE_LEAVE_S; //Leave_S
pInstr->m_pTarget = pEndFinallyInstr->m_pNext;
}
break;
}
default:
break;
}
}
EHClause exClause{};
exClause.m_Flags = COR_ILEXCEPTION_CLAUSE_NONE;
exClause.m_pTryBegin = pTryStartInstr;
exClause.m_pTryEnd = pRethrowInstr->m_pPrev;
exClause.m_pHandlerBegin = pRethrowInstr->m_pPrev;
exClause.m_pHandlerEnd = pRethrowInstr;
exClause.m_ClassToken = exTypeRef;
EHClause finallyClause{};
finallyClause.m_Flags = COR_ILEXCEPTION_CLAUSE_FINALLY;
finallyClause.m_pTryBegin = pTryStartInstr;
finallyClause.m_pTryEnd = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerBegin = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerEnd = pEndFinallyInstr;
auto m_pEHNew = new EHClause[rewriter.m_nEH + 2];
for (unsigned i = 0; i < rewriter.m_nEH; i++) {
m_pEHNew[i] = rewriter.m_pEH[i];
}
rewriter.m_nEH += 2;
m_pEHNew[rewriter.m_nEH - 2] = exClause;
m_pEHNew[rewriter.m_nEH - 1] = finallyClause;
rewriter.m_pEH = m_pEHNew;
}
else
{
//static method
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexMethodTrace); //stloc
reWriterWrapper.LoadNull(); //Ldnull
reWriterWrapper.StLocal(indexEx); //stloc
reWriterWrapper.LoadNull();// Ldnull
reWriterWrapper.StLocal(indexRet);
ILInstr* pTryStartInstr = reWriterWrapper.CallMember0(getInstanceMemberRef, false);
reWriterWrapper.Cast(traceAgentTypeRef); //castclass
reWriterWrapper.LoadNull(); //ldstr
reWriterWrapper.LoadNull();
auto argNum = functionInfo.signature.NumberOfArguments();
reWriterWrapper.CreateArray(objectTypeRef, argNum); //newarr
auto arguments = functionInfo.signature.GetMethodArguments();
for (unsigned i = 0; i < argNum; i++) {
reWriterWrapper.BeginLoadValueIntoArray(i);
reWriterWrapper.LoadArgument(i);//ldarg Static index 0
auto argTypeFlags = arguments[i].GetTypeFlags(elementType);
if (argTypeFlags & TypeFlagByRef) {
reWriterWrapper.LoadIND(elementType); //ldind
}
if (argTypeFlags & TypeFlagBoxedType) {
auto tok = arguments[i].GetTypeTok(pEmit, corLibAssemblyRef);
if (tok == mdTokenNil) {
return S_OK;
}
reWriterWrapper.Box(tok);
}
reWriterWrapper.EndLoadValueIntoArray(); //stelem_ref
}
reWriterWrapper.LoadInt32((INT32)function_token); //ldc_i4
reWriterWrapper.CallMember(beforeMemberRef, true); // call
reWriterWrapper.Cast(methodTraceTypeRef); //Castclass
reWriterWrapper.StLocal(rewriter.cNewLocals - 1); //STLOC
ILInstr* pRetInstr = pReWriter->NewILInstr();/
pRetInstr->m_opcode = CEE_RET;
pReWriter->InsertAfter(pReWriter->GetILList()->m_pPrev, pRetInstr);
bool isVoidMethod = (retTypeFlags & TypeFlagVoid) > 0;
auto ret = functionInfo.signature.GetRet();
bool retIsBoxedType = false;
mdToken retTypeTok;
if (!isVoidMethod) {
retTypeTok = ret.GetTypeTok(pEmit, corLibAssemblyRef);
if (ret.GetTypeFlags(elementType) & TypeFlagBoxedType) {
retIsBoxedType = true;
}
}
reWriterWrapper.SetILPosition(pRetInstr);
reWriterWrapper.StLocal(indexEx); //stloc
ILInstr* pRethrowInstr = reWriterWrapper.Rethrow(); //Rethrow
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
ILInstr* pNewInstr = pReWriter->NewILInstr(); //Brfalse
pNewInstr->m_opcode = CEE_BRFALSE_S;
pReWriter->InsertBefore(pRetInstr, pNewInstr);
reWriterWrapper.LoadLocal(indexMethodTrace); //ldloc
reWriterWrapper.LoadLocal(indexRet);//ldloc
reWriterWrapper.LoadLocal(indexEx); //ldloc
reWriterWrapper.CallMember(endMemberRef, true); // call
ILInstr* pEndFinallyInstr = reWriterWrapper.EndFinally(); //Endfinally
pNewInstr->m_pTarget = pEndFinallyInstr;
if (!isVoidMethod) {
reWriterWrapper.LoadLocal(indexRet);//ldloc
if (retIsBoxedType) {
reWriterWrapper.UnboxAny(retTypeTok); // Unbox_Any
}
else {
reWriterWrapper.Cast(retTypeTok);
}
}
for (ILInstr* pInstr = pReWriter->GetILList()->m_pNext; pInstr != pReWriter->GetILList(); pInstr = pInstr->m_pNext) {
switch (pInstr->m_opcode)
{
case CEE_RET:
{
if (pInstr != pRetInstr) {
if (!isVoidMethod) {
reWriterWrapper.SetILPosition(pInstr);
if (retIsBoxedType) {
reWriterWrapper.Box(retTypeTok);
}
reWriterWrapper.StLocal(indexRet); //ldloc
}
pInstr->m_opcode = CEE_LEAVE_S; //Leave_S
pInstr->m_pTarget = pEndFinallyInstr->m_pNext;
}
break;
}
default:
break;
}
}
EHClause exClause{};
exClause.m_Flags = COR_ILEXCEPTION_CLAUSE_NONE;
exClause.m_pTryBegin = pTryStartInstr;
exClause.m_pTryEnd = pRethrowInstr->m_pPrev;
exClause.m_pHandlerBegin = pRethrowInstr->m_pPrev;
exClause.m_pHandlerEnd = pRethrowInstr;
exClause.m_ClassToken = exTypeRef;
EHClause finallyClause{};
finallyClause.m_Flags = COR_ILEXCEPTION_CLAUSE_FINALLY;
finallyClause.m_pTryBegin = pTryStartInstr;
finallyClause.m_pTryEnd = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerBegin = pRethrowInstr->m_pNext;
finallyClause.m_pHandlerEnd = pEndFinallyInstr;
auto m_pEHNew = new EHClause[rewriter.m_nEH + 2];
for (unsigned i = 0; i < rewriter.m_nEH; i++) {
m_pEHNew[i] = rewriter.m_pEH[i];
}
rewriter.m_nEH += 2;
m_pEHNew[rewriter.m_nEH - 2] = exClause;
m_pEHNew[rewriter.m_nEH - 1] = finallyClause;
rewriter.m_pEH = m_pEHNew;
}
hr = rewriter.Export();
....
LocalSigCode
HRESULT ModifyLocalSig(CComPtr<IMetaDataImport2>& pImport, CComPtr<IMetaDataEmit2>& pEmit, ILRewriter& reWriter, mdTypeRef exTypeRef,mdTypeRef methodTraceTypeRef)
{
HRESULT hr;
PCCOR_SIGNATURE rgbOrigSig = NULL;
ULONG cbOrigSig = 0;
UNALIGNED INT32 temp = 0;
if (reWriter.m_tkLocalVarSig != mdTokenNil)
{
IfFailRet(pImport->GetSigFromToken(reWriter.m_tkLocalVarSig, &rgbOrigSig, &cbOrigSig));
const auto len = CorSigCompressToken(methodTraceTypeRef, &temp);
if(cbOrigSig - len > 0){
if(rgbOrigSig[cbOrigSig - len -1]== ELEMENT_TYPE_CLASS){
if (memcmp(&rgbOrigSig[cbOrigSig - len], &temp, len) == 0) {
return E_FAIL;
}
}
}
}
auto exTypeRefSize = CorSigCompressToken(exTypeRef, &temp);
auto methodTraceTypeRefSize = CorSigCompressToken(methodTraceTypeRef, &temp);
ULONG cbNewSize = cbOrigSig + 1 + 1 + methodTraceTypeRefSize + 1 + exTypeRefSize;
ULONG cOrigLocals;
ULONG cNewLocalsLen;
ULONG cbOrigLocals = 0;
if (cbOrigSig == 0) {
cbNewSize += 2;
reWriter.cNewLocals = 3;
cNewLocalsLen = CorSigCompressData(reWriter.cNewLocals, &temp);
}
else {
cbOrigLocals = CorSigUncompressData(rgbOrigSig + 1, &cOrigLocals);
reWriter.cNewLocals = cOrigLocals + 3;
cNewLocalsLen = CorSigCompressData(reWriter.cNewLocals, &temp);
cbNewSize += cNewLocalsLen - cbOrigLocals;
}
auto rgbNewSig = new COR_SIGNATURE[cbNewSize];
*rgbNewSig = IMAGE_CEE_CS_CALLCONV_LOCAL_SIG;
ULONG rgbNewSigOffset = 1;
memcpy(rgbNewSig + rgbNewSigOffset, &temp, cNewLocalsLen);
rgbNewSigOffset += cNewLocalsLen;
if (cbOrigSig > 0) {
const auto cbOrigCopyLen = cbOrigSig - 1 - cbOrigLocals;
memcpy(rgbNewSig + rgbNewSigOffset, rgbOrigSig + 1 + cbOrigLocals, cbOrigCopyLen);
rgbNewSigOffset += cbOrigCopyLen;
}
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_OBJECT;
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_CLASS;
exTypeRefSize = CorSigCompressToken(exTypeRef, &temp);
memcpy(rgbNewSig + rgbNewSigOffset, &temp, exTypeRefSize);
rgbNewSigOffset += exTypeRefSize;
rgbNewSig[rgbNewSigOffset++] = ELEMENT_TYPE_CLASS;
methodTraceTypeRefSize = CorSigCompressToken(methodTraceTypeRef, &temp);
memcpy(rgbNewSig + rgbNewSigOffset, &temp, methodTraceTypeRefSize);
rgbNewSigOffset += methodTraceTypeRefSize;
IfFailRet(pEmit->GetTokenFromSig(&rgbNewSig[0], cbNewSize, &reWriter.m_tkLocalVarSig));
return S_OK;
}
修改方法模板:
//before fixing method
private Task DataRead(string a, int b)
{
return Task.Delay(10);
}
//After modification
private Task DataReadWrapper(string a, int b)
{
object ret = null;
Exception ex = null;
MethodTrace methodTrace = null;
try
{
methodTrace = (MethodTrace)((TraceAgent)TraceAgent.GetInstance())
.BeforeMethod(this.GetType(), this, new object[]{ a, b }, functiontoken);
ret = Task.Delay(10);
goto T;
}
catch (Exception e)
{
ex = e;
throw;
}
finally
{
if (methodTrace != null)
{
methodTrace.EndMethod(ret, ex);
}
}
T:
return (Task)ret;
}
错误:
Unhandled exception.
Cannot print exception string because Exception.ToString() failed.
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\inetpub\wwwroot\DotNetRangeCore\' failed to load coreclr. Exception message: CLR worker thread exited prematurely
如果我在其他方法中通过这段代码修改IL是没有问题的。比如:set_CommandText、System.Random.Next、System.Web.HttpContext.FinishPipelineRequest...
不知道为什么修改Concat会出错。
我通过更换解决了。如果这个IL修改后报错,我换成打包方式