From aac5831cd19d509bb293b34ebbbcb14a64c4c384 Mon Sep 17 00:00:00 2001 From: Jeremy Pritts <49847914+ds5678@users.noreply.github.com> Date: Sat, 14 Sep 2024 19:27:38 -0700 Subject: [PATCH] Unstrip Exception Handlers (#157) * Unstrip Exception Handlers * Handle ExceptionType more strictly --- .../Utils/UnstripTranslator.cs | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs index d0b6ca98..28a09316 100644 --- a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs @@ -4,6 +4,7 @@ using AsmResolver.DotNet.Collections; using AsmResolver.DotNet.Signatures; using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables; using Il2CppInterop.Generator.Contexts; using Il2CppInterop.Generator.Extensions; using Il2CppInterop.Generator.Passes; @@ -341,13 +342,91 @@ 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; + } + + switch (exceptionHandler.ExceptionType?.ToTypeSignature()) + { + case null: + break; + case CorLibTypeSignature { ElementType: ElementType.Object }: + newExceptionHandler.ExceptionType = imports.Module.CorLibTypeFactory.Object.ToTypeDefOrRef(); + break; + default: + // In the future, we will throw exact exceptions, but we don't right now, + // so attempting to catch a specific exception type will always fail. + 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 = new(newMethod); var processor = newMethod.CilMethodBody.Instructions; processor.Add(OpCodes.Ldstr, "Method unstripping failed");