Patcher correctly translates catch clauses
This commit is contained in:
@@ -12,19 +12,9 @@ namespace Torch.Managers.PatchManager.MSIL
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum MsilTryCatchOperationType
|
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,
|
BeginExceptionBlock,
|
||||||
BeginCatchBlock,
|
BeginClauseBlock,
|
||||||
|
BeginFaultBlock,
|
||||||
BeginFinallyBlock,
|
BeginFinallyBlock,
|
||||||
EndExceptionBlock
|
EndExceptionBlock
|
||||||
}
|
}
|
||||||
@@ -46,9 +36,11 @@ namespace Torch.Managers.PatchManager.MSIL
|
|||||||
public MsilTryCatchOperation(MsilTryCatchOperationType op, Type caughtType = null)
|
public MsilTryCatchOperation(MsilTryCatchOperationType op, Type caughtType = null)
|
||||||
{
|
{
|
||||||
Type = op;
|
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));
|
throw new ArgumentException($"Can't use caught type with operation type {op}", nameof(caughtType));
|
||||||
CatchType = caughtType;
|
CatchType = caughtType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString() => $"{Type} -> {CatchType}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,10 +43,8 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[ReflectedMethod(Name = "BakeByteArray")]
|
[ReflectedMethod(Name = "BakeByteArray")] private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
|
||||||
private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
|
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public MethodContext(DynamicMethod method)
|
public MethodContext(DynamicMethod method)
|
||||||
@@ -72,11 +70,11 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
using (var reader = new BinaryReader(memory))
|
using (var reader = new BinaryReader(memory))
|
||||||
while (memory.Length > memory.Position)
|
while (memory.Length > memory.Position)
|
||||||
{
|
{
|
||||||
var opcodeOffset = (int)memory.Position;
|
var opcodeOffset = (int) memory.Position;
|
||||||
var instructionValue = (short)memory.ReadByte();
|
var instructionValue = (short) memory.ReadByte();
|
||||||
if (Prefixes.Contains(instructionValue))
|
if (Prefixes.Contains(instructionValue))
|
||||||
{
|
{
|
||||||
instructionValue = (short)((instructionValue << 8) | memory.ReadByte());
|
instructionValue = (short) ((instructionValue << 8) | memory.ReadByte());
|
||||||
}
|
}
|
||||||
if (!OpCodeLookup.TryGetValue(instructionValue, out OpCode opcode))
|
if (!OpCodeLookup.TryGetValue(instructionValue, out OpCode opcode))
|
||||||
{
|
{
|
||||||
@@ -86,7 +84,8 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (opcode.Size != memory.Position - opcodeOffset)
|
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)
|
var instruction = new MsilInstruction(opcode)
|
||||||
{
|
{
|
||||||
Offset = opcodeOffset
|
Offset = opcodeOffset
|
||||||
@@ -105,16 +104,24 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
var beginInstruction = FindInstruction(clause.TryOffset);
|
var beginInstruction = FindInstruction(clause.TryOffset);
|
||||||
var catchInstruction = FindInstruction(clause.HandlerOffset);
|
var catchInstruction = FindInstruction(clause.HandlerOffset);
|
||||||
var finalInstruction = FindInstruction(clause.HandlerOffset + clause.HandlerLength);
|
var finalInstruction = FindInstruction(clause.HandlerOffset + clause.HandlerLength);
|
||||||
beginInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
|
beginInstruction.TryCatchOperation =
|
||||||
if ((clause.Flags & ExceptionHandlingClauseOptions.Clause) != 0)
|
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginExceptionBlock);
|
||||||
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginCatchBlock, clause.CatchType);
|
if ((clause.Flags & ExceptionHandlingClauseOptions.Fault) != 0)
|
||||||
|
catchInstruction.TryCatchOperation =
|
||||||
|
new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFaultBlock);
|
||||||
else if ((clause.Flags & ExceptionHandlingClauseOptions.Finally) != 0)
|
else if ((clause.Flags & ExceptionHandlingClauseOptions.Finally) != 0)
|
||||||
catchInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.BeginFinallyBlock);
|
catchInstruction.TryCatchOperation =
|
||||||
finalInstruction.TryCatchOperation = new MsilTryCatchOperation(MsilTryCatchOperationType.EndExceptionBlock);
|
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;
|
int min = 0, max = _instructions.Count;
|
||||||
while (min != max)
|
while (min != max)
|
||||||
@@ -153,12 +160,12 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
Prefixes = new HashSet<short>();
|
Prefixes = new HashSet<short>();
|
||||||
foreach (FieldInfo field in typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public))
|
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)
|
if (opcode.OpCodeType != OpCodeType.Nternal)
|
||||||
OpCodeLookup.Add(opcode.Value, opcode);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -60,9 +60,12 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
case MsilTryCatchOperationType.BeginExceptionBlock:
|
case MsilTryCatchOperationType.BeginExceptionBlock:
|
||||||
target.BeginExceptionBlock();
|
target.BeginExceptionBlock();
|
||||||
break;
|
break;
|
||||||
case MsilTryCatchOperationType.BeginCatchBlock:
|
case MsilTryCatchOperationType.BeginClauseBlock:
|
||||||
target.BeginCatchBlock(il.TryCatchOperation.CatchType);
|
target.BeginCatchBlock(il.TryCatchOperation.CatchType);
|
||||||
break;
|
break;
|
||||||
|
case MsilTryCatchOperationType.BeginFaultBlock:
|
||||||
|
target.BeginFaultBlock();
|
||||||
|
break;
|
||||||
case MsilTryCatchOperationType.BeginFinallyBlock:
|
case MsilTryCatchOperationType.BeginFinallyBlock:
|
||||||
target.BeginFinallyBlock();
|
target.BeginFinallyBlock();
|
||||||
break;
|
break;
|
||||||
@@ -80,11 +83,12 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
|
|
||||||
// Leave opcodes emitted by these:
|
// Leave opcodes emitted by these:
|
||||||
if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
|
if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
|
||||||
MsilTryCatchOperationType.BeginCatchBlock)
|
MsilTryCatchOperationType.BeginClauseBlock)
|
||||||
continue;
|
continue;
|
||||||
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
|
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
|
||||||
(ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock ||
|
(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))
|
ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFinallyBlock))
|
||||||
continue;
|
continue;
|
||||||
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
|
if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
|
||||||
@@ -175,7 +179,7 @@ namespace Torch.Managers.PatchManager.Transpile
|
|||||||
continue;
|
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;
|
unreachable = true;
|
||||||
}
|
}
|
||||||
foreach (var k in data)
|
foreach (var k in data)
|
||||||
|
Reference in New Issue
Block a user