From c07a01a427d577ad3db11e81b1cee0612c8947e8 Mon Sep 17 00:00:00 2001 From: Westin Miller Date: Sat, 11 Nov 2017 03:50:25 -0800 Subject: [PATCH] Patcher correctly translates catch clauses --- .../MSIL/MsilTryCatchOperation.cs | 18 +++----- .../PatchManager/Transpile/MethodContext.cs | 41 +++++++++++-------- .../Transpile/MethodTranspiler.cs | 12 ++++-- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/Torch/Managers/PatchManager/MSIL/MsilTryCatchOperation.cs b/Torch/Managers/PatchManager/MSIL/MsilTryCatchOperation.cs index d9aecae..5ea653e 100644 --- a/Torch/Managers/PatchManager/MSIL/MsilTryCatchOperation.cs +++ b/Torch/Managers/PatchManager/MSIL/MsilTryCatchOperation.cs @@ -12,19 +12,9 @@ namespace Torch.Managers.PatchManager.MSIL /// 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}"; } } diff --git a/Torch/Managers/PatchManager/Transpile/MethodContext.cs b/Torch/Managers/PatchManager/Transpile/MethodContext.cs index aa7b203..52bd002 100644 --- a/Torch/Managers/PatchManager/Transpile/MethodContext.cs +++ b/Torch/Managers/PatchManager/Transpile/MethodContext.cs @@ -43,10 +43,8 @@ namespace Torch.Managers.PatchManager.Transpile } - #pragma warning disable 649 - [ReflectedMethod(Name = "BakeByteArray")] - private static Func _ilGeneratorBakeByteArray; + [ReflectedMethod(Name = "BakeByteArray")] private static Func _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(); 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)); } } } } -} +} \ No newline at end of file diff --git a/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs b/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs index b989e49..3c5bc94 100644 --- a/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs +++ b/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs @@ -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)