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)
@@ -72,11 +70,11 @@ namespace Torch.Managers.PatchManager.Transpile
using (var reader = new BinaryReader(memory))
while (memory.Length > memory.Position)
{
var opcodeOffset = (int)memory.Position;
var instructionValue = (short)memory.ReadByte();
var opcodeOffset = (int) memory.Position;
var instructionValue = (short) memory.ReadByte();
if (Prefixes.Contains(instructionValue))
{
instructionValue = (short)((instructionValue << 8) | memory.ReadByte());
instructionValue = (short) ((instructionValue << 8) | memory.ReadByte());
}
if (!OpCodeLookup.TryGetValue(instructionValue, out OpCode opcode))
{
@@ -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)
@@ -153,14 +160,14 @@ namespace Torch.Managers.PatchManager.Transpile
Prefixes = new HashSet<short>();
foreach (FieldInfo field in typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public))
{
var opcode = (OpCode)field.GetValue(null);
var opcode = (OpCode) field.GetValue(null);
if (opcode.OpCodeType != OpCodeType.Nternal)
OpCodeLookup.Add(opcode.Value, opcode);
if ((ushort)opcode.Value > 0xFF)
if ((ushort) opcode.Value > 0xFF)
{
Prefixes.Add((short)((ushort)opcode.Value >> 8));
Prefixes.Add((short) ((ushort) opcode.Value >> 8));
}
}
}
}
}
}

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)