Patcher correctly translates catch clauses

This commit is contained in:
Westin Miller
2017-11-11 03:50:25 -08:00
parent 11bc7cb60c
commit c07a01a427
3 changed files with 37 additions and 34 deletions

View File

@@ -12,19 +12,9 @@ namespace Torch.Managers.PatchManager.MSIL
/// </summary>
public enum MsilTryCatchOperationType
{
// TryCatchBlockIL:
// var exBlock = ILGenerator.BeginExceptionBlock();
// try{
// ILGenerator.BeginCatchBlock(typeof(Exception));
// } catch(Exception e) {
// ILGenerator.BeginCatchBlock(null);
// } catch {
// ILGenerator.BeginFinallyBlock();
// }finally {
// ILGenerator.EndExceptionBlock();
// }
BeginExceptionBlock,
BeginCatchBlock,
BeginClauseBlock,
BeginFaultBlock,
BeginFinallyBlock,
EndExceptionBlock
}
@@ -46,9 +36,11 @@ namespace Torch.Managers.PatchManager.MSIL
public MsilTryCatchOperation(MsilTryCatchOperationType op, Type caughtType = null)
{
Type = op;
if (caughtType != null && op != MsilTryCatchOperationType.BeginCatchBlock)
if (caughtType != null && op != MsilTryCatchOperationType.BeginClauseBlock)
throw new ArgumentException($"Can't use caught type with operation type {op}", nameof(caughtType));
CatchType = caughtType;
}
public override string ToString() => $"{Type} -> {CatchType}";
}
}

View File

@@ -43,10 +43,8 @@ namespace Torch.Managers.PatchManager.Transpile
}
#pragma warning disable 649
[ReflectedMethod(Name = "BakeByteArray")]
private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
[ReflectedMethod(Name = "BakeByteArray")] private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
#pragma warning restore 649
public MethodContext(DynamicMethod method)
@@ -86,7 +84,8 @@ namespace Torch.Managers.PatchManager.Transpile
continue;
}
if (opcode.Size != memory.Position - opcodeOffset)
throw new Exception($"Opcode said it was {opcode.Size} but we read {memory.Position - opcodeOffset}");
throw new Exception(
$"Opcode said it was {opcode.Size} but we read {memory.Position - opcodeOffset}");
var instruction = new MsilInstruction(opcode)
{
Offset = opcodeOffset
@@ -105,16 +104,24 @@ namespace Torch.Managers.PatchManager.Transpile
var beginInstruction = FindInstruction(clause.TryOffset);
var catchInstruction = FindInstruction(clause.HandlerOffset);
var finalInstruction = FindInstruction(clause.HandlerOffset + clause.HandlerLength);
beginInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
if ((clause.Flags & ExceptionHandlingClauseOptions.Clause) != 0)
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginCatchBlock, clause.CatchType);
beginInstruction.TryCatchOperation =
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
if ((clause.Flags & ExceptionHandlingClauseOptions.Fault) != 0)
catchInstruction.TryCatchOperation =
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFaultBlock);
else if ((clause.Flags & ExceptionHandlingClauseOptions.Finally) != 0)
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFinallyBlock);
finalInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.EndExceptionBlock);
catchInstruction.TryCatchOperation =
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFinallyBlock);
else
catchInstruction.TryCatchOperation =
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginClauseBlock, clause.CatchType);
finalInstruction.TryCatchOperation =
new MsilTryCatchOperation(MsilTryCatchOperationType.EndExceptionBlock);
}
}
private MsilInstruction FindInstruction(int offset)
public MsilInstruction FindInstruction(int offset)
{
int min = 0, max = _instructions.Count;
while (min != max)

View File

@@ -60,9 +60,12 @@ namespace Torch.Managers.PatchManager.Transpile
case MsilTryCatchOperationType.BeginExceptionBlock:
target.BeginExceptionBlock();
break;
case MsilTryCatchOperationType.BeginCatchBlock:
case MsilTryCatchOperationType.BeginClauseBlock:
target.BeginCatchBlock(il.TryCatchOperation.CatchType);
break;
case MsilTryCatchOperationType.BeginFaultBlock:
target.BeginFaultBlock();
break;
case MsilTryCatchOperationType.BeginFinallyBlock:
target.BeginFinallyBlock();
break;
@@ -80,11 +83,12 @@ namespace Torch.Managers.PatchManager.Transpile
// Leave opcodes emitted by these:
if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
MsilTryCatchOperationType.BeginCatchBlock)
MsilTryCatchOperationType.BeginClauseBlock)
continue;
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
(ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock ||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginCatchBlock ||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginClauseBlock ||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFaultBlock ||
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFinallyBlock))
continue;
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
@@ -175,7 +179,7 @@ namespace Torch.Managers.PatchManager.Transpile
continue;
}
}
if (k.OpCode == OpCodes.Br || k.OpCode == OpCodes.Br_S)
if (k.OpCode == OpCodes.Br || k.OpCode == OpCodes.Br_S || k.OpCode == OpCodes.Leave || k.OpCode == OpCodes.Leave_S)
unreachable = true;
}
foreach (var k in data)