Skip to content

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
pardeike committed Jan 24, 2020
1 parent 1877ad2 commit 798915f
Show file tree
Hide file tree
Showing 31 changed files with 767 additions and 658 deletions.
6 changes: 3 additions & 3 deletions Harmony/Extras/DelegateTypeFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ public class DelegateTypeFactory
public DelegateTypeFactory()
{
counter++;
var name = "HarmonyDTFAssembly" + counter;
var name = $"HarmonyDTFAssembly{counter}";
var assembly = PatchTools.DefineDynamicAssembly(name);
module = assembly.DefineDynamicModule("HarmonyDTFModule" + counter);
module = assembly.DefineDynamicModule($"HarmonyDTFModule{counter}");
}

/// <summary>Creates a delegate type for a method</summary>
Expand All @@ -27,7 +27,7 @@ public DelegateTypeFactory()
public Type CreateDelegateType(MethodInfo method)
{
var attr = TypeAttributes.Sealed | TypeAttributes.Public;
var typeBuilder = module.DefineType("HarmonyDTFType" + counter, attr, typeof(MulticastDelegate));
var typeBuilder = module.DefineType($"HarmonyDTFType{counter}", attr, typeof(MulticastDelegate));

var constructor = typeBuilder.DefineConstructor(
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
Expand Down
6 changes: 3 additions & 3 deletions Harmony/Extras/FastAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static InstantiationHandler<T> CreateInstantiationHandler<T>()
typeof(T)));
}

var dynamicMethod = new DynamicMethod("InstantiateObject_" + typeof(T).Name,
var dynamicMethod = new DynamicMethod($"InstantiateObject_{typeof(T).Name}",
MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(T), null, typeof(T),
true);
var generator = dynamicMethod.GetILGenerator();
Expand Down Expand Up @@ -159,12 +159,12 @@ public static InstantiationHandler<T> CreateInstantiationHandler<T>()

static DynamicMethod CreateGetDynamicMethod<T, S>(Type type)
{
return new DynamicMethod("DynamicGet_" + type.Name, typeof(S), new Type[] { typeof(T) }, type, true);
return new DynamicMethod($"DynamicGet_{type.Name}", typeof(S), new Type[] { typeof(T) }, type, true);
}

static DynamicMethod CreateSetDynamicMethod<T, S>(Type type)
{
return new DynamicMethod("DynamicSet_" + type.Name, typeof(void), new Type[] { typeof(T), typeof(S) }, type,
return new DynamicMethod($"DynamicSet_{type.Name}", typeof(void), new Type[] { typeof(T), typeof(S) }, type,
true);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Harmony/Extras/MethodInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public MethodInvoker(bool directBoxValueAccess = false)
/// <returns>The fast invocation handler</returns>
public FastInvokeHandler Handler(MethodInfo methodInfo, Module module)
{
var dynamicMethod = new DynamicMethod("FastInvoke_" + methodInfo.Name + "_" + (directBoxValueAccess ? "direct" : "indirect"), typeof(object), new Type[] { typeof(object), typeof(object[]) }, module, true);
var dynamicMethod = new DynamicMethod($"FastInvoke_{methodInfo.Name}_{(directBoxValueAccess ? "direct" : "indirect")}", typeof(object), new Type[] { typeof(object), typeof(object[]) }, module, true);
var il = dynamicMethod.GetILGenerator();

if (!methodInfo.IsStatic)
Expand Down
10 changes: 5 additions & 5 deletions Harmony/Internal/Emitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ internal static string FormatArgument(object argument)
return ((MethodInfo)argument).FullDescription();

if (type == typeof(string))
return "\"" + argument + "\"";
return $"\"{argument}\"";
if (type == typeof(Label))
return "Label" + ((Label)argument).GetHashCode();
return $"Label{((Label)argument).GetHashCode()}";
if (type == typeof(Label[]))
return "Labels" + string.Join(",", ((Label[])argument).Select(l => l.GetHashCode().ToString()).ToArray());
return $"Labels{string.Join(",", ((Label[])argument).Select(l => l.GetHashCode().ToString()).ToArray())}";
if (type == typeof(LocalBuilder))
return ((LocalBuilder)argument).LocalIndex + " (" + ((LocalBuilder)argument).LocalType + ")";
return $"{((LocalBuilder)argument).LocalIndex} ({((LocalBuilder)argument).LocalType})";

return argument.ToString().Trim();
}
Expand Down Expand Up @@ -111,7 +111,7 @@ internal static void MarkBlockBefore(ILGenerator il, ExceptionBlock block, out L
FileLog.ChangeIndent(-1);
FileLog.LogBuffered("} // end try");

FileLog.LogBuffered(".catch " + block.catchType);
FileLog.LogBuffered($".catch {block.catchType}");
FileLog.LogBuffered("{");
FileLog.ChangeIndent(1);
}
Expand Down
9 changes: 3 additions & 6 deletions Harmony/Internal/ILInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public override string ToString()
var instruction = "";

AppendLabel(ref instruction, this);
instruction = instruction + ": " + opcode.Name;
instruction += $": {opcode.Name}";

if (operand == null)
return instruction;
Expand All @@ -103,7 +103,7 @@ public override string ToString()
break;

case OperandType.InlineString:
instruction = instruction + "\"" + operand + "\"";
instruction += $"\"{operand}\"";
break;

default:
Expand All @@ -117,10 +117,7 @@ public override string ToString()
static void AppendLabel(ref string str, object argument)
{
var instruction = argument as ILInstruction;
if (instruction != null)
str = str + "IL_" + instruction.offset.ToString("X4");
else
str = str + "IL_" + argument;
str += $"IL_{instruction?.offset.ToString("X4") ?? argument}";
}
}
}
22 changes: 11 additions & 11 deletions Harmony/Internal/MethodCopier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ internal MethodBodyReader(MethodBase method, ILGenerator generator)

var body = method.GetMethodBody();
if (body == null)
throw new ArgumentException("Method " + method.FullDescription() + " has no body");
throw new ArgumentException($"Method {method.FullDescription()} has no body");

var bytes = body.GetILAsByteArray();
if (bytes == null)
throw new ArgumentException("Can not get IL bytes of method " + method.FullDescription());
throw new ArgumentException($"Can not get IL bytes of method {method.FullDescription()}");
ilBytes = new ByteBuffer(bytes);
ilInstructions = new List<ILInstruction>((bytes.Length + 1) / 2);

Expand Down Expand Up @@ -338,8 +338,8 @@ internal void FinalizeILCodes(List<MethodInfo> transpilers, List<Label> endLabel
// TODO the following will fail because we do not convert the token (operand)
// All the decompilers can show the arguments correctly, we just need to find out how
//
if (operand == null) throw new Exception("Wrong null argument: " + codeInstruction);
if ((operand is int) == false) throw new Exception("Wrong Emit argument type " + operand.GetType() + " in " + codeInstruction);
if (operand == null) throw new Exception($"Wrong null argument: {codeInstruction}");
if ((operand is int) == false) throw new Exception($"Wrong Emit argument type {operand.GetType()} in {codeInstruction}");
Emitter.Emit(generator, code, (int)operand);
/*
Expand All @@ -357,10 +357,10 @@ internal void FinalizeILCodes(List<MethodInfo> transpilers, List<Label> endLabel
break;
default:
if (operand == null) throw new Exception("Wrong null argument: " + codeInstruction);
if (operand == null) throw new Exception($"Wrong null argument: {codeInstruction}");
var emitMethod = EmitMethodForType(operand.GetType());
if (emitMethod == null) throw new Exception("Unknown Emit argument type " + operand.GetType() + " in " + codeInstruction);
if (Harmony.DEBUG) FileLog.LogBuffered(Emitter.CodePos(generator) + code + " " + Emitter.FormatArgument(operand));
if (emitMethod == null) throw new Exception($"Unknown Emit argument type {operand.GetType()} in {codeInstruction}");
if (Harmony.DEBUG) FileLog.LogBuffered($"{Emitter.CodePos(generator)}{code} {Emitter.FormatArgument(operand)}");
_ = emitMethod.Invoke(generator, new object[] { code, operand });
break;
}
Expand Down Expand Up @@ -501,8 +501,8 @@ void ReadOperand(ILInstruction instruction)
var bytes = module.ResolveSignature(val);
instruction.operand = bytes;
instruction.argument = bytes;
Debugger.Log(0, "TEST", "METHOD " + method.FullDescription() + "\n");
Debugger.Log(0, "TEST", "Signature = " + bytes.Select(b => string.Format("0x{0:x02}", b)).Aggregate((a, b) => a + " " + b) + "\n");
Debugger.Log(0, "TEST", $"METHOD {method.FullDescription()}\n");
Debugger.Log(0, "TEST", $"Signature = {bytes.Select(b => string.Format("0x{0:x02}", b)).Aggregate((a, b) => a + " " + b)}\n");
Debugger.Break();
break;
}
Expand Down Expand Up @@ -603,7 +603,7 @@ ILInstruction GetInstruction(int offset, bool isEndOfInstruction)
{
var lastInstructionIndex = ilInstructions.Count - 1;
if (offset < 0 || offset > ilInstructions[lastInstructionIndex].offset)
throw new Exception("Instruction offset " + offset + " is outside valid range 0 - " + ilInstructions[lastInstructionIndex].offset);
throw new Exception($"Instruction offset {offset} is outside valid range 0 - {ilInstructions[lastInstructionIndex].offset}");

var min = 0;
var max = lastInstructionIndex;
Expand All @@ -629,7 +629,7 @@ ILInstruction GetInstruction(int offset, bool isEndOfInstruction)
min = mid + 1;
}

throw new Exception("Cannot find instruction for " + offset.ToString("X4"));
throw new Exception($"Cannot find instruction for {offset.ToString("X4")}");
}

static bool TargetsLocalVariable(OpCode opcode)
Expand Down
26 changes: 13 additions & 13 deletions Harmony/Internal/MethodPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ public static DynamicMethod CreatePatchedMethod(MethodBase original, MethodBase

if (Harmony.DEBUG)
{
FileLog.LogBuffered("### Patch " + original.FullDescription());
FileLog.LogBuffered($"### Patch {original.FullDescription()}");
FileLog.FlushBuffer();
}

var idx = prefixes.Count() + postfixes.Count() + finalizers.Count();
var firstArgIsReturnBuffer = NativeThisPointer.NeedsNativeThisPointerFix(original);
var returnType = AccessTools.GetReturnedType(original);
var hasFinalizers = finalizers.Any();
var patch = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx);
var patch = DynamicTools.CreateDynamicMethod(original, $"_Patch{idx}");
if (patch == null)
return null;

Expand Down Expand Up @@ -167,7 +167,7 @@ public static DynamicMethod CreatePatchedMethod(MethodBase original, MethodBase
}
catch (Exception ex)
{
var exceptionString = "Exception from HarmonyInstance \"" + harmonyInstanceID + "\" patching " + original.FullDescription() + ": " + ex;
var exceptionString = $"Exception from HarmonyInstance \"{harmonyInstanceID}\" patching {original.FullDescription()}: {ex}";
if (Harmony.DEBUG)
{
var savedIndentLevel = FileLog.indentLevel;
Expand Down Expand Up @@ -371,13 +371,13 @@ static void EmitCallParameter(ILGenerator il, MethodBase original, MethodInfo pa
{
fieldInfo = AccessTools.DeclaredField(original.DeclaringType, int.Parse(fieldName));
if (fieldInfo == null)
throw new ArgumentException("No field found at given index in class " + original.DeclaringType.FullName, fieldName);
throw new ArgumentException($"No field found at given index in class {original.DeclaringType.FullName}", fieldName);
}
else
{
fieldInfo = AccessTools.DeclaredField(original.DeclaringType, fieldName);
if (fieldInfo == null)
throw new ArgumentException("No such field defined in class " + original.DeclaringType.FullName, fieldName);
throw new ArgumentException($"No such field defined in class {original.DeclaringType.FullName}", fieldName);
}

if (fieldInfo.IsStatic)
Expand Down Expand Up @@ -406,12 +406,12 @@ static void EmitCallParameter(ILGenerator il, MethodBase original, MethodInfo pa
{
var returnType = AccessTools.GetReturnedType(original);
if (returnType == typeof(void))
throw new Exception("Cannot get result from void method " + original.FullDescription());
throw new Exception($"Cannot get result from void method {original.FullDescription()}");
var resultType = patchParam.ParameterType;
if (resultType.IsByRef)
resultType = resultType.GetElementType();
if (resultType.IsAssignableFrom(returnType) == false)
throw new Exception("Cannot assign method return type " + returnType.FullName + " to " + RESULT_VAR + " type " + resultType.FullName + " for method " + original.FullDescription());
throw new Exception($"Cannot assign method return type {returnType.FullName} to {RESULT_VAR} type {resultType.FullName} for method {original.FullDescription()}");
var ldlocCode = patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
Emitter.Emit(il, ldlocCode, variables[RESULT_VAR]);
continue;
Expand All @@ -430,14 +430,14 @@ static void EmitCallParameter(ILGenerator il, MethodBase original, MethodInfo pa
{
var val = patchParam.Name.Substring(PARAM_INDEX_PREFIX.Length);
if (!int.TryParse(val, out idx))
throw new Exception("Parameter " + patchParam.Name + " does not contain a valid index");
throw new Exception($"Parameter {patchParam.Name} does not contain a valid index");
if (idx < 0 || idx >= originalParameters.Length)
throw new Exception("No parameter found at index " + idx);
throw new Exception($"No parameter found at index {idx}");
}
else
{
idx = GetArgumentIndex(patch, originalParameterNames, patchParam);
if (idx == -1) throw new Exception("Parameter \"" + patchParam.Name + "\" not found in method " + original.FullDescription());
if (idx == -1) throw new Exception($"Parameter \"{patchParam.Name}\" not found in method {original.FullDescription()}");
}

// original -> patch opcode
Expand Down Expand Up @@ -482,7 +482,7 @@ static bool AddPrefixes(ILGenerator il, MethodBase original, List<MethodInfo> pr
if (fix.ReturnType != typeof(void))
{
if (fix.ReturnType != typeof(bool))
throw new Exception("Prefix patch " + fix + " has not \"bool\" or \"void\" return type: " + fix.ReturnType);
throw new Exception($"Prefix patch {fix} has not \"bool\" or \"void\" return type: {fix.ReturnType}");
Emitter.Emit(il, OpCodes.Brfalse, label);
canHaveJump = true;
}
Expand All @@ -506,9 +506,9 @@ static void AddPostfixes(ILGenerator il, MethodBase original, List<MethodInfo> p
if (!hasPassThroughResultParam)
{
if (firstFixParam != null)
throw new Exception("Return type of pass through postfix " + fix + " does not match type of its first parameter");
throw new Exception($"Return type of pass through postfix {fix} does not match type of its first parameter");
throw new Exception("Postfix patch " + fix + " must have a \"void\" return type");
throw new Exception($"Postfix patch {fix} must have a \"void\" return type");
}
}
});
Expand Down
8 changes: 4 additions & 4 deletions Harmony/Internal/PatchFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ internal static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patch
var sortedFinalizers = GetSortedPatchMethods(original, patchInfo.finalizers);

var replacement = MethodPatcher.CreatePatchedMethod(original, null, instanceID, sortedPrefixes, sortedPostfixes, sortedTranspilers, sortedFinalizers);
if (replacement == null) throw new MissingMethodException("Cannot create dynamic replacement for " + original.FullDescription());
if (replacement == null) throw new MissingMethodException($"Cannot create dynamic replacement for {original.FullDescription()}");

var errorString = Memory.DetourMethod(original, replacement);
if (errorString != null)
throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
throw new FormatException($"Method {original.FullDescription()} cannot be patched. Reason: {errorString}");

PatchTools.RememberObject(original, replacement); // no gc for new value + release old value to gc

Expand All @@ -170,11 +170,11 @@ internal static void ReversePatch(MethodInfo standin, MethodBase original, strin
transpilers.Add(transpiler);

var replacement = MethodPatcher.CreatePatchedMethod(standin, original, instanceID, emptyFixes, emptyFixes, transpilers, emptyFixes);
if (replacement == null) throw new MissingMethodException("Cannot create dynamic replacement for " + standin.FullDescription());
if (replacement == null) throw new MissingMethodException($"Cannot create dynamic replacement for {standin.FullDescription()}");

var errorString = Memory.DetourMethod(standin, replacement);
if (errorString != null)
throw new FormatException("Method " + standin.FullDescription() + " cannot be patched. Reason: " + errorString);
throw new FormatException($"Method {standin.FullDescription()} cannot be patched. Reason: {errorString}");

PatchTools.RememberObject(standin, replacement);
}
Expand Down

0 comments on commit 798915f

Please sign in to comment.