Skip to content

Commit

Permalink
Small cleanup, fixed InjectWith signature
Browse files Browse the repository at this point in the history
  • Loading branch information
ghorsington committed May 22, 2017
1 parent 32f2573 commit 64d5831
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 87 deletions.
6 changes: 3 additions & 3 deletions Mono.Cecil.Inject/ILUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public static Instruction CopyInstruction(Instruction ins)
result = Instruction.Create(ins.OpCode);
else
result =
(Instruction)
typeof(Instruction).GetMethod("Create", new[] {typeof(OpCode), ins.Operand.GetType()})
.Invoke(null, new[] {ins.OpCode, ins.Operand});
(Instruction)
typeof(Instruction).GetMethod("Create", new[] {typeof(OpCode), ins.Operand.GetType()})
.Invoke(null, new[] {ins.OpCode, ins.Operand});
return result;
}

Expand Down
12 changes: 7 additions & 5 deletions Mono.Cecil.Inject/InjectFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,14 +237,16 @@ public InjectValues(InjectFlags flags)
/// <returns>The combination of the properties in a single <see cref="InjectFlags" /> value to use in injection.</returns>
public InjectFlags GetCombinedFlags()
{
return (ModifyReturn ? InjectFlags.ModifyReturn : 0) | (TagType == PassTagType.Int32
return (ModifyReturn ? InjectFlags.ModifyReturn : 0) |
(TagType == PassTagType.Int32
? InjectFlags.PassTag
: TagType == PassTagType.String
? InjectFlags.PassStringTag
: 0)
| (PassInvokingInstance ? InjectFlags.PassInvokingInstance : 0)
| (PassFields ? InjectFlags.PassFields : 0) | (PassLocals ? InjectFlags.PassLocals : 0)
| (ParameterType == PassParametersType.ByValue
: 0) |
(PassInvokingInstance ? InjectFlags.PassInvokingInstance : 0) |
(PassFields ? InjectFlags.PassFields : 0) |
(PassLocals ? InjectFlags.PassLocals : 0) |
(ParameterType == PassParametersType.ByValue
? InjectFlags.PassParametersVal
: (ParameterType == PassParametersType.ByReference ? InjectFlags.PassParametersRef : 0));
}
Expand Down
104 changes: 60 additions & 44 deletions Mono.Cecil.Inject/InjectionDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ public InjectionDefinition(MethodDefinition injectTarget,
int[] localVarIDs = null,
params FieldDefinition[] memberReferences)
{
ParameterCount = VerifyInjectionDefinition(injectMethod, injectTarget, flags, localVarIDs,
ParameterCount = VerifyInjectionDefinition(injectMethod,
injectTarget,
flags,
localVarIDs,
memberReferences);
InjectMethod = injectMethod;
InjectTarget = injectTarget;
Expand Down Expand Up @@ -140,19 +143,19 @@ internal static InjectionDefinition FindInjectionDefinition(TypeDefinition type,
int parameterCount = 0;

MethodDefinition injection =
type.Methods.FirstOrDefault(m =>
{
try
{
parameterCount = VerifyInjectionDefinition(m, target, flags, localVarIDs, memberReferences);
}
catch (InjectionDefinitionException e)
type.Methods.FirstOrDefault(m =>
{
Logger.LogLine(LogMask.GetInjectionMethod, e.Message);
return false;
}
return true;
});
try
{
parameterCount = VerifyInjectionDefinition(m, target, flags, localVarIDs, memberReferences);
}
catch (InjectionDefinitionException e)
{
Logger.LogLine(LogMask.GetInjectionMethod, e.Message);
return false;
}
return true;
});

if (injection == null)
{
Expand All @@ -178,8 +181,10 @@ private static void Assert(bool val, string message)
throw new InjectionDefinitionException(message);
}

private static int VerifyInjectionDefinition(MethodDefinition injectMethod, MethodDefinition injectTarget,
InjectFlags flags, int[] localVarIDs = null,
private static int VerifyInjectionDefinition(MethodDefinition injectMethod,
MethodDefinition injectTarget,
InjectFlags flags,
int[] localVarIDs = null,
params FieldDefinition[] memberReferences)
{
Assert(
Expand All @@ -201,22 +206,25 @@ private static int VerifyInjectionDefinition(MethodDefinition injectMethod, Meth
!hFlags.PassFields || memberReferences != null,
$"Supposed to pass member fields, but {nameof(memberReferences)} is empty!");

int prefixCount = Convert.ToInt32(hFlags.PassTag) + Convert.ToInt32(hFlags.PassInvokingInstance)
+ Convert.ToInt32(hFlags.ModifyReturn && !isVoid);
int prefixCount = Convert.ToInt32(hFlags.PassTag) +
Convert.ToInt32(hFlags.PassInvokingInstance) +
Convert.ToInt32(hFlags.ModifyReturn && !isVoid);
int localsCount = hFlags.PassLocals ? localVarIDs.Length : 0;
int memberRefCount = hFlags.PassFields ? memberReferences.Length : 0;
int paramCount = hFlags.PassParameters ? injectTarget.Parameters.Count : 0;
int parameters = injectMethod.Parameters.Count - prefixCount - localsCount - memberRefCount;

Assert(
hFlags.PassParameters && 0 < parameters && parameters <= injectTarget.Parameters.Count
|| !hFlags.PassParameters && parameters == 0,
hFlags.PassParameters && 0 < parameters && parameters <= injectTarget.Parameters.Count ||
!hFlags.PassParameters && parameters == 0,
$@"The injection method has a wrong number of parameters! Check that the provided target method, local variables, member references and injection flags add up to the right number of parameters.
Needed parameters: Prefix: {prefixCount}, Locals: {localsCount}, Members: {memberRefCount}, Parameters: {
(hFlags.PassParameters ? "between 1 and " + paramCount : "0")
}, TOTAL: {
(hFlags.PassParameters ? $"between {prefixCount + localsCount + memberRefCount + 1} and " : "")
}{prefixCount + localsCount + memberRefCount + paramCount}.
(hFlags.PassParameters ? "between 1 and " + paramCount : "0")
}, TOTAL: {
(hFlags.PassParameters
? $"between {prefixCount + localsCount + memberRefCount + 1} and "
: "")
}{prefixCount + localsCount + memberRefCount + paramCount}.
Injection has {injectMethod.Parameters.Count} parameters.");

TypeComparer comparer = TypeComparer.Instance;
Expand Down Expand Up @@ -247,11 +255,12 @@ private static int VerifyInjectionDefinition(MethodDefinition injectMethod, Meth
injectMethod.ReturnType.FullName == "System.Boolean",
"The injection method must return a boolean in order to alter the return value.");
Assert(
isVoid
|| comparer.Equals(
isVoid ||
comparer.Equals(
injectMethod
.Parameters[Convert.ToInt32(hFlags.PassTag) + Convert.ToInt32(hFlags.PassInvokingInstance)]
.ParameterType,
.Parameters[Convert.ToInt32(hFlags.PassTag) +
Convert.ToInt32(hFlags.PassInvokingInstance)]
.ParameterType,
new ByReferenceType(injectTarget.ReturnType)),
"Supposed to modify the return value, but the provided return type does not match with the return type of the target method! Also make sure the type is passed by reference (out/ref).");
}
Expand All @@ -267,11 +276,15 @@ private static int VerifyInjectionDefinition(MethodDefinition injectMethod, Meth
"Supposed to receive local references, but the provided local variable index/indices do not exist in the target method!");
Assert(
injectMethod.Parameters.Slice(prefixCount, localsCount)
.Select((p, i) => new {param = p, index = localVarIDs[i]})
.Select((p, i) => new
{
param = p,
index = localVarIDs[i]
})
.All(
t =>
t.param.ParameterType.IsByReference
&& comparer.Equals(
t.param.ParameterType.IsByReference &&
comparer.Equals(
t.param.ParameterType,
new ByReferenceType(injectTarget.Body.Variables[t.index].VariableType))),
"Supposed to receive local references, but the types between injection method and target method mismatch. Also make sure they are passed by reference (ref/out).");
Expand All @@ -286,13 +299,13 @@ private static int VerifyInjectionDefinition(MethodDefinition injectMethod, Meth
Assert(
memberReferences.All(
m =>
m.DeclaringType.FullName == injectTarget.DeclaringType.FullName
&& m.DeclaringType.BaseType.FullName == injectTarget.DeclaringType.BaseType.FullName),
m.DeclaringType.FullName == injectTarget.DeclaringType.FullName &&
m.DeclaringType.BaseType.FullName == injectTarget.DeclaringType.BaseType.FullName),
$"The provided member fields do not belong to {injectTarget.DeclaringType}");

IEnumerable<TypeReference> paramRefs =
injectMethod.Parameters.Slice(prefixCount + localsCount, memberRefCount)
.Select(p => p.ParameterType);
injectMethod.Parameters.Slice(prefixCount + localsCount, memberRefCount)
.Select(p => p.ParameterType);
IEnumerable<TypeReference> typeReferences = paramRefs as TypeReference[] ?? paramRefs.ToArray();

Assert(
Expand All @@ -313,15 +326,16 @@ private static int VerifyInjectionDefinition(MethodDefinition injectMethod, Meth
"The injection and target methods have mismatching specification of generic parameters!");

Assert(
!injectMethod.HasGenericParameters
|| injectMethod.GenericParameters.Count <= injectTarget.GenericParameters.Count +
!injectMethod.HasGenericParameters ||
injectMethod.GenericParameters.Count <=
injectTarget.GenericParameters.Count +
injectTarget.DeclaringType.GenericParameters.Count,
"The injection and target methods have a mismatching number of generic parameters! The injection method must have less or the same number of generic parameters as the target!");

Assert(
!hFlags.PassParametersByRef
|| injectMethod.Parameters.Skip(prefixCount + localsCount + memberRefCount)
.All(p => p.ParameterType.IsByReference),
!hFlags.PassParametersByRef ||
injectMethod.Parameters.Skip(prefixCount + localsCount + memberRefCount)
.All(p => p.ParameterType.IsByReference),
"Supposed to pass target method parameters by reference, but the provided parameters in the injection method are not of a reference type (ref).");

Assert(
Expand Down Expand Up @@ -369,7 +383,8 @@ public void Inject(int startCode = 0, object token = null, InjectDirection direc
/// parameter to the injection method.
/// </param>
/// <param name="direction">The direction in which to insert the call: either above the start code or below it.</param>
public void Inject(Instruction startCode, object token = null,
public void Inject(Instruction startCode,
object token = null,
InjectDirection direction = InjectDirection.Before)
{
InjectValues flags = Flags.ToValues();
Expand Down Expand Up @@ -397,10 +412,11 @@ public void Inject(Instruction startCode, object token = null,
MethodReference hookRef = InjectTarget.Module.Import(InjectMethod);

// If the hook is generic but not instantiated fully, attempt to fill in the generic arguments with the ones specified in the target method/class
if (hookRef.HasGenericParameters && (!hookRef.IsGenericInstance ||
hookRef.IsGenericInstance &&
((GenericInstanceMethod) hookRef).GenericArguments.Count <
hookRef.GenericParameters.Count))
if (hookRef.HasGenericParameters &&
(!hookRef.IsGenericInstance ||
hookRef.IsGenericInstance &&
((GenericInstanceMethod) hookRef).GenericArguments.Count <
hookRef.GenericParameters.Count))
{
GenericInstanceMethod genericInjectMethod = new GenericInstanceMethod(hookRef);
foreach (GenericParameter genericParameter in InjectMethod.GenericParameters)
Expand Down
2 changes: 1 addition & 1 deletion Mono.Cecil.Inject/MethodDefinitionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static InjectionDefinition GetInjector(this MethodDefinition target,
public static void InjectWith(this MethodDefinition method,
MethodDefinition injectionMethod,
int codeOffset = 0,
int tag = 0,
object tag = null,
InjectFlags flags = InjectFlags.None,
InjectDirection dir = InjectDirection.Before,
int[] localsID = null,
Expand Down
5 changes: 4 additions & 1 deletion Mono.Cecil.Inject/ParamHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ public static Type CreateDummyType(string name)
/// </returns>
public static TypeReference CreateGeneric(string name)
{
return new GenericParameter(new TypeReference(name, null, resolverModule, null)) {Name = name};
return new GenericParameter(new TypeReference(name, null, resolverModule, null))
{
Name = name
};
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Mono.Cecil.Inject/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

[assembly: AssemblyVersion("1.2.5.0")]
[assembly: AssemblyFileVersion("1.2.5.0")]
[assembly: AssemblyVersion("1.2.5.1")]
[assembly: AssemblyFileVersion("1.2.5.1")]
43 changes: 26 additions & 17 deletions Mono.Cecil.Inject/TypeDefinitionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,12 @@ public static InjectionDefinition GetInjectionMethod(this TypeDefinition type,
params FieldDefinition[] memberReferences)
{
return InjectionDefinition.FindInjectionDefinition(
type, name, target, flags, localVarIDs, memberReferences);
type,
name,
target,
flags,
localVarIDs,
memberReferences);
}


Expand Down Expand Up @@ -199,11 +204,11 @@ public static MethodDefinition GetMethod(this TypeDefinition self, string method
public static MethodDefinition GetMethod(this TypeDefinition self, string methodName, params string[] types)
{
return
self.Methods.FirstOrDefault(
m =>
m.Name == methodName
&& types.SequenceEqual(m.Parameters.Select(p => p.ParameterType.FullName),
StringComparer.InvariantCulture));
self.Methods.FirstOrDefault(
m =>
m.Name == methodName &&
types.SequenceEqual(m.Parameters.Select(p => p.ParameterType.FullName),
StringComparer.InvariantCulture));
}

/// <summary>
Expand Down Expand Up @@ -263,13 +268,14 @@ public static MethodDefinition[] MatchMethod(this TypeDefinition self,
params string[] paramTypes)
{
return
self.Methods.Where(
m =>
m.Name == methodName && paramTypes.Length <= m.Parameters.Count
&& paramTypes.SequenceEqual(
m.Parameters.Take(paramTypes.Length).Select(p => p.ParameterType.FullName),
StringComparer.InvariantCulture))
.ToArray();
self.Methods.Where(
m =>
m.Name == methodName &&
paramTypes.Length <= m.Parameters.Count &&
paramTypes.SequenceEqual(
m.Parameters.Take(paramTypes.Length).Select(p => p.ParameterType.FullName),
StringComparer.InvariantCulture))
.ToArray();
}
}

Expand All @@ -292,8 +298,11 @@ public bool Equals(TypeReference x, TypeReference y)


if (
!(x.Name == y.Name && x.Namespace == y.Namespace && x.IsArray == y.IsArray
&& x.IsGenericInstance == y.IsGenericInstance && x.IsByReference == y.IsByReference))
!(x.Name == y.Name &&
x.Namespace == y.Namespace &&
x.IsArray == y.IsArray &&
x.IsGenericInstance == y.IsGenericInstance &&
x.IsByReference == y.IsByReference))
return false;
if (!x.IsGenericInstance)
return true;
Expand All @@ -305,8 +314,8 @@ public bool Equals(TypeReference x, TypeReference y)
$"Generic arg count| x: {gx.GenericArguments.Count}, y: {gy.GenericArguments.Count}");
Logger.LogLine(LogMask.TypeCompare, "Comparing generics");

return gx.GenericArguments.Count == gy.GenericArguments.Count
&& !gx.GenericArguments.Where((t, i) => !Equals(t, gy.GenericArguments[i])).Any();
return gx.GenericArguments.Count == gy.GenericArguments.Count &&
!gx.GenericArguments.Where((t, i) => !Equals(t, gy.GenericArguments[i])).Any();
}

public int GetHashCode(TypeReference obj)
Expand Down
Loading

0 comments on commit 64d5831

Please sign in to comment.