Use reflected manager for patch internals
This commit is contained in:
@@ -3,11 +3,17 @@ using System.Reflection;
|
|||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Torch.Utils;
|
||||||
|
|
||||||
namespace Torch.Managers.PatchManager
|
namespace Torch.Managers.PatchManager
|
||||||
{
|
{
|
||||||
internal class AssemblyMemory
|
internal class AssemblyMemory
|
||||||
{
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[ReflectedMethod(Name = "GetMethodDescriptor")]
|
||||||
|
private static Func<DynamicMethod, RuntimeMethodHandle> _getMethodHandle;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the address, in RAM, where the body of a method starts.
|
/// Gets the address, in RAM, where the body of a method starts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -16,9 +22,8 @@ namespace Torch.Managers.PatchManager
|
|||||||
public static long GetMethodBodyStart(MethodBase method)
|
public static long GetMethodBodyStart(MethodBase method)
|
||||||
{
|
{
|
||||||
RuntimeMethodHandle handle;
|
RuntimeMethodHandle handle;
|
||||||
if (method is DynamicMethod)
|
if (method is DynamicMethod dyn)
|
||||||
handle = (RuntimeMethodHandle)typeof(DynamicMethod).GetMethod("GetMethodDescriptor", BindingFlags.NonPublic | BindingFlags.Instance)
|
handle = _getMethodHandle.Invoke(dyn);
|
||||||
.Invoke(method, new object[0]);
|
|
||||||
else
|
else
|
||||||
handle = method.MethodHandle;
|
handle = method.MethodHandle;
|
||||||
RuntimeHelpers.PrepareMethod(handle);
|
RuntimeHelpers.PrepareMethod(handle);
|
||||||
|
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Torch.Managers.PatchManager.Transpile;
|
using Torch.Managers.PatchManager.Transpile;
|
||||||
|
using Torch.Utils;
|
||||||
|
|
||||||
namespace Torch.Managers.PatchManager
|
namespace Torch.Managers.PatchManager
|
||||||
{
|
{
|
||||||
@@ -76,21 +77,25 @@ namespace Torch.Managers.PatchManager
|
|||||||
private const string INSTANCE_PARAMETER = "__instance";
|
private const string INSTANCE_PARAMETER = "__instance";
|
||||||
private const string RESULT_PARAMETER = "__result";
|
private const string RESULT_PARAMETER = "__result";
|
||||||
|
|
||||||
|
#pragma warning disable 649
|
||||||
|
[ReflectedStaticMethod(Type = typeof(RuntimeHelpers), Name = "_CompileMethod", OverrideTypeNames = new[] { "System.IRuntimeMethodInfo" })]
|
||||||
|
private static Action<object> _compileDynamicMethod;
|
||||||
|
[ReflectedMethod(Name = "GetMethodInfo")]
|
||||||
|
private static Func<RuntimeMethodHandle, object> _getMethodInfo;
|
||||||
|
[ReflectedMethod(Name = "GetMethodDescriptor")]
|
||||||
|
private static Func<DynamicMethod, RuntimeMethodHandle> _getMethodHandle;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
public DynamicMethod ComposePatchedMethod()
|
public DynamicMethod ComposePatchedMethod()
|
||||||
{
|
{
|
||||||
var method = AllocatePatchMethod();
|
DynamicMethod method = AllocatePatchMethod();
|
||||||
var generator = new LoggingIlGenerator(method.GetILGenerator());
|
var generator = new LoggingIlGenerator(method.GetILGenerator());
|
||||||
EmitPatched(generator);
|
EmitPatched(generator);
|
||||||
|
|
||||||
// Force it to compile
|
// Force it to compile
|
||||||
const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
RuntimeMethodHandle handle = _getMethodHandle.Invoke(method);
|
||||||
const BindingFlags nonPublicStatic = BindingFlags.NonPublic | BindingFlags.Static;
|
object runtimeMethodInfo = _getMethodInfo.Invoke(handle);
|
||||||
var compileMethod = typeof(RuntimeHelpers).GetMethod("_CompileMethod", nonPublicStatic);
|
_compileDynamicMethod.Invoke(runtimeMethodInfo);
|
||||||
var getMethodDescriptor = typeof(DynamicMethod).GetMethod("GetMethodDescriptor", nonPublicInstance);
|
|
||||||
var handle = (RuntimeMethodHandle)getMethodDescriptor.Invoke(method, new object[0]);
|
|
||||||
var getMethodInfo = typeof(RuntimeMethodHandle).GetMethod("GetMethodInfo", nonPublicInstance);
|
|
||||||
var runtimeMethodInfo = getMethodInfo.Invoke(handle, new object[0]);
|
|
||||||
compileMethod.Invoke(null, new[] { runtimeMethodInfo });
|
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
Reference in New Issue
Block a user