Use reflected manager for patch internals

This commit is contained in:
Westin Miller
2017-09-09 00:50:45 -07:00
parent 9c3a22c556
commit 837b56462f
2 changed files with 22 additions and 12 deletions

View File

@@ -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);

View File

@@ -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