Skip to content

Commit

Permalink
Unstrip Exception Handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
ds5678 committed Sep 8, 2024
1 parent 7a56995 commit a842e19
Showing 1 changed file with 111 additions and 22 deletions.
133 changes: 111 additions & 22 deletions Il2CppInterop.Generator/Utils/UnstripTranslator.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using AsmResolver;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
Expand Down Expand Up @@ -170,28 +171,8 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
}
else if (bodyInstruction.OpCode.OperandType == CilOperandType.InlineType)
{
var targetType = ((ITypeDefOrRef)bodyInstruction.Operand).ToTypeSignature();
if (targetType is GenericParameterSignature genericParam)
{
if (genericParam.ParameterType is GenericParameterType.Type)
{
var newTypeOwner =
Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, original.DeclaringType?.ToTypeSignature(), imports)?.Resolve();
if (newTypeOwner == null)
return false;
targetType = newTypeOwner.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature();
}
else
{
targetType = target.GenericParameters.Single(it => it.Name == targetType.Name).ToTypeSignature();
}
}
else
{
targetType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, targetType, imports);
if (targetType == null)
return false;
}
if (!TryResolveTypeInNewAssemblies(((ITypeDefOrRef)bodyInstruction.Operand).ToTypeSignature(), original, target, imports, globalContext, out var targetType))
return false;

if (bodyInstruction.OpCode == OpCodes.Castclass && !targetType.IsValueType)
{
Expand Down Expand Up @@ -324,13 +305,92 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t
newLabel.Instruction = instructionMap[oldLabel.Instruction!];
}

// Copy exception handlers
foreach (var exceptionHandler in original.CilMethodBody.ExceptionHandlers)
{
var newExceptionHandler = new CilExceptionHandler
{
HandlerType = exceptionHandler.HandlerType
};

switch (exceptionHandler.TryStart)
{
case null:
break;
case CilInstructionLabel { Instruction: not null } tryStart:
newExceptionHandler.TryStart = new CilInstructionLabel(instructionMap[tryStart.Instruction]);
break;
default:
return false;
}

switch (exceptionHandler.TryEnd)
{
case null:
break;
case CilInstructionLabel { Instruction: not null } tryEnd:
newExceptionHandler.TryEnd = new CilInstructionLabel(instructionMap[tryEnd.Instruction]);
break;
default:
return false;
}

switch (exceptionHandler.HandlerStart)
{
case null:
break;
case CilInstructionLabel { Instruction: not null } handlerStart:
newExceptionHandler.HandlerStart = new CilInstructionLabel(instructionMap[handlerStart.Instruction]);
break;
default:
return false;
}

switch (exceptionHandler.HandlerEnd)
{
case null:
break;
case CilInstructionLabel { Instruction: not null } handlerEnd:
newExceptionHandler.HandlerEnd = new CilInstructionLabel(instructionMap[handlerEnd.Instruction]);
break;
default:
return false;
}

switch (exceptionHandler.FilterStart)
{
case null:
break;
case CilInstructionLabel { Instruction: not null } filterStart:
newExceptionHandler.FilterStart = new CilInstructionLabel(instructionMap[filterStart.Instruction]);
break;
default:
return false;
}

if (exceptionHandler.ExceptionType is null)
{
}
else if (TryResolveTypeInNewAssemblies(exceptionHandler.ExceptionType.ToTypeSignature(), original, target, imports, globalContext, out var resolvedType))
{
newExceptionHandler.ExceptionType = resolvedType.ToTypeDefOrRef();
}
else
{
return false;
}

target.CilMethodBody.ExceptionHandlers.Add(newExceptionHandler);
}

return true;
}

public static void ReplaceBodyWithException(MethodDefinition newMethod, RuntimeAssemblyReferences imports)
{
newMethod.CilMethodBody!.LocalVariables.Clear();
newMethod.CilMethodBody.Instructions.Clear();
newMethod.CilMethodBody.ExceptionHandlers.Clear();
var processor = newMethod.CilMethodBody.Instructions;

processor.Add(OpCodes.Ldstr, "Method unstripping failed");
Expand All @@ -339,6 +399,35 @@ public static void ReplaceBodyWithException(MethodDefinition newMethod, RuntimeA
processor.Add(OpCodes.Ret);
}

private static bool TryResolveTypeInNewAssemblies(TypeSignature? originalType, MethodDefinition original, MethodDefinition target, RuntimeAssemblyReferences imports, RewriteGlobalContext globalContext, [NotNullWhen(true)] out TypeSignature? targetType)
{
if (originalType is GenericParameterSignature genericParam)
{
if (genericParam.ParameterType is GenericParameterType.Type)
{
var newTypeOwner =
Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, original.DeclaringType?.ToTypeSignature(), imports)?.Resolve();
if (newTypeOwner == null)
{
targetType = null;
return false;
}

targetType = newTypeOwner.GenericParameters.Single(it => it.Name == originalType.Name).ToTypeSignature();
}
else
{
targetType = target.GenericParameters.Single(it => it.Name == originalType.Name).ToTypeSignature();
}
return true;
}
else
{
targetType = Pass80UnstripMethods.ResolveTypeInNewAssemblies(globalContext, originalType, imports);
return targetType != null;
}
}

//Required for deconstruction on net472
private static void Deconstruct(this KeyValuePair<CilInstructionLabel, CilInstructionLabel> pair, out CilInstructionLabel key, out CilInstructionLabel value)
{
Expand Down

0 comments on commit a842e19

Please sign in to comment.