Skip to content

Commit

Permalink
fix: fail to inject when the methods are sharing the same name
Browse files Browse the repository at this point in the history
  • Loading branch information
labbbirder committed Jan 30, 2024
1 parent a4a898c commit 7a680b6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 41 deletions.
58 changes: 35 additions & 23 deletions Editor/InjectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ internal static bool InjectAssembly(InjectionInfo[] injections, string inputAsse

//mark check
var injected = targetAssembly.MainModule.Types.Any(t =>
Constants.InjectedMarkName == t.Name &&
Constants.InjectedMarkNamespace == t.Namespace);
Constants.INJECTED_MARK_NAME == t.Name &&
Constants.INJECTED_MARK_NAMESPACE == t.Namespace);
if (injected)
{
targetAssembly.Release();
Expand All @@ -72,7 +72,7 @@ internal static bool InjectAssembly(InjectionInfo[] injections, string inputAsse
{
throw new($"Cannot find Type `{type}` in target assembly {inputAssemblyPath}");
}
var targetMethod = targetType.FindMethod(methodName).Resolve();
var targetMethod = targetType.FindMethod(injectedMethod.GetSignature()).Resolve();
if (targetMethod is null)
{
throw new($"Cannot find Method `{methodName}` in Type `{type}`");
Expand All @@ -88,8 +88,8 @@ internal static bool InjectAssembly(InjectionInfo[] injections, string inputAsse

//mark make
var InjectedMark = new TypeDefinition(
Constants.InjectedMarkNamespace,
Constants.InjectedMarkName,
Constants.INJECTED_MARK_NAMESPACE,
Constants.INJECTED_MARK_NAME,
TypeAttributes.Class,
targetAssembly.MainModule.TypeSystem.Object);
targetAssembly.MainModule.Types.Add(InjectedMark);
Expand Down Expand Up @@ -127,9 +127,11 @@ static IEnumerable<Type> GetContainingTypes(Type type)
}
}
}


static MethodDefinition DuplicateOriginalMethod(this TypeDefinition targetType, MethodDefinition targetMethod)
{
var originName = Constants.GetOriginMethodName(targetMethod.Name);
var originName = Constants.GetOriginMethodName(targetMethod.Name, targetMethod.GetSignature());
var duplicatedMethod = targetType.Methods.FirstOrDefault(m => m.Name == originName);
if (duplicatedMethod is null)
{
Expand All @@ -140,16 +142,20 @@ static MethodDefinition DuplicateOriginalMethod(this TypeDefinition targetType,
}
return duplicatedMethod;
}


static void Release(this AssemblyDefinition assemblyDefinition)
{
if (assemblyDefinition == null) return;
assemblyDefinition.MainModule.AssemblyResolver?.Dispose();
assemblyDefinition.MainModule.SymbolReader?.Dispose();
assemblyDefinition.Dispose();
}


static (FieldDefinition field, MethodReference fieldInvokeMethod) AddInjectField(this TypeDefinition targetType, MethodDefinition targetMethod, string methodName)
{
var injectionName = Constants.GetInjectedFieldName(methodName);
var injectionName = Constants.GetInjectedFieldName(methodName, targetMethod.GetSignature());
var HasThis = targetMethod.HasThis;
var Parameters = targetMethod.Parameters;
var GenericParameters = targetMethod.GenericParameters;
Expand Down Expand Up @@ -194,7 +200,7 @@ static void Release(this AssemblyDefinition assemblyDefinition)
// FieldAttributes.Private|FieldAttributes.Static|FieldAttributes.Assembly,
// targetType.Module.ImportReference(typeof(Delegate)));
// var resMth = genInst.Resolve();
var genMtd = rawGenType.FindMethod("Invoke");
var genMtd = rawGenType.FindMethodByName("Invoke");
// genMtd.DeclaringType = genInst;
var mnlMth = new MethodReference(genMtd.Name, genMtd.ReturnType, genInst)
{
Expand All @@ -208,6 +214,7 @@ static void Release(this AssemblyDefinition assemblyDefinition)
return (sfldInject, mnlMth);
}


static void AddInjectionMethod(
this TypeDefinition targetType,
MethodDefinition targetMethod, MethodDefinition originalMethod,
Expand Down Expand Up @@ -285,19 +292,8 @@ static void Release(this AssemblyDefinition assemblyDefinition)
ilProcessor.Append(Instruction.Create(OpCodes.Nop));
ilProcessor.Append(Instruction.Create(OpCodes.Ret));
}
// static void InjectCctor(this TypeDefinition targetType,FieldDefinition field){
// var cctorMethod = targetType.Methods.FirstOrDefault(m=>m.Name==".cctor");
// if(cctorMethod is null){
// cctorMethod = new MethodDefinition(".cctor",MethodAttributes.Static|MethodAttributes.Private,targetType.Module.TypeSystem.Void);
// targetType.Methods.Add(cctorMethod);
// }
// var ilProcessor = cctorMethod.Body.GetILProcessor();
// var bdis = cctorMethod.Body.Instructions;
// var insertPoint = bdis[0];
// ilProcessor.InsertBefore(insertPoint,Instruction.Create(OpCodes.Ldsfld,field));
// ilProcessor.InsertBefore(insertPoint,Instruction.Create(OpCodes.Ldsfld,field));
// }
// =>md.GetType(type.ToString(),true);


static Instruction createLdarg(this ILProcessor ilProcessor, int i)
{
if (i < s_ldargs.Length)
Expand All @@ -314,6 +310,7 @@ static Instruction createLdarg(this ILProcessor ilProcessor, int i)
}
}


/// <summary>
/// Create a clone of the given method definition
/// </summary>
Expand All @@ -337,6 +334,7 @@ public static MethodDefinition Clone(this MethodDefinition source)
return result;
}


/// <summary>
/// Create a clone of the given method body
/// </summary>
Expand All @@ -362,6 +360,7 @@ public static MethodBody Clone(this MethodBody source, MethodDefinition target)
return result;
}


internal static bool IsReturnVoid(this MethodDefinition md)
=> md.ReturnType.ToString() == voidType.ToString();
internal static bool IsReturnValueType(this MethodDefinition md)
Expand All @@ -370,8 +369,15 @@ internal static bool IsComplexValueType(this TypeReference td)
=> td.ToString() != voidType.ToString() && !td.IsPrimitive;
internal static Type GetUnderlyingType(this TypeReference td)
=> td.IsPrimitive ? Type.GetType(td.Name) : objType;
internal static MethodReference FindMethod(this TypeDefinition td, string methodName)
=> td.Module.ImportReference(td.Methods.FirstOrDefault(m => m.Name == methodName));

internal static string GetSignature(this MethodDefinition md)
=> $"{md.Name}({string.Join(",", md.Parameters.Select(p => p.ParameterType.FullName))})";

internal static MethodReference FindMethod(this TypeDefinition td, string methodSignature)
=> td.Module.ImportReference(td.Methods.FirstOrDefault(m => m.GetSignature().Equals(methodSignature)));

internal static MethodReference FindMethodByName(this TypeDefinition td, string methodName)
=> td.Module.ImportReference(td.Methods.FirstOrDefault(m => m.Name.Equals(methodName)));
internal static TypeDefinition FindType(this ModuleDefinition md, Type type)
{
Assert.IsNotNull(type);
Expand Down Expand Up @@ -421,11 +427,15 @@ void AddModule(ModuleDefinition md)
}
// return new TypeReference(type.Namespace,type.Name,md,md.TypeSystem.CoreLibrary);
}


internal static TypeReference FindType<T>(this ModuleDefinition md)
{
return FindType(md, typeof(T));
// return new TypeReference(typeof(T).Namespace,typeof(T).Name,md,md.TypeSystem.CoreLibrary);
}


internal static TypeDefinition CreateDelegateType(this ModuleDefinition assembly, string name, TypeDefinition declaringType,
TypeReference returnType, IEnumerable<TypeReference> parameters)
{
Expand Down Expand Up @@ -481,6 +491,8 @@ internal static TypeReference FindType<T>(this ModuleDefinition md)

return dt;
}


static Type voidType = typeof(void);
static Type objType = typeof(object);
static OpCode[] s_ldargs = new[] { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3 };
Expand Down
5 changes: 3 additions & 2 deletions Editor/UnityInjectUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,14 @@ static bool VisitAssembly(string assemblyPath, InjectionInfo[] injections, bool
Debug.Log($"Inject success: {assemblyPath}");
return isWritten;
}
catch
catch (Exception e)
{
Debug.LogException(e);
if (IsEngineAssembly)
{
File.Copy(backPath, assemblyPath, true);
}
throw;
throw e;
}

}
Expand Down
30 changes: 20 additions & 10 deletions Runtime/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace com.bbbirder.injection {
public static class Constants{
public const string InjectedMarkNamespace = "com.bbbirder";
public const string InjectedMarkName = "InjectedMarkAttribute";
public static string GetDelegateTypeName(string methodName)
=> strBuilder.Clear().Append("__").Append(methodName).Append("Delegate").ToString();
namespace com.bbbirder.injection
{
public static class Constants
{
public const string INJECTED_MARK_NAMESPACE = "com.bbbirder";
public const string INJECTED_MARK_NAME = "InjectedMarkAttribute";

public static string GetInjectedFieldName(string methodName)
=> strBuilder.Clear().Append("s_").Append(methodName).Append("_injection").ToString();
public static string GetInjectedFieldName(string methodName, string methodSignature)
=> strBuilder.Clear().Append("_injection_field+").Append(methodName).Append(MD5Hash(methodSignature)).ToString();

public static string GetOriginMethodName(string methodName)
=> strBuilder.Clear().Append("origin_").Append(methodName).ToString();
public static string GetOriginMethodName(string methodName, string methodSignature)
=> strBuilder.Clear().Append("_injection_origin+").Append(methodName).Append(MD5Hash(methodSignature)).ToString();

static string MD5Hash(string rawContent)
{
var md5 = MD5.Create();
var buffer = md5.ComputeHash(Encoding.UTF8.GetBytes(rawContent));
return string.Concat(buffer.Select(b => b.ToString("X")));
}

static StringBuilder strBuilder = new();
}
Expand Down
16 changes: 11 additions & 5 deletions Runtime/FixHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,17 @@ public static void Install(Assembly assembly)
/// <returns></returns>
public static bool IsInjected(Type type)
{
var mark = type.Assembly.GetType($"{Constants.InjectedMarkNamespace}.{Constants.InjectedMarkName}");
var mark = type.Assembly.GetType($"{Constants.INJECTED_MARK_NAMESPACE}.{Constants.INJECTED_MARK_NAME}");
return mark != null;
}

public static MethodInfo GetOriginMethodFor(MethodInfo targetMethod)
{
var oriName = Constants.GetOriginMethodName(targetMethod.Name);
var oriName = Constants.GetOriginMethodName(targetMethod.Name, targetMethod.GetSignature());
return targetMethod.DeclaringType.GetMethod(oriName, bindingFlags);
}
static void FixMethod(InjectionInfo injection)

public static void FixMethod(InjectionInfo injection)
{
injection.onStartFix?.Invoke();
var targetMethod = injection.InjectedMethod;
Expand All @@ -80,7 +81,8 @@ static void FixMethod(InjectionInfo injection)

try
{
sfld = targetType.GetField(Constants.GetInjectedFieldName(methodName), bindingFlags ^ BindingFlags.Instance);
var sfldName = Constants.GetInjectedFieldName(methodName, targetMethod.GetSignature());
sfld = targetType.GetField(sfldName, bindingFlags ^ BindingFlags.Instance);
}
catch (Exception e)
{
Expand Down Expand Up @@ -112,7 +114,8 @@ static void FixMethod(InjectionInfo injection)
}

// set overwrite origin field
var originMethod = targetType.GetMethod(Constants.GetOriginMethodName(methodName), bindingFlags);
var originName = Constants.GetOriginMethodName(methodName, targetMethod.GetSignature());
var originMethod = targetType.GetMethod(originName, bindingFlags);
try
{
var oriDelegate = originMethod.CreateDelegate(sfld.FieldType);
Expand Down Expand Up @@ -218,6 +221,9 @@ public static string GetAssemblyPath(this Assembly assembly)
return null;
}

public static string GetSignature(this MethodBase m)
=> $"{m.Name}({string.Join(",", m.GetParameters().Select(p => p.ParameterType.FullName))})";

static InjectionInfo[] m_allInjections;
public static InjectionInfo[] allInjections => m_allInjections ??= GetAllInjections();

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "com.bbbirder.injection",
"displayName": "Unity Injection",
"description": "Unity注入模块,可以运行时改变被注入函数实现。",
"version": "1.3.21",
"version": "1.3.24",
"hideInEditor": false,
"author": "bbbirder <502100554@qq.com>",
"dependencies": {
Expand Down

0 comments on commit 7a680b6

Please sign in to comment.