XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using Mono.Cecil;
using Mono.Cecil.Cil;

/// <summary>Resolve EH-only funclet lookups to the root method's EH table and address space.</summary>
internal static class FuncletEhRuntimePatch
{
    public const string HelperName = "XfeResolveEhFuncletRootV1";
    public static bool Apply(AssemblyDefinition assembly)
    {
        var module = assembly.MainModule;
        var eh = module.Types.Single(type => type.FullName == "Cosmos.Kernel.Core.Runtime.ExceptionHandling.ExceptionHelper");
        var lookup = eh.Methods.Single(method => method.Name == "TryGetMethodLSDA");
        var existing = eh.Methods.SingleOrDefault(method => method.Name == HelperName);
        if (existing is not null)
        {
            if (lookup.Body.Instructions.Count(instruction => instruction.Operand is MethodReference method && method.FullName == existing.FullName) != 1 ||
                existing.Parameters.Count != 2 || existing.Body.Instructions.Count != 31)
                throw new InvalidOperationException("Unexpected EH funclet root resolver patch.");
            return true;
        }
        if (lookup.Body.Instructions.Count != 5 || lookup.Body.Instructions[3].Operand is not MethodReference original ||
            original.Name != "TryGetMethodLSDA" || original.DeclaringType.FullName != "Cosmos.Kernel.Core.Runtime.GcInfo.MethodGcInfoLookup")
            throw new InvalidOperationException("Pinned EH LSDA wrapper changed; refusing to replace it.");
        var resolve = new MethodDefinition(HelperName, MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig, module.TypeSystem.Void);
        resolve.Parameters.Add(new("rootStart", ParameterAttributes.None, lookup.Parameters[1].ParameterType));
        resolve.Parameters.Add(new("rootLsda", ParameterAttributes.None, lookup.Parameters[2].ParameterType));
        resolve.Body.InitLocals = true;
        var cursor = new VariableDefinition(new PointerType(module.TypeSystem.Byte)); resolve.Body.Variables.Add(cursor);
        eh.Methods.Add(resolve);
        var il = resolve.Body.GetILProcessor(); var end = il.Create(OpCodes.Ret);
        il.Append(il.Create(OpCodes.Ldarg_1)); il.Append(il.Create(OpCodes.Ldind_I)); il.Append(il.Create(OpCodes.Ldind_U1));
        il.Append(il.Create(OpCodes.Ldc_I4_3)); il.Append(il.Create(OpCodes.And)); il.Append(il.Create(OpCodes.Brfalse, end));
        // Same signed relative-pointer format used by the unmodified pinned
        // GCInfo decoder: LSDA delta is relative to its own int32 slot.
        il.Append(il.Create(OpCodes.Ldarg_1)); il.Append(il.Create(OpCodes.Ldind_I)); il.Append(il.Create(OpCodes.Ldc_I4_1));
        il.Append(il.Create(OpCodes.Add)); il.Append(il.Create(OpCodes.Stloc, cursor));
        il.Append(il.Create(OpCodes.Ldarg_1)); il.Append(il.Create(OpCodes.Ldloc, cursor)); il.Append(il.Create(OpCodes.Ldloc, cursor));
        il.Append(il.Create(OpCodes.Ldind_I4)); il.Append(il.Create(OpCodes.Conv_I)); il.Append(il.Create(OpCodes.Add)); il.Append(il.Create(OpCodes.Stind_I));
        il.Append(il.Create(OpCodes.Ldloc, cursor)); il.Append(il.Create(OpCodes.Ldc_I4_4)); il.Append(il.Create(OpCodes.Add)); il.Append(il.Create(OpCodes.Stloc, cursor));
        il.Append(il.Create(OpCodes.Ldarg_0)); il.Append(il.Create(OpCodes.Ldarg_0)); il.Append(il.Create(OpCodes.Ldind_I));
        il.Append(il.Create(OpCodes.Ldloc, cursor)); il.Append(il.Create(OpCodes.Ldind_I4)); il.Append(il.Create(OpCodes.Conv_I));
        il.Append(il.Create(OpCodes.Sub)); il.Append(il.Create(OpCodes.Stind_I)); il.Append(end); resolve.Body.MaxStackSize = 3;
        lookup.Body.Instructions.Clear(); var wrapper = lookup.Body.GetILProcessor(); var notFound = wrapper.Create(OpCodes.Ldc_I4_0);
        wrapper.Append(wrapper.Create(OpCodes.Ldarg_0)); wrapper.Append(wrapper.Create(OpCodes.Ldarg_1)); wrapper.Append(wrapper.Create(OpCodes.Ldarg_2));
        wrapper.Append(wrapper.Create(OpCodes.Call, original)); wrapper.Append(wrapper.Create(OpCodes.Brfalse, notFound));
        wrapper.Append(wrapper.Create(OpCodes.Ldarg_1)); wrapper.Append(wrapper.Create(OpCodes.Ldarg_2)); wrapper.Append(wrapper.Create(OpCodes.Call, resolve));
        wrapper.Append(wrapper.Create(OpCodes.Ldc_I4_1)); wrapper.Append(wrapper.Create(OpCodes.Ret)); wrapper.Append(notFound); wrapper.Append(wrapper.Create(OpCodes.Ret));
        lookup.Body.MaxStackSize = 3;
        return false;
    }
}