Mono.Cecil was answered here에 try/catch를 구현하는 방법에 대한 개요가 있지만 try/catch/finally 전체가 부족합니다. 그렇다면 어떻게 Mono.Cecil을 사용하여 try/finally를 구현합니까?Mono.Cecil : injection try/finally?
3
A
답변
8
마지막으로 주사하는 방법입니다.
먼저 신고서를 수정해야합니다. 너는 오직 하나만 원한다.
Instruction FixReturns()
{
if (Method.ReturnType == TypeSystem.Void)
{
var instructions = body.Instructions;
var lastRet = Instruction.Create(OpCodes.Ret);
instructions.Add(lastRet);
for (var index = 0; index < instructions.Count - 1; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastRet);
}
}
return lastRet;
}
else
{
var instructions = body.Instructions;
var returnVariable = new VariableDefinition("methodTimerReturn", Method.ReturnType);
body.Variables.Add(returnVariable);
var lastLd = Instruction.Create(OpCodes.Ldloc, returnVariable);
instructions.Add(lastLd);
instructions.Add(Instruction.Create(OpCodes.Ret));
for (var index = 0; index < instructions.Count - 2; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastLd);
instructions.Insert(index, Instruction.Create(OpCodes.Stloc, returnVariable));
index++;
}
}
return lastLd;
}
}
그런 다음 첫 번째 명령을 찾으십시오. 인스턴스 생성자 인 경우 2를 건너 뛸 필요가 있습니다.
Instruction FirstInstructionSkipCtor()
{
if (Method.IsConstructor && !Method.IsStatic)
{
return body.Instructions.Skip(2).First();
}
return body.Instructions.First();
}
그런 다음 검사 예는 매우 유익하고 유용하다고 함께
void InnerProcess()
{
body = Method.Body;
body.SimplifyMacros();
ilProcessor = body.GetILProcessor();
var returnInstruction = FixReturns();
var firstInstruction = FirstInstructionSkipCtor();
var beforeReturn = Instruction.Create(OpCodes.Nop);
ilProcessor.InsertBefore(returnInstruction, beforeReturn);
InjectIlForFinaly(returnInstruction);
var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
{
TryStart = firstInstruction,
TryEnd = beforeReturn,
HandlerStart = beforeReturn,
HandlerEnd = returnInstruction,
};
body.ExceptionHandlers.Add(handler);
body.InitLocals = true;
body.OptimizeMacros();
}
1
를 스티치. 더 복잡한 조건에서 문제가 발생 했습니까? FixReturns()에서 보이드 및 비 보이드 반환 범위 모두에서 새로운 명령 작성을 통한 ret -> leave 변경 방법은 원본을 고아가됩니다. 이는 고아가있는 다른 명령어를 피연산자로 남겨 둘 수 있습니다 (예 : 원본 ret로 분기). 그런 다음 결과 코드가 유효하지 않게됩니다.
기존의 ret 명령어의 opcode/operand 쌍 대 새로운 명령어 생성자 쌍을 업데이트하여 모두 잘 나타납니다.
건배.
관련 문제
- 1. Mono.Cecil
- 2. Mono.Cecil Type.GetInterfaceMap과 같은 것?
- 3. Mono.Cecil 및 Mono.Cecil.Cil 확인
- 4. Mono.Cecil 메서드의 RVA 수정
- 5. DataTable.Select injection
- 6. Mono.Cecil - 사용자 지정 속성을 얻는 방법
- 7. Rails 3 HTML Injection
- 8. SQL Injection Prevention
- 9. Rails SQL injection? 레일에서
- 10. Java Runtime DLL injection
- 11. Pex & Moles - Dependencey Injection
- 12. Stateless resteasy EntityManager injection?
- 13. Ninject PerRequest injection
- 14. Spring Transitive Dependency Injection
- 15. TableAdapters SQL Injection
- 16. C# Dependency Injection
- 17. C++ Dll Injection
- 18. Sql Injection group_concat
- 19. DataTable 이후의 Bean Injection
- 20. Zendframework2 Dependency Injection Confusion
- 21. Zend sql injection prevention
- 22. java bean injection
- 23. UIWebView JavaScript Injection
- 24. setter injection guice + wicket
- 25. Sql Injection MS Access
- 26. Zend Dependency Injection
- 27. Webforms 및 Dependency Injection
- 28. Seam JNDI injection
- 29. mysql query + sprintf = injection?
- 30. MSTest TestMethod Dependency Injection
그래서 기본적으로 ExceptionHandlerType.Finally를 새로운 ExceptionHandler()에 전달하여 해당 게시물에 설명 된 것과 동일한 프로세스입니다. try/catch/finally를 원한다면 두 개의 "ExceptionHandler"인스턴스를 만들어 메소드에 추가합니다. 하나는 catch를위한 인스턴스이고, 하나는 finally를위한 것입니다. 이 경우, 적어도 'finally'를 위해 새로운 예외 처리기를 실제로 만들지 않으므로 이름이 확실히 혼란 스럽습니다. 포인터를 가져 주셔서 감사합니다. – naasking