SMAPI Android Transportation
This commit is contained in:
parent
44ddc4ca42
commit
589d48a969
1
SMAPI
1
SMAPI
|
@ -1 +0,0 @@
|
|||
Subproject commit 9e521091fe4b13a9091bcb30c9f73ef210ace2dd
|
|
@ -0,0 +1,325 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public enum MethodType
|
||||
{
|
||||
Normal,
|
||||
Getter,
|
||||
Setter,
|
||||
Constructor,
|
||||
StaticConstructor
|
||||
}
|
||||
|
||||
[Obsolete("This enum will be removed in the next major version. To define special methods, use MethodType")]
|
||||
public enum PropertyMethod
|
||||
{
|
||||
Getter,
|
||||
Setter
|
||||
}
|
||||
|
||||
public enum ArgumentType
|
||||
{
|
||||
Normal,
|
||||
Ref,
|
||||
Out,
|
||||
Pointer
|
||||
}
|
||||
|
||||
public enum HarmonyPatchType
|
||||
{
|
||||
All,
|
||||
Prefix,
|
||||
Postfix,
|
||||
Transpiler
|
||||
}
|
||||
|
||||
public class HarmonyAttribute : Attribute
|
||||
{
|
||||
public HarmonyMethod info = new HarmonyMethod();
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class HarmonyPatch : HarmonyAttribute
|
||||
{
|
||||
// no argument (for use with TargetMethod)
|
||||
|
||||
public HarmonyPatch()
|
||||
{
|
||||
}
|
||||
|
||||
// starting with 'Type'
|
||||
|
||||
public HarmonyPatch(Type declaringType)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, Type[] argumentTypes)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, string methodName)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodName = methodName;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, string methodName, params Type[] argumentTypes)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodName = methodName;
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodName = methodName;
|
||||
ParseSpecialArguments(argumentTypes, argumentVariations);
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, MethodType methodType)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodType = methodType;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, MethodType methodType, params Type[] argumentTypes)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodType = methodType;
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodType = methodType;
|
||||
ParseSpecialArguments(argumentTypes, argumentVariations);
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type declaringType, string propertyName, MethodType methodType)
|
||||
{
|
||||
info.declaringType = declaringType;
|
||||
info.methodName = propertyName;
|
||||
info.methodType = methodType;
|
||||
}
|
||||
|
||||
// starting with 'string'
|
||||
|
||||
public HarmonyPatch(string methodName)
|
||||
{
|
||||
info.methodName = methodName;
|
||||
}
|
||||
|
||||
public HarmonyPatch(string methodName, params Type[] argumentTypes)
|
||||
{
|
||||
info.methodName = methodName;
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
info.methodName = methodName;
|
||||
ParseSpecialArguments(argumentTypes, argumentVariations);
|
||||
}
|
||||
|
||||
public HarmonyPatch(string propertyName, MethodType methodType)
|
||||
{
|
||||
info.methodName = propertyName;
|
||||
info.methodType = methodType;
|
||||
}
|
||||
|
||||
// starting with 'MethodType'
|
||||
|
||||
public HarmonyPatch(MethodType methodType)
|
||||
{
|
||||
info.methodType = methodType;
|
||||
}
|
||||
|
||||
public HarmonyPatch(MethodType methodType, params Type[] argumentTypes)
|
||||
{
|
||||
info.methodType = methodType;
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
info.methodType = methodType;
|
||||
ParseSpecialArguments(argumentTypes, argumentVariations);
|
||||
}
|
||||
|
||||
// starting with 'Type[]'
|
||||
|
||||
public HarmonyPatch(Type[] argumentTypes)
|
||||
{
|
||||
info.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
public HarmonyPatch(Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
ParseSpecialArguments(argumentTypes, argumentVariations);
|
||||
}
|
||||
|
||||
// Obsolete attributes
|
||||
|
||||
[Obsolete("This attribute will be removed in the next major version. Use HarmonyPatch together with MethodType.Getter or MethodType.Setter instead")]
|
||||
public HarmonyPatch(string propertyName, PropertyMethod type)
|
||||
{
|
||||
info.methodName = propertyName;
|
||||
info.methodType = type == PropertyMethod.Getter ? MethodType.Getter : MethodType.Setter;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void ParseSpecialArguments(Type[] argumentTypes, ArgumentType[] argumentVariations)
|
||||
{
|
||||
if (argumentVariations == null || argumentVariations.Length == 0)
|
||||
{
|
||||
info.argumentTypes = argumentTypes;
|
||||
return;
|
||||
}
|
||||
|
||||
if (argumentTypes.Length < argumentVariations.Length)
|
||||
throw new ArgumentException("argumentVariations contains more elements than argumentTypes", nameof(argumentVariations));
|
||||
|
||||
var types = new List<Type>();
|
||||
for (var i = 0; i < argumentTypes.Length; i++)
|
||||
{
|
||||
var type = argumentTypes[i];
|
||||
switch (argumentVariations[i])
|
||||
{
|
||||
case ArgumentType.Ref:
|
||||
case ArgumentType.Out:
|
||||
type = type.MakeByRefType();
|
||||
break;
|
||||
case ArgumentType.Pointer:
|
||||
type = type.MakePointerType();
|
||||
break;
|
||||
}
|
||||
types.Add(type);
|
||||
}
|
||||
info.argumentTypes = types.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class HarmonyPatchAll : HarmonyAttribute
|
||||
{
|
||||
public HarmonyPatchAll()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class HarmonyPriority : HarmonyAttribute
|
||||
{
|
||||
public HarmonyPriority(int prioritiy)
|
||||
{
|
||||
info.prioritiy = prioritiy;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class HarmonyBefore : HarmonyAttribute
|
||||
{
|
||||
public HarmonyBefore(params string[] before)
|
||||
{
|
||||
info.before = before;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class HarmonyAfter : HarmonyAttribute
|
||||
{
|
||||
public HarmonyAfter(params string[] after)
|
||||
{
|
||||
info.after = after;
|
||||
}
|
||||
}
|
||||
|
||||
// If you don't want to use the special method names you can annotate
|
||||
// using the following attributes:
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyPrepare : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyCleanup : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyTargetMethod : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyTargetMethods : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyPrefix : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyPostfix : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class HarmonyTranspiler : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class HarmonyArgument : Attribute
|
||||
{
|
||||
public string OriginalName { get; private set; }
|
||||
public int Index { get; private set; }
|
||||
public string NewName { get; private set; }
|
||||
|
||||
public HarmonyArgument(string originalName) : this(originalName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public HarmonyArgument(int index) : this(index, null)
|
||||
{
|
||||
}
|
||||
|
||||
public HarmonyArgument(string originalName, string newName)
|
||||
{
|
||||
OriginalName = originalName;
|
||||
Index = -1;
|
||||
NewName = newName;
|
||||
}
|
||||
|
||||
public HarmonyArgument(int index, string name)
|
||||
{
|
||||
OriginalName = null;
|
||||
Index = index;
|
||||
NewName = name;
|
||||
}
|
||||
}
|
||||
|
||||
// This attribute is for Harmony patching itself to the latest
|
||||
//
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)]
|
||||
internal class UpgradeToLatestVersion : Attribute
|
||||
{
|
||||
public int version;
|
||||
|
||||
public UpgradeToLatestVersion(int version)
|
||||
{
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using Harmony.ILCopying;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class CodeInstruction
|
||||
{
|
||||
public OpCode opcode;
|
||||
public object operand;
|
||||
public List<Label> labels = new List<Label>();
|
||||
public List<ExceptionBlock> blocks = new List<ExceptionBlock>();
|
||||
|
||||
public CodeInstruction(OpCode opcode, object operand = null)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
public CodeInstruction(CodeInstruction instruction)
|
||||
{
|
||||
opcode = instruction.opcode;
|
||||
operand = instruction.operand;
|
||||
labels = instruction.labels.ToArray().ToList();
|
||||
}
|
||||
|
||||
public CodeInstruction Clone()
|
||||
{
|
||||
return new CodeInstruction(this) { labels = new List<Label>() };
|
||||
}
|
||||
|
||||
public CodeInstruction Clone(OpCode opcode)
|
||||
{
|
||||
var instruction = new CodeInstruction(this) { labels = new List<Label>() };
|
||||
instruction.opcode = opcode;
|
||||
return instruction;
|
||||
}
|
||||
|
||||
public CodeInstruction Clone(OpCode opcode, object operand)
|
||||
{
|
||||
var instruction = new CodeInstruction(this) { labels = new List<Label>() };
|
||||
instruction.opcode = opcode;
|
||||
instruction.operand = operand;
|
||||
return instruction;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var list = new List<string>();
|
||||
foreach (var label in labels)
|
||||
list.Add("Label" + label.GetHashCode());
|
||||
foreach (var block in blocks)
|
||||
list.Add("EX_" + block.blockType.ToString().Replace("Block", ""));
|
||||
|
||||
var extras = list.Count > 0 ? " [" + string.Join(", ", list.ToArray()) + "]" : "";
|
||||
var operandStr = Emitter.FormatArgument(operand);
|
||||
if (operandStr != "") operandStr = " " + operandStr;
|
||||
return opcode + operandStr + extras;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
using System.Collections.Generic;
|
||||
using Harmony.ILCopying;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class CodeTranspiler
|
||||
{
|
||||
private IEnumerable<CodeInstruction> codeInstructions;
|
||||
private List<MethodInfo> transpilers = new List<MethodInfo>();
|
||||
|
||||
public CodeTranspiler(List<ILInstruction> ilInstructions)
|
||||
{
|
||||
codeInstructions = ilInstructions
|
||||
.Select(ilInstruction => ilInstruction.GetCodeInstruction())
|
||||
.ToList().AsEnumerable();
|
||||
}
|
||||
|
||||
public void Add(MethodInfo transpiler)
|
||||
{
|
||||
transpilers.Add(transpiler);
|
||||
}
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
public static object ConvertInstruction(Type type, object op, out Dictionary<string, object> unassigned)
|
||||
{
|
||||
var nonExisting = new Dictionary<string, object>();
|
||||
var elementTo = AccessTools.MakeDeepCopy(op, type, (namePath, trvSrc, trvDest) =>
|
||||
{
|
||||
var value = trvSrc.GetValue();
|
||||
|
||||
if (trvDest.FieldExists() == false)
|
||||
{
|
||||
nonExisting[namePath] = value;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (namePath == nameof(CodeInstruction.opcode))
|
||||
return ReplaceShortJumps((OpCode)value);
|
||||
|
||||
return value;
|
||||
});
|
||||
unassigned = nonExisting;
|
||||
return elementTo;
|
||||
}
|
||||
|
||||
// ShouldAddExceptionInfo is used to determine if CodeInstructions from an older Harmony version were duplicating
|
||||
// exception information as well as to preserve the exception information from being dropped when piping through
|
||||
// multiple transpilers with mixed Harmony versions.
|
||||
//
|
||||
public static bool ShouldAddExceptionInfo(object op, int opIndex, List<object> originalInstructions, List<object> newInstructions, Dictionary<object, Dictionary<string, object>> unassignedValues)
|
||||
{
|
||||
var originalIndex = originalInstructions.IndexOf(op);
|
||||
if (originalIndex == -1)
|
||||
return false; // no need, new instruction
|
||||
|
||||
Dictionary<string, object> unassigned = null;
|
||||
if (unassignedValues.TryGetValue(op, out unassigned) == false)
|
||||
return false; // no need, no unassigned info
|
||||
|
||||
if (unassigned.TryGetValue(nameof(CodeInstruction.blocks), out var blocksObject) == false)
|
||||
return false; // no need, no try-catch info
|
||||
var blocks = blocksObject as List<ExceptionBlock>;
|
||||
|
||||
var dupCount = newInstructions.Count(instr => instr == op);
|
||||
if (dupCount <= 1)
|
||||
return true; // ok, no duplicate found
|
||||
|
||||
var isStartBlock = blocks.FirstOrDefault(block => block.blockType != ExceptionBlockType.EndExceptionBlock);
|
||||
var isEndBlock = blocks.FirstOrDefault(block => block.blockType == ExceptionBlockType.EndExceptionBlock);
|
||||
|
||||
if (isStartBlock != null && isEndBlock == null)
|
||||
{
|
||||
var pairInstruction = originalInstructions.Skip(originalIndex + 1).FirstOrDefault(instr =>
|
||||
{
|
||||
if (unassignedValues.TryGetValue(instr, out unassigned) == false)
|
||||
return false;
|
||||
if (unassigned.TryGetValue(nameof(CodeInstruction.blocks), out blocksObject) == false)
|
||||
return false;
|
||||
blocks = blocksObject as List<ExceptionBlock>;
|
||||
return blocks.Count() > 0;
|
||||
});
|
||||
if (pairInstruction != null)
|
||||
{
|
||||
var pairStart = originalIndex + 1;
|
||||
var pairEnd = pairStart + originalInstructions.Skip(pairStart).ToList().IndexOf(pairInstruction) - 1;
|
||||
var originalBetweenInstructions = originalInstructions
|
||||
.GetRange(pairStart, pairEnd - pairStart)
|
||||
.Intersect(newInstructions);
|
||||
|
||||
pairInstruction = newInstructions.Skip(opIndex + 1).FirstOrDefault(instr =>
|
||||
{
|
||||
if (unassignedValues.TryGetValue(instr, out unassigned) == false)
|
||||
return false;
|
||||
if (unassigned.TryGetValue(nameof(CodeInstruction.blocks), out blocksObject) == false)
|
||||
return false;
|
||||
blocks = blocksObject as List<ExceptionBlock>;
|
||||
return blocks.Count() > 0;
|
||||
});
|
||||
if (pairInstruction != null)
|
||||
{
|
||||
pairStart = opIndex + 1;
|
||||
pairEnd = pairStart + newInstructions.Skip(opIndex + 1).ToList().IndexOf(pairInstruction) - 1;
|
||||
var newBetweenInstructions = newInstructions.GetRange(pairStart, pairEnd - pairStart);
|
||||
var remaining = originalBetweenInstructions.Except(newBetweenInstructions).ToList();
|
||||
return remaining.Count() == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isStartBlock == null && isEndBlock != null)
|
||||
{
|
||||
var pairInstruction = originalInstructions.GetRange(0, originalIndex).LastOrDefault(instr =>
|
||||
{
|
||||
if (unassignedValues.TryGetValue(instr, out unassigned) == false)
|
||||
return false;
|
||||
if (unassigned.TryGetValue(nameof(CodeInstruction.blocks), out blocksObject) == false)
|
||||
return false;
|
||||
blocks = blocksObject as List<ExceptionBlock>;
|
||||
return blocks.Count() > 0;
|
||||
});
|
||||
if (pairInstruction != null)
|
||||
{
|
||||
var pairStart = originalInstructions.GetRange(0, originalIndex).LastIndexOf(pairInstruction);
|
||||
var pairEnd = originalIndex;
|
||||
var originalBetweenInstructions = originalInstructions
|
||||
.GetRange(pairStart, pairEnd - pairStart)
|
||||
.Intersect(newInstructions);
|
||||
|
||||
pairInstruction = newInstructions.GetRange(0, opIndex).LastOrDefault(instr =>
|
||||
{
|
||||
if (unassignedValues.TryGetValue(instr, out unassigned) == false)
|
||||
return false;
|
||||
if (unassigned.TryGetValue(nameof(CodeInstruction.blocks), out blocksObject) == false)
|
||||
return false;
|
||||
blocks = blocksObject as List<ExceptionBlock>;
|
||||
return blocks.Count() > 0;
|
||||
});
|
||||
if (pairInstruction != null)
|
||||
{
|
||||
pairStart = newInstructions.GetRange(0, opIndex).LastIndexOf(pairInstruction);
|
||||
pairEnd = opIndex;
|
||||
var newBetweenInstructions = newInstructions.GetRange(pairStart, pairEnd - pairStart);
|
||||
var remaining = originalBetweenInstructions.Except(newBetweenInstructions);
|
||||
return remaining.Count() == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unclear or unexpected case, ok by default
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable ConvertInstructionsAndUnassignedValues(Type type, IEnumerable enumerable, out Dictionary<object, Dictionary<string, object>> unassignedValues)
|
||||
{
|
||||
var enumerableAssembly = type.GetGenericTypeDefinition().Assembly;
|
||||
var genericListType = enumerableAssembly.GetType(typeof(List<>).FullName);
|
||||
var elementType = type.GetGenericArguments()[0];
|
||||
var listType = enumerableAssembly.GetType(genericListType.MakeGenericType(new Type[] { elementType }).FullName);
|
||||
var list = Activator.CreateInstance(listType);
|
||||
var listAdd = list.GetType().GetMethod("Add");
|
||||
unassignedValues = new Dictionary<object, Dictionary<string, object>>();
|
||||
foreach (var op in enumerable)
|
||||
{
|
||||
var elementTo = ConvertInstruction(elementType, op, out var unassigned);
|
||||
unassignedValues.Add(elementTo, unassigned);
|
||||
listAdd.Invoke(list, new object[] { elementTo });
|
||||
// cannot yield return 'elementTo' here because we have an out parameter in the method
|
||||
}
|
||||
return list as IEnumerable;
|
||||
}
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
public static IEnumerable ConvertToOurInstructions(IEnumerable instructions, List<object> originalInstructions, Dictionary<object, Dictionary<string, object>> unassignedValues)
|
||||
{
|
||||
// Since we are patching this method, we cannot use typeof(CodeInstruction)
|
||||
// because that would use the CodeInstruction of the Harmony lib that patches
|
||||
// us and we get a type assignment error.
|
||||
// Instead, we know that our caller returns List<X> where X is the type we need
|
||||
//
|
||||
var codeInstructionType = new StackTrace().GetFrames()
|
||||
.Select(frame => frame.GetMethod())
|
||||
.OfType<MethodInfo>()
|
||||
.Select(method =>
|
||||
{
|
||||
var returnType = method.ReturnType;
|
||||
if (returnType.IsGenericType == false) return null;
|
||||
var listTypes = returnType.GetGenericArguments();
|
||||
if (listTypes.Length != 1) return null;
|
||||
var type = listTypes[0];
|
||||
return type.FullName == typeof(CodeInstruction).FullName ? type : null;
|
||||
})
|
||||
.Where(type => type != null)
|
||||
.First();
|
||||
|
||||
var newInstructions = instructions.Cast<object>().ToList();
|
||||
|
||||
var index = -1;
|
||||
foreach (var op in newInstructions)
|
||||
{
|
||||
index++;
|
||||
var elementTo = AccessTools.MakeDeepCopy(op, codeInstructionType);
|
||||
if (unassignedValues.TryGetValue(op, out var fields))
|
||||
{
|
||||
var addExceptionInfo = ShouldAddExceptionInfo(op, index, originalInstructions, newInstructions, unassignedValues);
|
||||
|
||||
var trv = Traverse.Create(elementTo);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (addExceptionInfo || field.Key != nameof(CodeInstruction.blocks))
|
||||
trv.Field(field.Key).SetValue(field.Value);
|
||||
}
|
||||
}
|
||||
yield return elementTo;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable ConvertToGeneralInstructions(MethodInfo transpiler, IEnumerable enumerable, out Dictionary<object, Dictionary<string, object>> unassignedValues)
|
||||
{
|
||||
var type = transpiler.GetParameters()
|
||||
.Select(p => p.ParameterType)
|
||||
.FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition().Name.StartsWith("IEnumerable"));
|
||||
return ConvertInstructionsAndUnassignedValues(type, enumerable, out unassignedValues);
|
||||
}
|
||||
|
||||
public static List<object> GetTranspilerCallParameters(ILGenerator generator, MethodInfo transpiler, MethodBase method, IEnumerable instructions)
|
||||
{
|
||||
var parameter = new List<object>();
|
||||
transpiler.GetParameters().Select(param => param.ParameterType).Do(type =>
|
||||
{
|
||||
if (type.IsAssignableFrom(typeof(ILGenerator)))
|
||||
parameter.Add(generator);
|
||||
else if (type.IsAssignableFrom(typeof(MethodBase)))
|
||||
parameter.Add(method);
|
||||
else
|
||||
parameter.Add(instructions);
|
||||
});
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public List<CodeInstruction> GetResult(ILGenerator generator, MethodBase method)
|
||||
{
|
||||
IEnumerable instructions = codeInstructions;
|
||||
transpilers.ForEach(transpiler =>
|
||||
{
|
||||
// before calling some transpiler, convert the input to 'their' CodeInstruction type
|
||||
// also remember any unassignable values that otherwise would be lost
|
||||
instructions = ConvertToGeneralInstructions(transpiler, instructions, out var unassignedValues);
|
||||
|
||||
// remember the order of the original input (for detection of dupped code instructions)
|
||||
var originalInstructions = new List<object>();
|
||||
originalInstructions.AddRange(instructions.Cast<object>());
|
||||
|
||||
// call the transpiler
|
||||
var parameter = GetTranspilerCallParameters(generator, transpiler, method, instructions);
|
||||
instructions = transpiler.Invoke(null, parameter.ToArray()) as IEnumerable;
|
||||
|
||||
// convert result back to 'our' CodeInstruction and re-assign otherwise lost fields
|
||||
instructions = ConvertToOurInstructions(instructions, originalInstructions, unassignedValues);
|
||||
});
|
||||
return instructions.Cast<CodeInstruction>().ToList();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static readonly Dictionary<OpCode, OpCode> allJumpCodes = new Dictionary<OpCode, OpCode>
|
||||
{
|
||||
{ OpCodes.Beq_S, OpCodes.Beq },
|
||||
{ OpCodes.Bge_S, OpCodes.Bge },
|
||||
{ OpCodes.Bge_Un_S, OpCodes.Bge_Un },
|
||||
{ OpCodes.Bgt_S, OpCodes.Bgt },
|
||||
{ OpCodes.Bgt_Un_S, OpCodes.Bgt_Un },
|
||||
{ OpCodes.Ble_S, OpCodes.Ble },
|
||||
{ OpCodes.Ble_Un_S, OpCodes.Ble_Un },
|
||||
{ OpCodes.Blt_S, OpCodes.Blt },
|
||||
{ OpCodes.Blt_Un_S, OpCodes.Blt_Un },
|
||||
{ OpCodes.Bne_Un_S, OpCodes.Bne_Un },
|
||||
{ OpCodes.Brfalse_S, OpCodes.Brfalse },
|
||||
{ OpCodes.Brtrue_S, OpCodes.Brtrue },
|
||||
{ OpCodes.Br_S, OpCodes.Br },
|
||||
{ OpCodes.Leave_S, OpCodes.Leave }
|
||||
};
|
||||
static OpCode ReplaceShortJumps(OpCode opcode)
|
||||
{
|
||||
foreach (var pair in allJumpCodes)
|
||||
if (opcode == pair.Key)
|
||||
return pair.Value;
|
||||
return opcode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class DelegateTypeFactory
|
||||
{
|
||||
readonly ModuleBuilder module;
|
||||
|
||||
static int counter;
|
||||
public DelegateTypeFactory()
|
||||
{
|
||||
counter++;
|
||||
var name = new AssemblyName("HarmonyDTFAssembly" + counter);
|
||||
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
|
||||
module = assembly.DefineDynamicModule("HarmonyDTFModule" + counter);
|
||||
}
|
||||
|
||||
public Type CreateDelegateType(MethodInfo method)
|
||||
{
|
||||
var attr = TypeAttributes.Sealed | TypeAttributes.Public;
|
||||
var typeBuilder = module.DefineType("HarmonyDTFType" + counter, attr, typeof(MulticastDelegate));
|
||||
|
||||
var constructor = typeBuilder.DefineConstructor(
|
||||
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
|
||||
CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) });
|
||||
constructor.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
|
||||
var invokeMethod = typeBuilder.DefineMethod(
|
||||
"Invoke", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public,
|
||||
method.ReturnType, parameters.Types());
|
||||
invokeMethod.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
|
||||
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
invokeMethod.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Name);
|
||||
|
||||
return typeBuilder.CreateType();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
// Based on https://www.codeproject.com/Articles/14973/Dynamic-Code-Generation-vs-Reflection
|
||||
|
||||
public delegate object GetterHandler(object source);
|
||||
public delegate void SetterHandler(object source, object value);
|
||||
public delegate object InstantiationHandler();
|
||||
|
||||
public class FastAccess
|
||||
{
|
||||
public static InstantiationHandler CreateInstantiationHandler(Type type)
|
||||
{
|
||||
var constructorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
|
||||
if (constructorInfo == null)
|
||||
{
|
||||
throw new ApplicationException(string.Format("The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).", type));
|
||||
}
|
||||
|
||||
var dynamicMethod = new DynamicMethod("InstantiateObject_" + type.Name, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(object), null, type, true);
|
||||
var generator = dynamicMethod.GetILGenerator();
|
||||
generator.Emit(OpCodes.Newobj, constructorInfo);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
return (InstantiationHandler)dynamicMethod.CreateDelegate(typeof(InstantiationHandler));
|
||||
}
|
||||
|
||||
public static GetterHandler CreateGetterHandler(PropertyInfo propertyInfo)
|
||||
{
|
||||
var getMethodInfo = propertyInfo.GetGetMethod(true);
|
||||
var dynamicGet = CreateGetDynamicMethod(propertyInfo.DeclaringType);
|
||||
var getGenerator = dynamicGet.GetILGenerator();
|
||||
|
||||
getGenerator.Emit(OpCodes.Ldarg_0);
|
||||
getGenerator.Emit(OpCodes.Call, getMethodInfo);
|
||||
BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
|
||||
getGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
return (GetterHandler)dynamicGet.CreateDelegate(typeof(GetterHandler));
|
||||
}
|
||||
|
||||
public static GetterHandler CreateGetterHandler(FieldInfo fieldInfo)
|
||||
{
|
||||
var dynamicGet = CreateGetDynamicMethod(fieldInfo.DeclaringType);
|
||||
var getGenerator = dynamicGet.GetILGenerator();
|
||||
|
||||
getGenerator.Emit(OpCodes.Ldarg_0);
|
||||
getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
BoxIfNeeded(fieldInfo.FieldType, getGenerator);
|
||||
getGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
return (GetterHandler)dynamicGet.CreateDelegate(typeof(GetterHandler));
|
||||
}
|
||||
|
||||
public static GetterHandler CreateFieldGetter(Type type, params string[] names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
if (AccessTools.Field(typeof(ILGenerator), name) != null)
|
||||
return CreateGetterHandler(AccessTools.Field(type, name));
|
||||
|
||||
if (AccessTools.Property(typeof(ILGenerator), name) != null)
|
||||
return CreateGetterHandler(AccessTools.Property(type, name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SetterHandler CreateSetterHandler(PropertyInfo propertyInfo)
|
||||
{
|
||||
var setMethodInfo = propertyInfo.GetSetMethod(true);
|
||||
var dynamicSet = CreateSetDynamicMethod(propertyInfo.DeclaringType);
|
||||
var setGenerator = dynamicSet.GetILGenerator();
|
||||
|
||||
setGenerator.Emit(OpCodes.Ldarg_0);
|
||||
setGenerator.Emit(OpCodes.Ldarg_1);
|
||||
UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
|
||||
setGenerator.Emit(OpCodes.Call, setMethodInfo);
|
||||
setGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
return (SetterHandler)dynamicSet.CreateDelegate(typeof(SetterHandler));
|
||||
}
|
||||
|
||||
public static SetterHandler CreateSetterHandler(FieldInfo fieldInfo)
|
||||
{
|
||||
var dynamicSet = CreateSetDynamicMethod(fieldInfo.DeclaringType);
|
||||
var setGenerator = dynamicSet.GetILGenerator();
|
||||
|
||||
setGenerator.Emit(OpCodes.Ldarg_0);
|
||||
setGenerator.Emit(OpCodes.Ldarg_1);
|
||||
UnboxIfNeeded(fieldInfo.FieldType, setGenerator);
|
||||
setGenerator.Emit(OpCodes.Stfld, fieldInfo);
|
||||
setGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
return (SetterHandler)dynamicSet.CreateDelegate(typeof(SetterHandler));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static DynamicMethod CreateGetDynamicMethod(Type type)
|
||||
{
|
||||
return new DynamicMethod("DynamicGet_" + type.Name, typeof(object), new Type[] { typeof(object) }, type, true);
|
||||
}
|
||||
|
||||
static DynamicMethod CreateSetDynamicMethod(Type type)
|
||||
{
|
||||
return new DynamicMethod("DynamicSet_" + type.Name, typeof(void), new Type[] { typeof(object), typeof(object) }, type, true);
|
||||
}
|
||||
|
||||
static void BoxIfNeeded(Type type, ILGenerator generator)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
generator.Emit(OpCodes.Box, type);
|
||||
}
|
||||
|
||||
static void UnboxIfNeeded(Type type, ILGenerator generator)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
generator.Emit(OpCodes.Unbox_Any, type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
// Based on https://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker
|
||||
|
||||
public delegate object FastInvokeHandler(object target, object[] paramters);
|
||||
|
||||
public class MethodInvoker
|
||||
{
|
||||
public static FastInvokeHandler GetHandler(DynamicMethod methodInfo, Module module)
|
||||
{
|
||||
return Handler(methodInfo, module);
|
||||
}
|
||||
|
||||
public static FastInvokeHandler GetHandler(MethodInfo methodInfo)
|
||||
{
|
||||
return Handler(methodInfo, methodInfo.DeclaringType.Module);
|
||||
}
|
||||
|
||||
static FastInvokeHandler Handler(MethodInfo methodInfo, Module module, bool directBoxValueAccess = false)
|
||||
{
|
||||
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)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
EmitUnboxIfNeeded(il, methodInfo.DeclaringType);
|
||||
}
|
||||
|
||||
var generateLocalBoxValuePtr = true;
|
||||
var ps = methodInfo.GetParameters();
|
||||
for (var i = 0; i < ps.Length; i++)
|
||||
{
|
||||
var argType = ps[i].ParameterType;
|
||||
var argIsByRef = argType.IsByRef;
|
||||
if (argIsByRef)
|
||||
argType = argType.GetElementType();
|
||||
var argIsValueType = argType.IsValueType;
|
||||
|
||||
if (argIsByRef && argIsValueType && !directBoxValueAccess)
|
||||
{
|
||||
// used later when storing back the reference to the new box in the array.
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
EmitFastInt(il, i);
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
EmitFastInt(il, i);
|
||||
|
||||
if (argIsByRef && !argIsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Ldelema, typeof(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ldelem_Ref);
|
||||
if (argIsValueType)
|
||||
{
|
||||
if (!argIsByRef || !directBoxValueAccess)
|
||||
{
|
||||
// if !directBoxValueAccess, create a new box if required
|
||||
il.Emit(OpCodes.Unbox_Any, argType);
|
||||
if (argIsByRef)
|
||||
{
|
||||
// box back
|
||||
il.Emit(OpCodes.Box, argType);
|
||||
|
||||
// store new box value address to local 0
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Unbox, argType);
|
||||
if (generateLocalBoxValuePtr)
|
||||
{
|
||||
generateLocalBoxValuePtr = false;
|
||||
// Yes, you're seeing this right - a local of type void* to store the box value address!
|
||||
il.DeclareLocal(typeof(void*), true);
|
||||
}
|
||||
il.Emit(OpCodes.Stloc_0);
|
||||
|
||||
// arr and index set up already
|
||||
il.Emit(OpCodes.Stelem_Ref);
|
||||
|
||||
// load address back to stack
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if directBoxValueAccess, emit unbox (get value address)
|
||||
il.Emit(OpCodes.Unbox, argType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable XS0001
|
||||
if (methodInfo.IsStatic)
|
||||
il.EmitCall(OpCodes.Call, methodInfo, null);
|
||||
else
|
||||
il.EmitCall(OpCodes.Callvirt, methodInfo, null);
|
||||
#pragma warning restore XS0001
|
||||
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
il.Emit(OpCodes.Ldnull);
|
||||
else
|
||||
EmitBoxIfNeeded(il, methodInfo.ReturnType);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
var invoder = (FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
|
||||
return invoder;
|
||||
}
|
||||
|
||||
static void EmitCastToReference(ILGenerator il, Type type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
il.Emit(OpCodes.Unbox_Any, type);
|
||||
else
|
||||
il.Emit(OpCodes.Castclass, type);
|
||||
}
|
||||
|
||||
static void EmitUnboxIfNeeded(ILGenerator il, Type type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
il.Emit(OpCodes.Unbox_Any, type);
|
||||
}
|
||||
|
||||
static void EmitBoxIfNeeded(ILGenerator il, Type type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
il.Emit(OpCodes.Box, type);
|
||||
}
|
||||
|
||||
static void EmitFastInt(ILGenerator il, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case -1:
|
||||
il.Emit(OpCodes.Ldc_I4_M1);
|
||||
return;
|
||||
case 0:
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
return;
|
||||
case 1:
|
||||
il.Emit(OpCodes.Ldc_I4_1);
|
||||
return;
|
||||
case 2:
|
||||
il.Emit(OpCodes.Ldc_I4_2);
|
||||
return;
|
||||
case 3:
|
||||
il.Emit(OpCodes.Ldc_I4_3);
|
||||
return;
|
||||
case 4:
|
||||
il.Emit(OpCodes.Ldc_I4_4);
|
||||
return;
|
||||
case 5:
|
||||
il.Emit(OpCodes.Ldc_I4_5);
|
||||
return;
|
||||
case 6:
|
||||
il.Emit(OpCodes.Ldc_I4_6);
|
||||
return;
|
||||
case 7:
|
||||
il.Emit(OpCodes.Ldc_I4_7);
|
||||
return;
|
||||
case 8:
|
||||
il.Emit(OpCodes.Ldc_I4_8);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value > -129 && value < 128)
|
||||
il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
|
||||
else
|
||||
il.Emit(OpCodes.Ldc_I4, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope = "member", Target = "Harmony.FileLog.#LogBytes(System.Int64,System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope = "member", Target = "Harmony.DynamicTools.#PrepareDynamicMethod(System.Reflection.Emit.DynamicMethod)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "Harmony.HarmonySharedState.#GetState()")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope = "member", Target = "Harmony.ILCopying.Memory.#GetMethodStart(System.Reflection.MethodBase)")]
|
|
@ -0,0 +1,190 @@
|
|||
using Harmony.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class Patches
|
||||
{
|
||||
public readonly ReadOnlyCollection<Patch> Prefixes;
|
||||
public readonly ReadOnlyCollection<Patch> Postfixes;
|
||||
public readonly ReadOnlyCollection<Patch> Transpilers;
|
||||
|
||||
public ReadOnlyCollection<string> Owners
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new HashSet<string>();
|
||||
result.UnionWith(Prefixes.Select(p => p.owner));
|
||||
result.UnionWith(Postfixes.Select(p => p.owner));
|
||||
result.UnionWith(Transpilers.Select(p => p.owner));
|
||||
return result.ToList().AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public Patches(Patch[] prefixes, Patch[] postfixes, Patch[] transpilers)
|
||||
{
|
||||
if (prefixes == null) prefixes = new Patch[0];
|
||||
if (postfixes == null) postfixes = new Patch[0];
|
||||
if (transpilers == null) transpilers = new Patch[0];
|
||||
|
||||
Prefixes = prefixes.ToList().AsReadOnly();
|
||||
Postfixes = postfixes.ToList().AsReadOnly();
|
||||
Transpilers = transpilers.ToList().AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public class HarmonyInstance
|
||||
{
|
||||
readonly string id;
|
||||
public string Id => id;
|
||||
public static bool DEBUG = false;
|
||||
|
||||
private static bool selfPatchingDone = false;
|
||||
|
||||
HarmonyInstance(string id)
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
var assembly = typeof(HarmonyInstance).Assembly;
|
||||
var version = assembly.GetName().Version;
|
||||
var location = assembly.Location;
|
||||
if (location == null || location == "") location = new Uri(assembly.CodeBase).LocalPath;
|
||||
FileLog.Log("### Harmony id=" + id + ", version=" + version + ", location=" + location);
|
||||
var callingMethod = GetOutsideCaller();
|
||||
var callingAssembly = callingMethod.DeclaringType.Assembly;
|
||||
location = callingAssembly.Location;
|
||||
if (location == null || location == "") location = new Uri(callingAssembly.CodeBase).LocalPath;
|
||||
FileLog.Log("### Started from " + callingMethod.FullDescription() + ", location " + location);
|
||||
FileLog.Log("### At " + DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss"));
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
|
||||
if (!selfPatchingDone)
|
||||
{
|
||||
selfPatchingDone = true;
|
||||
SelfPatching.PatchOldHarmonyMethods();
|
||||
}
|
||||
}
|
||||
|
||||
public static HarmonyInstance Create(string id)
|
||||
{
|
||||
if (id == null) throw new Exception("id cannot be null");
|
||||
return new HarmonyInstance(id);
|
||||
}
|
||||
|
||||
private MethodBase GetOutsideCaller()
|
||||
{
|
||||
var trace = new StackTrace(true);
|
||||
foreach (var frame in trace.GetFrames())
|
||||
{
|
||||
var method = frame.GetMethod();
|
||||
if (method.DeclaringType.Namespace != typeof(HarmonyInstance).Namespace)
|
||||
return method;
|
||||
}
|
||||
throw new Exception("Unexpected end of stack trace");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public void PatchAll()
|
||||
{
|
||||
var method = new StackTrace().GetFrame(1).GetMethod();
|
||||
var assembly = method.ReflectedType.Assembly;
|
||||
PatchAll(assembly);
|
||||
}
|
||||
|
||||
public void PatchAll(Assembly assembly)
|
||||
{
|
||||
assembly.GetTypes().Do(type =>
|
||||
{
|
||||
var parentMethodInfos = type.GetHarmonyMethods();
|
||||
if (parentMethodInfos != null && parentMethodInfos.Count() > 0)
|
||||
{
|
||||
var info = HarmonyMethod.Merge(parentMethodInfos);
|
||||
var processor = new PatchProcessor(this, type, info);
|
||||
processor.Patch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DynamicMethod Patch(MethodBase original, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null)
|
||||
{
|
||||
var processor = new PatchProcessor(this, new List<MethodBase> { original }, prefix, postfix, transpiler);
|
||||
return processor.Patch().FirstOrDefault();
|
||||
}
|
||||
|
||||
public void UnpatchAll(string harmonyID = null)
|
||||
{
|
||||
bool IDCheck(Patch patchInfo) => harmonyID == null || patchInfo.owner == harmonyID;
|
||||
|
||||
var originals = GetPatchedMethods().ToList();
|
||||
foreach (var original in originals)
|
||||
{
|
||||
var info = GetPatchInfo(original);
|
||||
info.Prefixes.DoIf(IDCheck, patchInfo => Unpatch(original, patchInfo.patch));
|
||||
info.Postfixes.DoIf(IDCheck, patchInfo => Unpatch(original, patchInfo.patch));
|
||||
info.Transpilers.DoIf(IDCheck, patchInfo => Unpatch(original, patchInfo.patch));
|
||||
}
|
||||
}
|
||||
|
||||
public void Unpatch(MethodBase original, HarmonyPatchType type, string harmonyID = null)
|
||||
{
|
||||
var processor = new PatchProcessor(this, new List<MethodBase> { original });
|
||||
processor.Unpatch(type, harmonyID);
|
||||
}
|
||||
|
||||
public void Unpatch(MethodBase original, MethodInfo patch)
|
||||
{
|
||||
var processor = new PatchProcessor(this, new List<MethodBase> { original });
|
||||
processor.Unpatch(patch);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public bool HasAnyPatches(string harmonyID)
|
||||
{
|
||||
return GetPatchedMethods()
|
||||
.Select(original => GetPatchInfo(original))
|
||||
.Any(info => info.Owners.Contains(harmonyID));
|
||||
}
|
||||
|
||||
public Patches GetPatchInfo(MethodBase method)
|
||||
{
|
||||
return PatchProcessor.GetPatchInfo(method);
|
||||
}
|
||||
|
||||
public IEnumerable<MethodBase> GetPatchedMethods()
|
||||
{
|
||||
return HarmonySharedState.GetPatchedMethods();
|
||||
}
|
||||
|
||||
public Dictionary<string, Version> VersionInfo(out Version currentVersion)
|
||||
{
|
||||
currentVersion = typeof(HarmonyInstance).Assembly.GetName().Version;
|
||||
var assemblies = new Dictionary<string, Assembly>();
|
||||
GetPatchedMethods().Do(method =>
|
||||
{
|
||||
var info = HarmonySharedState.GetPatchInfo(method);
|
||||
info.prefixes.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly);
|
||||
info.postfixes.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly);
|
||||
info.transpilers.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly);
|
||||
});
|
||||
|
||||
var result = new Dictionary<string, Version>();
|
||||
assemblies.Do(info =>
|
||||
{
|
||||
var assemblyName = info.Value.GetReferencedAssemblies().FirstOrDefault(a => a.FullName.StartsWith("0Harmony, Version"));
|
||||
if (assemblyName != null)
|
||||
result[info.Key] = assemblyName.Version;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class HarmonyMethod
|
||||
{
|
||||
public MethodInfo method; // need to be called 'method'
|
||||
|
||||
public Type declaringType;
|
||||
public string methodName;
|
||||
public MethodType? methodType;
|
||||
public Type[] argumentTypes;
|
||||
public int prioritiy = -1;
|
||||
public string[] before;
|
||||
public string[] after;
|
||||
|
||||
public HarmonyMethod()
|
||||
{
|
||||
}
|
||||
|
||||
void ImportMethod(MethodInfo theMethod)
|
||||
{
|
||||
method = theMethod;
|
||||
if (method != null)
|
||||
{
|
||||
var infos = method.GetHarmonyMethods();
|
||||
if (infos != null)
|
||||
Merge(infos).CopyTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public HarmonyMethod(MethodInfo method)
|
||||
{
|
||||
ImportMethod(method);
|
||||
}
|
||||
|
||||
public HarmonyMethod(Type type, string name, Type[] parameters = null)
|
||||
{
|
||||
var method = AccessTools.Method(type, name, parameters);
|
||||
ImportMethod(method);
|
||||
}
|
||||
|
||||
public static List<string> HarmonyFields()
|
||||
{
|
||||
return AccessTools
|
||||
.GetFieldNames(typeof(HarmonyMethod))
|
||||
.Where(s => s != "method")
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static HarmonyMethod Merge(List<HarmonyMethod> attributes)
|
||||
{
|
||||
var result = new HarmonyMethod();
|
||||
if (attributes == null) return result;
|
||||
var resultTrv = Traverse.Create(result);
|
||||
attributes.ForEach(attribute =>
|
||||
{
|
||||
var trv = Traverse.Create(attribute);
|
||||
HarmonyFields().ForEach(f =>
|
||||
{
|
||||
var val = trv.Field(f).GetValue();
|
||||
if (val != null)
|
||||
resultTrv.Field(f).SetValue(val);
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var result = "HarmonyMethod[";
|
||||
var trv = Traverse.Create(this);
|
||||
HarmonyFields().ForEach(f =>
|
||||
{
|
||||
result += f + '=' + trv.Field(f).GetValue();
|
||||
});
|
||||
return result + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public static class HarmonyMethodExtensions
|
||||
{
|
||||
public static void CopyTo(this HarmonyMethod from, HarmonyMethod to)
|
||||
{
|
||||
if (to == null) return;
|
||||
var fromTrv = Traverse.Create(from);
|
||||
var toTrv = Traverse.Create(to);
|
||||
HarmonyMethod.HarmonyFields().ForEach(f =>
|
||||
{
|
||||
var val = fromTrv.Field(f).GetValue();
|
||||
if (val != null) toTrv.Field(f).SetValue(val);
|
||||
});
|
||||
}
|
||||
|
||||
public static HarmonyMethod Clone(this HarmonyMethod original)
|
||||
{
|
||||
var result = new HarmonyMethod();
|
||||
original.CopyTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detail)
|
||||
{
|
||||
if (detail == null) return master;
|
||||
var result = new HarmonyMethod();
|
||||
var resultTrv = Traverse.Create(result);
|
||||
var masterTrv = Traverse.Create(master);
|
||||
var detailTrv = Traverse.Create(detail);
|
||||
HarmonyMethod.HarmonyFields().ForEach(f =>
|
||||
{
|
||||
var baseValue = masterTrv.Field(f).GetValue();
|
||||
var detailValue = detailTrv.Field(f).GetValue();
|
||||
resultTrv.Field(f).SetValue(detailValue ?? baseValue);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<HarmonyMethod> GetHarmonyMethods(this Type type)
|
||||
{
|
||||
return type.GetCustomAttributes(true)
|
||||
.Where(attr => attr is HarmonyAttribute)
|
||||
.Cast<HarmonyAttribute>()
|
||||
.Select(attr => attr.info)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static List<HarmonyMethod> GetHarmonyMethods(this MethodBase method)
|
||||
{
|
||||
if (method is DynamicMethod) return new List<HarmonyMethod>();
|
||||
return method.GetCustomAttributes(true)
|
||||
.Where(attr => attr is HarmonyAttribute)
|
||||
.Cast<HarmonyAttribute>()
|
||||
.Select(attr => attr.info)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class HarmonySharedState
|
||||
{
|
||||
static readonly string name = "HarmonySharedState";
|
||||
internal static readonly int internalVersion = 100;
|
||||
internal static int actualVersion = -1;
|
||||
|
||||
static Dictionary<MethodBase, byte[]> GetState()
|
||||
{
|
||||
lock (name)
|
||||
{
|
||||
var assembly = SharedStateAssembly();
|
||||
if (assembly == null)
|
||||
{
|
||||
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run);
|
||||
var moduleBuilder = assemblyBuilder.DefineDynamicModule(name);
|
||||
var typeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract;
|
||||
var typeBuilder = moduleBuilder.DefineType(name, typeAttributes);
|
||||
typeBuilder.DefineField("state", typeof(Dictionary<MethodBase, byte[]>), FieldAttributes.Static | FieldAttributes.Public);
|
||||
typeBuilder.DefineField("version", typeof(int), FieldAttributes.Static | FieldAttributes.Public).SetConstant(internalVersion);
|
||||
typeBuilder.CreateType();
|
||||
|
||||
assembly = SharedStateAssembly();
|
||||
if (assembly == null) throw new Exception("Cannot find or create harmony shared state");
|
||||
}
|
||||
|
||||
var versionField = assembly.GetType(name).GetField("version");
|
||||
if (versionField == null) throw new Exception("Cannot find harmony state version field");
|
||||
actualVersion = (int)versionField.GetValue(null);
|
||||
|
||||
var stateField = assembly.GetType(name).GetField("state");
|
||||
if (stateField == null) throw new Exception("Cannot find harmony state field");
|
||||
if (stateField.GetValue(null) == null) stateField.SetValue(null, new Dictionary<MethodBase, byte[]>());
|
||||
return (Dictionary<MethodBase, byte[]>)stateField.GetValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
static Assembly SharedStateAssembly()
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name.Contains(name));
|
||||
}
|
||||
|
||||
internal static PatchInfo GetPatchInfo(MethodBase method)
|
||||
{
|
||||
var bytes = GetState().GetValueSafe(method);
|
||||
if (bytes == null) return null;
|
||||
return PatchInfoSerialization.Deserialize(bytes);
|
||||
}
|
||||
|
||||
internal static IEnumerable<MethodBase> GetPatchedMethods()
|
||||
{
|
||||
return GetState().Keys.AsEnumerable();
|
||||
}
|
||||
|
||||
internal static void UpdatePatchInfo(MethodBase method, PatchInfo patchInfo)
|
||||
{
|
||||
GetState()[method] = patchInfo.Serialize();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
public class ByteBuffer
|
||||
{
|
||||
public byte[] buffer;
|
||||
public int position;
|
||||
|
||||
public ByteBuffer(byte[] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
CheckCanRead(1);
|
||||
return buffer[position++];
|
||||
}
|
||||
|
||||
public byte[] ReadBytes(int length)
|
||||
{
|
||||
CheckCanRead(length);
|
||||
var value = new byte[length];
|
||||
Buffer.BlockCopy(buffer, position, value, 0, length);
|
||||
position += length;
|
||||
return value;
|
||||
}
|
||||
|
||||
public short ReadInt16()
|
||||
{
|
||||
CheckCanRead(2);
|
||||
var value = (short)(buffer[position]
|
||||
| (buffer[position + 1] << 8));
|
||||
position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
public int ReadInt32()
|
||||
{
|
||||
CheckCanRead(4);
|
||||
var value = buffer[position]
|
||||
| (buffer[position + 1] << 8)
|
||||
| (buffer[position + 2] << 16)
|
||||
| (buffer[position + 3] << 24);
|
||||
position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
public long ReadInt64()
|
||||
{
|
||||
CheckCanRead(8);
|
||||
var low = (uint)(buffer[position]
|
||||
| (buffer[position + 1] << 8)
|
||||
| (buffer[position + 2] << 16)
|
||||
| (buffer[position + 3] << 24));
|
||||
|
||||
var high = (uint)(buffer[position + 4]
|
||||
| (buffer[position + 5] << 8)
|
||||
| (buffer[position + 6] << 16)
|
||||
| (buffer[position + 7] << 24));
|
||||
|
||||
var value = (((long)high) << 32) | low;
|
||||
position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
public float ReadSingle()
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
var bytes = ReadBytes(4);
|
||||
Array.Reverse(bytes);
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
CheckCanRead(4);
|
||||
var value = BitConverter.ToSingle(buffer, position);
|
||||
position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
public double ReadDouble()
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
var bytes = ReadBytes(8);
|
||||
Array.Reverse(bytes);
|
||||
return BitConverter.ToDouble(bytes, 0);
|
||||
}
|
||||
|
||||
CheckCanRead(8);
|
||||
var value = BitConverter.ToDouble(buffer, position);
|
||||
position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
void CheckCanRead(int count)
|
||||
{
|
||||
if (position + count > buffer.Length)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,315 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
public class LeaveTry
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return "(autogenerated)";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Emitter
|
||||
{
|
||||
static readonly GetterHandler codeLenGetter = FastAccess.CreateFieldGetter(typeof(ILGenerator), "code_len", "m_length");
|
||||
static readonly GetterHandler localsGetter = FastAccess.CreateFieldGetter(typeof(ILGenerator), "locals");
|
||||
static readonly GetterHandler localCountGetter = FastAccess.CreateFieldGetter(typeof(ILGenerator), "m_localCount");
|
||||
|
||||
public static string CodePos(ILGenerator il)
|
||||
{
|
||||
var offset = (int)codeLenGetter(il);
|
||||
return string.Format("L_{0:x4}: ", offset);
|
||||
}
|
||||
|
||||
public static void LogIL(ILGenerator il, OpCode opCode, object argument)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
var argStr = FormatArgument(argument);
|
||||
var space = argStr.Length > 0 ? " " : "";
|
||||
FileLog.LogBuffered(string.Format("{0}{1}{2}{3}", CodePos(il), opCode, space, argStr));
|
||||
}
|
||||
}
|
||||
|
||||
public static void LogLocalVariable(ILGenerator il, LocalBuilder variable)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
var localCount = -1;
|
||||
var localsArray = localsGetter != null ? (LocalBuilder[])localsGetter(il) : null;
|
||||
if (localsArray != null && localsArray.Length > 0)
|
||||
localCount = localsArray.Length;
|
||||
else
|
||||
localCount = (int)localCountGetter(il);
|
||||
|
||||
var str = string.Format("{0}Local var {1}: {2}{3}", CodePos(il), localCount - 1, variable.LocalType.FullName, variable.IsPinned ? "(pinned)" : "");
|
||||
FileLog.LogBuffered(str);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatArgument(object argument)
|
||||
{
|
||||
if (argument == null) return "NULL";
|
||||
var type = argument.GetType();
|
||||
|
||||
if (type == typeof(string))
|
||||
return "\"" + argument + "\"";
|
||||
if (type == typeof(Label))
|
||||
return "Label" + ((Label)argument).GetHashCode();
|
||||
if (type == typeof(Label[]))
|
||||
return "Labels" + string.Join(",", ((Label[])argument).Select(l => l.GetHashCode().ToString()).ToArray());
|
||||
if (type == typeof(LocalBuilder))
|
||||
return ((LocalBuilder)argument).LocalIndex + " (" + ((LocalBuilder)argument).LocalType + ")";
|
||||
|
||||
return argument.ToString().Trim();
|
||||
}
|
||||
|
||||
public static void MarkLabel(ILGenerator il, Label label)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered(CodePos(il) + FormatArgument(label));
|
||||
il.MarkLabel(label);
|
||||
}
|
||||
|
||||
public static void MarkBlockBefore(ILGenerator il, ExceptionBlock block, out Label? label)
|
||||
{
|
||||
label = null;
|
||||
switch (block.blockType)
|
||||
{
|
||||
case ExceptionBlockType.BeginExceptionBlock:
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
FileLog.LogBuffered(".try");
|
||||
FileLog.LogBuffered("{");
|
||||
FileLog.ChangeIndent(1);
|
||||
}
|
||||
label = il.BeginExceptionBlock();
|
||||
return;
|
||||
|
||||
case ExceptionBlockType.BeginCatchBlock:
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
// fake log a LEAVE code since BeginCatchBlock() does add it
|
||||
LogIL(il, OpCodes.Leave, new LeaveTry());
|
||||
|
||||
FileLog.ChangeIndent(-1);
|
||||
FileLog.LogBuffered("} // end try");
|
||||
|
||||
FileLog.LogBuffered(".catch " + block.catchType);
|
||||
FileLog.LogBuffered("{");
|
||||
FileLog.ChangeIndent(1);
|
||||
}
|
||||
il.BeginCatchBlock(block.catchType);
|
||||
return;
|
||||
|
||||
case ExceptionBlockType.BeginExceptFilterBlock:
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
// fake log a LEAVE code since BeginCatchBlock() does add it
|
||||
LogIL(il, OpCodes.Leave, new LeaveTry());
|
||||
|
||||
FileLog.ChangeIndent(-1);
|
||||
FileLog.LogBuffered("} // end try");
|
||||
|
||||
FileLog.LogBuffered(".filter");
|
||||
FileLog.LogBuffered("{");
|
||||
FileLog.ChangeIndent(1);
|
||||
}
|
||||
il.BeginExceptFilterBlock();
|
||||
return;
|
||||
|
||||
case ExceptionBlockType.BeginFaultBlock:
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
// fake log a LEAVE code since BeginCatchBlock() does add it
|
||||
LogIL(il, OpCodes.Leave, new LeaveTry());
|
||||
|
||||
FileLog.ChangeIndent(-1);
|
||||
FileLog.LogBuffered("} // end try");
|
||||
|
||||
FileLog.LogBuffered(".fault");
|
||||
FileLog.LogBuffered("{");
|
||||
FileLog.ChangeIndent(1);
|
||||
}
|
||||
il.BeginFaultBlock();
|
||||
return;
|
||||
|
||||
case ExceptionBlockType.BeginFinallyBlock:
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
// fake log a LEAVE code since BeginCatchBlock() does add it
|
||||
LogIL(il, OpCodes.Leave, new LeaveTry());
|
||||
|
||||
FileLog.ChangeIndent(-1);
|
||||
FileLog.LogBuffered("} // end try");
|
||||
|
||||
FileLog.LogBuffered(".finally");
|
||||
FileLog.LogBuffered("{");
|
||||
FileLog.ChangeIndent(1);
|
||||
}
|
||||
il.BeginFinallyBlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void MarkBlockAfter(ILGenerator il, ExceptionBlock block)
|
||||
{
|
||||
if (block.blockType == ExceptionBlockType.EndExceptionBlock)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
// fake log a LEAVE code since BeginCatchBlock() does add it
|
||||
LogIL(il, OpCodes.Leave, new LeaveTry());
|
||||
|
||||
FileLog.ChangeIndent(-1);
|
||||
FileLog.LogBuffered("} // end handler");
|
||||
}
|
||||
il.EndExceptionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
// MethodCopier calls when Operand type is InlineNone
|
||||
public static void Emit(ILGenerator il, OpCode opcode)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered(CodePos(il) + opcode);
|
||||
il.Emit(opcode);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, LocalBuilder local)
|
||||
{
|
||||
LogIL(il, opcode, local);
|
||||
il.Emit(opcode, local);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, FieldInfo field)
|
||||
{
|
||||
LogIL(il, opcode, field);
|
||||
il.Emit(opcode, field);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, Label[] labels)
|
||||
{
|
||||
LogIL(il, opcode, labels);
|
||||
il.Emit(opcode, labels);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, Label label)
|
||||
{
|
||||
LogIL(il, opcode, label);
|
||||
il.Emit(opcode, label);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, string str)
|
||||
{
|
||||
LogIL(il, opcode, str);
|
||||
il.Emit(opcode, str);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, float arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, byte arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, sbyte arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, double arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, int arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, MethodInfo meth)
|
||||
{
|
||||
LogIL(il, opcode, meth);
|
||||
il.Emit(opcode, meth);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, short arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, SignatureHelper signature)
|
||||
{
|
||||
LogIL(il, opcode, signature);
|
||||
il.Emit(opcode, signature);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, ConstructorInfo con)
|
||||
{
|
||||
LogIL(il, opcode, con);
|
||||
il.Emit(opcode, con);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, Type cls)
|
||||
{
|
||||
LogIL(il, opcode, cls);
|
||||
il.Emit(opcode, cls);
|
||||
}
|
||||
|
||||
// MethodCopier calls by 3rd argument type
|
||||
public static void Emit(ILGenerator il, OpCode opcode, long arg)
|
||||
{
|
||||
LogIL(il, opcode, arg);
|
||||
il.Emit(opcode, arg);
|
||||
}
|
||||
|
||||
// called from MethodInvoker (calls from MethodCopier use the corresponding Emit() call above)
|
||||
public static void EmitCall(ILGenerator il, OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered(string.Format("{0}Call {1} {2} {3}", CodePos(il), opcode, methodInfo, optionalParameterTypes));
|
||||
il.EmitCall(opcode, methodInfo, optionalParameterTypes);
|
||||
}
|
||||
|
||||
// not called yet
|
||||
public static void EmitCalli(ILGenerator il, OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered(string.Format("{0}Calli {1} {2} {3} {4}", CodePos(il), opcode, unmanagedCallConv, returnType, parameterTypes));
|
||||
il.EmitCalli(opcode, unmanagedCallConv, returnType, parameterTypes);
|
||||
}
|
||||
|
||||
// not called yet
|
||||
public static void EmitCalli(ILGenerator il, OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered(string.Format("{0}Calli {1} {2} {3} {4} {5}", CodePos(il), opcode, callingConvention, returnType, parameterTypes, optionalParameterTypes));
|
||||
il.EmitCalli(opcode, callingConvention, returnType, parameterTypes, optionalParameterTypes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
public enum ExceptionBlockType
|
||||
{
|
||||
BeginExceptionBlock,
|
||||
BeginCatchBlock,
|
||||
BeginExceptFilterBlock,
|
||||
BeginFaultBlock,
|
||||
BeginFinallyBlock,
|
||||
EndExceptionBlock
|
||||
}
|
||||
|
||||
public class ExceptionBlock
|
||||
{
|
||||
public ExceptionBlockType blockType;
|
||||
public Type catchType;
|
||||
|
||||
public ExceptionBlock(ExceptionBlockType blockType, Type catchType)
|
||||
{
|
||||
this.blockType = blockType;
|
||||
this.catchType = catchType;
|
||||
}
|
||||
}
|
||||
|
||||
public class ILInstruction
|
||||
{
|
||||
public int offset;
|
||||
public OpCode opcode;
|
||||
public object operand;
|
||||
public object argument;
|
||||
|
||||
public List<Label> labels = new List<Label>();
|
||||
public List<ExceptionBlock> blocks = new List<ExceptionBlock>();
|
||||
|
||||
public ILInstruction(OpCode opcode, object operand = null)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
this.operand = operand;
|
||||
argument = operand;
|
||||
}
|
||||
|
||||
public CodeInstruction GetCodeInstruction()
|
||||
{
|
||||
var instr = new CodeInstruction(opcode, argument);
|
||||
if (opcode.OperandType == OperandType.InlineNone)
|
||||
instr.operand = null;
|
||||
instr.labels = labels;
|
||||
instr.blocks = blocks;
|
||||
return instr;
|
||||
}
|
||||
|
||||
public int GetSize()
|
||||
{
|
||||
var size = opcode.Size;
|
||||
|
||||
switch (opcode.OperandType)
|
||||
{
|
||||
case OperandType.InlineSwitch:
|
||||
size += (1 + ((Array)operand).Length) * 4;
|
||||
break;
|
||||
|
||||
case OperandType.InlineI8:
|
||||
case OperandType.InlineR:
|
||||
size += 8;
|
||||
break;
|
||||
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.InlineField:
|
||||
case OperandType.InlineI:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineSig:
|
||||
case OperandType.InlineString:
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.ShortInlineR:
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
case OperandType.InlineVar:
|
||||
size += 2;
|
||||
break;
|
||||
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.ShortInlineI:
|
||||
case OperandType.ShortInlineVar:
|
||||
size += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var instruction = "";
|
||||
|
||||
AppendLabel(ref instruction, this);
|
||||
instruction = instruction + ": " + opcode.Name;
|
||||
|
||||
if (operand == null)
|
||||
return instruction;
|
||||
|
||||
instruction = instruction + " ";
|
||||
|
||||
switch (opcode.OperandType)
|
||||
{
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
AppendLabel(ref instruction, operand);
|
||||
break;
|
||||
|
||||
case OperandType.InlineSwitch:
|
||||
var switchLabels = (ILInstruction[])operand;
|
||||
for (var i = 0; i < switchLabels.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
instruction = instruction + ",";
|
||||
|
||||
AppendLabel(ref instruction, switchLabels[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case OperandType.InlineString:
|
||||
instruction = instruction + "\"" + operand + "\"";
|
||||
break;
|
||||
|
||||
default:
|
||||
instruction = instruction + operand;
|
||||
break;
|
||||
}
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
[Flags]
|
||||
public enum Protection
|
||||
{
|
||||
PAGE_NOACCESS = 0x01,
|
||||
PAGE_READONLY = 0x02,
|
||||
PAGE_READWRITE = 0x04,
|
||||
PAGE_WRITECOPY = 0x08,
|
||||
PAGE_EXECUTE = 0x10,
|
||||
PAGE_EXECUTE_READ = 0x20,
|
||||
PAGE_EXECUTE_READWRITE = 0x40,
|
||||
PAGE_EXECUTE_WRITECOPY = 0x80,
|
||||
PAGE_GUARD = 0x100,
|
||||
PAGE_NOCACHE = 0x200,
|
||||
PAGE_WRITECOMBINE = 0x400
|
||||
}
|
||||
|
||||
public static class Memory
|
||||
{
|
||||
private static readonly HashSet<PlatformID> WindowsPlatformIDSet = new HashSet<PlatformID>
|
||||
{
|
||||
PlatformID.Win32NT, PlatformID.Win32S, PlatformID.Win32Windows, PlatformID.WinCE
|
||||
};
|
||||
|
||||
public static bool IsWindows => WindowsPlatformIDSet.Contains(Environment.OSVersion.Platform);
|
||||
|
||||
// Safe to use windows reference since this will only ever be called on windows
|
||||
//
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, Protection flNewProtect, out Protection lpflOldProtect);
|
||||
|
||||
public static void UnprotectMemoryPage(long memory)
|
||||
{
|
||||
if (IsWindows)
|
||||
{
|
||||
var success = VirtualProtect(new IntPtr(memory), new UIntPtr(1), Protection.PAGE_EXECUTE_READWRITE, out var _ignored);
|
||||
if (success == false)
|
||||
throw new System.ComponentModel.Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public static string DetourMethod(MethodBase original, MethodBase replacement)
|
||||
{
|
||||
var originalCodeStart = GetMethodStart(original, out var exception);
|
||||
if (originalCodeStart == 0)
|
||||
return exception.Message;
|
||||
var patchCodeStart = GetMethodStart(replacement, out exception);
|
||||
if (patchCodeStart == 0)
|
||||
return exception.Message;
|
||||
|
||||
return WriteJump(originalCodeStart, patchCodeStart);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is still a rough part in Harmony. So much information and no easy way
|
||||
* to determine when and what is valid. Especially with different environments
|
||||
* and .NET versions. More information might be found here:
|
||||
*
|
||||
* https://stackoverflow.com/questions/38782934/how-to-replace-the-pointer-to-the-overridden-virtual-method-in-the-pointer-of/
|
||||
* https://stackoverflow.com/questions/39034018/how-to-replace-a-pointer-to-a-pointer-to-a-method-in-a-class-of-my-method-inheri
|
||||
*
|
||||
*/
|
||||
public static string WriteJump(long memory, long destination)
|
||||
{
|
||||
UnprotectMemoryPage(memory);
|
||||
|
||||
if (IntPtr.Size == sizeof(long))
|
||||
{
|
||||
if (CompareBytes(memory, new byte[] { 0xe9 }))
|
||||
{
|
||||
var offset = ReadInt(memory + 1);
|
||||
memory += 5 + offset;
|
||||
}
|
||||
|
||||
memory = WriteBytes(memory, new byte[] { 0x48, 0xB8 });
|
||||
memory = WriteLong(memory, destination);
|
||||
memory = WriteBytes(memory, new byte[] { 0xFF, 0xE0 });
|
||||
}
|
||||
else
|
||||
{
|
||||
memory = WriteByte(memory, 0x68);
|
||||
memory = WriteInt(memory, (int)destination);
|
||||
memory = WriteByte(memory, 0xc3);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static RuntimeMethodHandle GetRuntimeMethodHandle(MethodBase method)
|
||||
{
|
||||
if (method is DynamicMethod)
|
||||
{
|
||||
var nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
|
||||
// DynamicMethod actually generates its m_methodHandle on-the-fly and therefore
|
||||
// we should call GetMethodDescriptor to force it to be created
|
||||
//
|
||||
var m_GetMethodDescriptor = typeof(DynamicMethod).GetMethod("GetMethodDescriptor", nonPublicInstance);
|
||||
if (m_GetMethodDescriptor != null)
|
||||
return (RuntimeMethodHandle)m_GetMethodDescriptor.Invoke(method, new object[0]);
|
||||
|
||||
// .Net Core
|
||||
var f_m_method = typeof(DynamicMethod).GetField("m_method", nonPublicInstance);
|
||||
if (f_m_method != null)
|
||||
return (RuntimeMethodHandle)f_m_method.GetValue(method);
|
||||
|
||||
// Mono
|
||||
var f_mhandle = typeof(DynamicMethod).GetField("mhandle", nonPublicInstance);
|
||||
return (RuntimeMethodHandle)f_mhandle.GetValue(method);
|
||||
}
|
||||
|
||||
return method.MethodHandle;
|
||||
}
|
||||
|
||||
public static long GetMethodStart(MethodBase method, out Exception exception)
|
||||
{
|
||||
// required in .NET Core so that the method is JITed and the method start does not change
|
||||
//
|
||||
var handle = GetRuntimeMethodHandle(method);
|
||||
try
|
||||
{
|
||||
RuntimeHelpers.PrepareMethod(handle);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
exception = null;
|
||||
return handle.GetFunctionPointer().ToInt64();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe bool CompareBytes(long memory, byte[] values)
|
||||
{
|
||||
var p = (byte*)memory;
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value != *p) return false;
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static unsafe byte ReadByte(long memory)
|
||||
{
|
||||
var p = (byte*)memory;
|
||||
return *p;
|
||||
}
|
||||
|
||||
public static unsafe int ReadInt(long memory)
|
||||
{
|
||||
var p = (int*)memory;
|
||||
return *p;
|
||||
}
|
||||
|
||||
public static unsafe long ReadLong(long memory)
|
||||
{
|
||||
var p = (long*)memory;
|
||||
return *p;
|
||||
}
|
||||
|
||||
public static unsafe long WriteByte(long memory, byte value)
|
||||
{
|
||||
var p = (byte*)memory;
|
||||
*p = value;
|
||||
return memory + sizeof(byte);
|
||||
}
|
||||
|
||||
public static unsafe long WriteBytes(long memory, byte[] values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
memory = WriteByte(memory, value);
|
||||
return memory;
|
||||
}
|
||||
|
||||
public static unsafe long WriteInt(long memory, int value)
|
||||
{
|
||||
var p = (int*)memory;
|
||||
*p = value;
|
||||
return memory + sizeof(int);
|
||||
}
|
||||
|
||||
public static unsafe long WriteLong(long memory, long value)
|
||||
{
|
||||
var p = (long*)memory;
|
||||
*p = value;
|
||||
return memory + sizeof(long);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,730 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
public class MethodCopier
|
||||
{
|
||||
readonly MethodBodyReader reader;
|
||||
readonly List<MethodInfo> transpilers = new List<MethodInfo>();
|
||||
|
||||
public MethodCopier(MethodBase fromMethod, ILGenerator toILGenerator, LocalBuilder[] existingVariables = null)
|
||||
{
|
||||
if (fromMethod == null) throw new ArgumentNullException("Method cannot be null");
|
||||
reader = new MethodBodyReader(fromMethod, toILGenerator);
|
||||
reader.DeclareVariables(existingVariables);
|
||||
reader.ReadInstructions();
|
||||
}
|
||||
|
||||
public void AddTranspiler(MethodInfo transpiler)
|
||||
{
|
||||
transpilers.Add(transpiler);
|
||||
}
|
||||
|
||||
public void Finalize(List<Label> endLabels, List<ExceptionBlock> endBlocks)
|
||||
{
|
||||
reader.FinalizeILCodes(transpilers, endLabels, endBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodBodyReader
|
||||
{
|
||||
readonly ILGenerator generator;
|
||||
|
||||
readonly MethodBase method;
|
||||
readonly Module module;
|
||||
readonly Type[] typeArguments;
|
||||
readonly Type[] methodArguments;
|
||||
readonly ByteBuffer ilBytes;
|
||||
readonly ParameterInfo this_parameter;
|
||||
readonly ParameterInfo[] parameters;
|
||||
readonly IList<LocalVariableInfo> locals;
|
||||
readonly IList<ExceptionHandlingClause> exceptions;
|
||||
List<ILInstruction> ilInstructions;
|
||||
|
||||
LocalBuilder[] variables;
|
||||
|
||||
// NOTE: you cannot simply "copy" ILInstructions from a method. They contain references to
|
||||
// local variables which must be CREATED on an ILGenerator or else they are invalid when you
|
||||
// want to use the ILInstruction. If you are really clever, you can supply a dummy generator
|
||||
// and edit out all labels during the processing but that might be more trickier than you think
|
||||
//
|
||||
// In order to copy together a bunch of method parts within a transpiler, you have to pass in
|
||||
// your current generator that builds your new method
|
||||
//
|
||||
// You will end up with the sum of all declared local variables of all methods you run
|
||||
// GetInstructions on or use a dummy generator but edit out the invalid labels from the codes
|
||||
// you copy
|
||||
//
|
||||
public static List<ILInstruction> GetInstructions(ILGenerator generator, MethodBase method)
|
||||
{
|
||||
if (method == null) throw new ArgumentNullException("Method cannot be null");
|
||||
var reader = new MethodBodyReader(method, generator);
|
||||
reader.DeclareVariables(null);
|
||||
reader.ReadInstructions();
|
||||
return reader.ilInstructions;
|
||||
}
|
||||
|
||||
// constructor
|
||||
//
|
||||
public MethodBodyReader(MethodBase method, ILGenerator generator)
|
||||
{
|
||||
this.generator = generator;
|
||||
this.method = method;
|
||||
module = method.Module;
|
||||
|
||||
var body = method.GetMethodBody();
|
||||
if (body == null)
|
||||
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());
|
||||
ilBytes = new ByteBuffer(bytes);
|
||||
ilInstructions = new List<ILInstruction>((bytes.Length + 1) / 2);
|
||||
|
||||
var type = method.DeclaringType;
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
try { typeArguments = type.GetGenericArguments(); }
|
||||
catch { typeArguments = null; }
|
||||
}
|
||||
|
||||
if (method.IsGenericMethod)
|
||||
{
|
||||
try { methodArguments = method.GetGenericArguments(); }
|
||||
catch { methodArguments = null; }
|
||||
}
|
||||
|
||||
if (!method.IsStatic)
|
||||
this_parameter = new ThisParameter(method);
|
||||
parameters = method.GetParameters();
|
||||
|
||||
locals = body.LocalVariables;
|
||||
exceptions = body.ExceptionHandlingClauses;
|
||||
}
|
||||
|
||||
// read and parse IL codes
|
||||
//
|
||||
public void ReadInstructions()
|
||||
{
|
||||
while (ilBytes.position < ilBytes.buffer.Length)
|
||||
{
|
||||
var loc = ilBytes.position; // get location first (ReadOpCode will advance it)
|
||||
var instruction = new ILInstruction(ReadOpCode()) { offset = loc };
|
||||
ReadOperand(instruction);
|
||||
ilInstructions.Add(instruction);
|
||||
}
|
||||
|
||||
ResolveBranches();
|
||||
ParseExceptions();
|
||||
}
|
||||
|
||||
// declare local variables
|
||||
//
|
||||
public void DeclareVariables(LocalBuilder[] existingVariables)
|
||||
{
|
||||
if (generator == null) return;
|
||||
if (existingVariables != null)
|
||||
variables = existingVariables;
|
||||
else
|
||||
variables = locals.Select(
|
||||
lvi => generator.DeclareLocal(lvi.LocalType, lvi.IsPinned)
|
||||
).ToArray();
|
||||
}
|
||||
|
||||
// process all jumps
|
||||
//
|
||||
void ResolveBranches()
|
||||
{
|
||||
foreach (var ilInstruction in ilInstructions)
|
||||
{
|
||||
switch (ilInstruction.opcode.OperandType)
|
||||
{
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
ilInstruction.operand = GetInstruction((int)ilInstruction.operand, false);
|
||||
break;
|
||||
|
||||
case OperandType.InlineSwitch:
|
||||
var offsets = (int[])ilInstruction.operand;
|
||||
var branches = new ILInstruction[offsets.Length];
|
||||
for (var j = 0; j < offsets.Length; j++)
|
||||
branches[j] = GetInstruction(offsets[j], false);
|
||||
|
||||
ilInstruction.operand = branches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process all exception blocks
|
||||
//
|
||||
void ParseExceptions()
|
||||
{
|
||||
foreach (var exception in exceptions)
|
||||
{
|
||||
var try_start = exception.TryOffset;
|
||||
var try_end = exception.TryOffset + exception.TryLength - 1;
|
||||
|
||||
var handler_start = exception.HandlerOffset;
|
||||
var handler_end = exception.HandlerOffset + exception.HandlerLength - 1;
|
||||
|
||||
var instr1 = GetInstruction(try_start, false);
|
||||
instr1.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock, null));
|
||||
|
||||
var instr2 = GetInstruction(handler_end, true);
|
||||
instr2.blocks.Add(new ExceptionBlock(ExceptionBlockType.EndExceptionBlock, null));
|
||||
|
||||
// The FilterOffset property is meaningful only for Filter clauses.
|
||||
// The CatchType property is not meaningful for Filter or Finally clauses.
|
||||
//
|
||||
switch (exception.Flags)
|
||||
{
|
||||
case ExceptionHandlingClauseOptions.Filter:
|
||||
var instr3 = GetInstruction(exception.FilterOffset, false);
|
||||
instr3.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginExceptFilterBlock, null));
|
||||
break;
|
||||
|
||||
case ExceptionHandlingClauseOptions.Finally:
|
||||
var instr4 = GetInstruction(handler_start, false);
|
||||
instr4.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginFinallyBlock, null));
|
||||
break;
|
||||
|
||||
case ExceptionHandlingClauseOptions.Clause:
|
||||
var instr5 = GetInstruction(handler_start, false);
|
||||
instr5.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginCatchBlock, exception.CatchType));
|
||||
break;
|
||||
|
||||
case ExceptionHandlingClauseOptions.Fault:
|
||||
var instr6 = GetInstruction(handler_start, false);
|
||||
instr6.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginFaultBlock, null));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// used in FinalizeILCodes to convert short jumps to long ones
|
||||
static Dictionary<OpCode, OpCode> shortJumps = new Dictionary<OpCode, OpCode>()
|
||||
{
|
||||
{ OpCodes.Leave_S, OpCodes.Leave },
|
||||
{ OpCodes.Brfalse_S, OpCodes.Brfalse },
|
||||
{ OpCodes.Brtrue_S, OpCodes.Brtrue },
|
||||
{ OpCodes.Beq_S, OpCodes.Beq },
|
||||
{ OpCodes.Bge_S, OpCodes.Bge },
|
||||
{ OpCodes.Bgt_S, OpCodes.Bgt },
|
||||
{ OpCodes.Ble_S, OpCodes.Ble },
|
||||
{ OpCodes.Blt_S, OpCodes.Blt },
|
||||
{ OpCodes.Bne_Un_S, OpCodes.Bne_Un },
|
||||
{ OpCodes.Bge_Un_S, OpCodes.Bge_Un },
|
||||
{ OpCodes.Bgt_Un_S, OpCodes.Bgt_Un },
|
||||
{ OpCodes.Ble_Un_S, OpCodes.Ble_Un },
|
||||
{ OpCodes.Br_S, OpCodes.Br },
|
||||
{ OpCodes.Blt_Un_S, OpCodes.Blt_Un }
|
||||
};
|
||||
|
||||
// use parsed IL codes and emit them to a generator
|
||||
//
|
||||
public void FinalizeILCodes(List<MethodInfo> transpilers, List<Label> endLabels, List<ExceptionBlock> endBlocks)
|
||||
{
|
||||
if (generator == null) return;
|
||||
|
||||
// pass1 - define labels and add them to instructions that are target of a jump
|
||||
//
|
||||
foreach (var ilInstruction in ilInstructions)
|
||||
{
|
||||
switch (ilInstruction.opcode.OperandType)
|
||||
{
|
||||
case OperandType.InlineSwitch:
|
||||
{
|
||||
var targets = ilInstruction.operand as ILInstruction[];
|
||||
if (targets != null)
|
||||
{
|
||||
var labels = new List<Label>();
|
||||
foreach (var target in targets)
|
||||
{
|
||||
var label = generator.DefineLabel();
|
||||
target.labels.Add(label);
|
||||
labels.Add(label);
|
||||
}
|
||||
ilInstruction.argument = labels.ToArray();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
{
|
||||
var target = ilInstruction.operand as ILInstruction;
|
||||
if (target != null)
|
||||
{
|
||||
var label = generator.DefineLabel();
|
||||
target.labels.Add(label);
|
||||
ilInstruction.argument = label;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pass2 - filter through all processors
|
||||
//
|
||||
var codeTranspiler = new CodeTranspiler(ilInstructions);
|
||||
transpilers.Do(transpiler => codeTranspiler.Add(transpiler));
|
||||
var codeInstructions = codeTranspiler.GetResult(generator, method);
|
||||
|
||||
// pass3 - remove RET if it appears at the end
|
||||
while (true)
|
||||
{
|
||||
var lastInstruction = codeInstructions.LastOrDefault();
|
||||
if (lastInstruction == null || lastInstruction.opcode != OpCodes.Ret) break;
|
||||
|
||||
// remember any existing labels
|
||||
endLabels.AddRange(lastInstruction.labels);
|
||||
|
||||
codeInstructions.RemoveAt(codeInstructions.Count - 1);
|
||||
}
|
||||
|
||||
// pass4 - mark labels and exceptions and emit codes
|
||||
//
|
||||
var idx = 0;
|
||||
codeInstructions.Do(codeInstruction =>
|
||||
{
|
||||
// mark all labels
|
||||
codeInstruction.labels.Do(label => Emitter.MarkLabel(generator, label));
|
||||
|
||||
// start all exception blocks
|
||||
// TODO: we ignore the resulting label because we have no way to use it
|
||||
//
|
||||
codeInstruction.blocks.Do(block => { Label? label; Emitter.MarkBlockBefore(generator, block, out label); });
|
||||
|
||||
var code = codeInstruction.opcode;
|
||||
var operand = codeInstruction.operand;
|
||||
|
||||
// replace RET with a jump to the end (outside this code)
|
||||
if (code == OpCodes.Ret)
|
||||
{
|
||||
var endLabel = generator.DefineLabel();
|
||||
code = OpCodes.Br;
|
||||
operand = endLabel;
|
||||
endLabels.Add(endLabel);
|
||||
}
|
||||
|
||||
// replace short jumps with long ones (can be optimized but requires byte counting, not instruction counting)
|
||||
if (shortJumps.TryGetValue(code, out var longJump))
|
||||
code = longJump;
|
||||
|
||||
var emitCode = true;
|
||||
|
||||
//if (code == OpCodes.Leave || code == OpCodes.Leave_S)
|
||||
//{
|
||||
// // skip LEAVE on EndExceptionBlock
|
||||
// if (codeInstruction.blocks.Any(block => block.blockType == ExceptionBlockType.EndExceptionBlock))
|
||||
// emitCode = false;
|
||||
|
||||
// // skip LEAVE on next instruction starts a new exception handler and we are already in
|
||||
// if (idx < instructions.Length - 1)
|
||||
// if (instructions[idx + 1].blocks.Any(block => block.blockType != ExceptionBlockType.EndExceptionBlock))
|
||||
// emitCode = false;
|
||||
//}
|
||||
|
||||
if (emitCode)
|
||||
{
|
||||
switch (code.OperandType)
|
||||
{
|
||||
case OperandType.InlineNone:
|
||||
Emitter.Emit(generator, code);
|
||||
break;
|
||||
|
||||
case OperandType.InlineSig:
|
||||
|
||||
// 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);
|
||||
Emitter.Emit(generator, code, (int)operand);
|
||||
|
||||
/*
|
||||
// the following will only work if we can convert the original signature token to the required arguments
|
||||
//
|
||||
var callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
|
||||
var returnType = typeof(object);
|
||||
var parameterTypes = new[] { typeof(object) };
|
||||
Emitter.EmitCalli(generator, code, callingConvention, returnType, parameterTypes);
|
||||
|
||||
var callingConventions = System.Reflection.CallingConventions.Standard;
|
||||
var optionalParameterTypes = new[] { typeof(object) };
|
||||
Emitter.EmitCalli(generator, code, callingConventions, returnType, parameterTypes, optionalParameterTypes);
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
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 (HarmonyInstance.DEBUG) FileLog.LogBuffered(Emitter.CodePos(generator) + code + " " + Emitter.FormatArgument(operand));
|
||||
emitMethod.Invoke(generator, new object[] { code, operand });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
codeInstruction.blocks.Do(block => Emitter.MarkBlockAfter(generator, block));
|
||||
|
||||
idx++;
|
||||
});
|
||||
}
|
||||
|
||||
// interpret member info value
|
||||
//
|
||||
static void GetMemberInfoValue(MemberInfo info, out object result)
|
||||
{
|
||||
result = null;
|
||||
switch (info.MemberType)
|
||||
{
|
||||
case MemberTypes.Constructor:
|
||||
result = (ConstructorInfo)info;
|
||||
break;
|
||||
|
||||
case MemberTypes.Event:
|
||||
result = (EventInfo)info;
|
||||
break;
|
||||
|
||||
case MemberTypes.Field:
|
||||
result = (FieldInfo)info;
|
||||
break;
|
||||
|
||||
case MemberTypes.Method:
|
||||
result = (MethodInfo)info;
|
||||
break;
|
||||
|
||||
case MemberTypes.TypeInfo:
|
||||
case MemberTypes.NestedType:
|
||||
result = (Type)info;
|
||||
break;
|
||||
|
||||
case MemberTypes.Property:
|
||||
result = (PropertyInfo)info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// interpret instruction operand
|
||||
//
|
||||
void ReadOperand(ILInstruction instruction)
|
||||
{
|
||||
switch (instruction.opcode.OperandType)
|
||||
{
|
||||
case OperandType.InlineNone:
|
||||
{
|
||||
instruction.argument = null;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineSwitch:
|
||||
{
|
||||
var length = ilBytes.ReadInt32();
|
||||
var base_offset = ilBytes.position + (4 * length);
|
||||
var branches = new int[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
branches[i] = ilBytes.ReadInt32() + base_offset;
|
||||
instruction.operand = branches;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
{
|
||||
var val = (sbyte)ilBytes.ReadByte();
|
||||
instruction.operand = val + ilBytes.position;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineBrTarget:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = val + ilBytes.position;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.ShortInlineI:
|
||||
{
|
||||
if (instruction.opcode == OpCodes.Ldc_I4_S)
|
||||
{
|
||||
var sb = (sbyte)ilBytes.ReadByte();
|
||||
instruction.operand = sb;
|
||||
instruction.argument = (sbyte)instruction.operand;
|
||||
}
|
||||
else
|
||||
{
|
||||
var b = ilBytes.ReadByte();
|
||||
instruction.operand = b;
|
||||
instruction.argument = (byte)instruction.operand;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineI:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = val;
|
||||
instruction.argument = (int)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.ShortInlineR:
|
||||
{
|
||||
var val = ilBytes.ReadSingle();
|
||||
instruction.operand = val;
|
||||
instruction.argument = (float)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineR:
|
||||
{
|
||||
var val = ilBytes.ReadDouble();
|
||||
instruction.operand = val;
|
||||
instruction.argument = (double)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineI8:
|
||||
{
|
||||
var val = ilBytes.ReadInt64();
|
||||
instruction.operand = val;
|
||||
instruction.argument = (long)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineSig:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
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.Break();
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineString:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = module.ResolveString(val);
|
||||
instruction.argument = (string)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineTok:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = module.ResolveMember(val, typeArguments, methodArguments);
|
||||
GetMemberInfoValue((MemberInfo)instruction.operand, out instruction.argument);
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineType:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = module.ResolveType(val, typeArguments, methodArguments);
|
||||
instruction.argument = (Type)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineMethod:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = module.ResolveMethod(val, typeArguments, methodArguments);
|
||||
if (instruction.operand is ConstructorInfo)
|
||||
instruction.argument = (ConstructorInfo)instruction.operand;
|
||||
else
|
||||
instruction.argument = (MethodInfo)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineField:
|
||||
{
|
||||
var val = ilBytes.ReadInt32();
|
||||
instruction.operand = module.ResolveField(val, typeArguments, methodArguments);
|
||||
instruction.argument = (FieldInfo)instruction.operand;
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.ShortInlineVar:
|
||||
{
|
||||
var idx = ilBytes.ReadByte();
|
||||
if (TargetsLocalVariable(instruction.opcode))
|
||||
{
|
||||
var lvi = GetLocalVariable(idx);
|
||||
if (lvi == null)
|
||||
instruction.argument = idx;
|
||||
else
|
||||
{
|
||||
instruction.operand = lvi;
|
||||
instruction.argument = variables[lvi.LocalIndex];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction.operand = GetParameter(idx);
|
||||
instruction.argument = idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OperandType.InlineVar:
|
||||
{
|
||||
var idx = ilBytes.ReadInt16();
|
||||
if (TargetsLocalVariable(instruction.opcode))
|
||||
{
|
||||
var lvi = GetLocalVariable(idx);
|
||||
if (lvi == null)
|
||||
instruction.argument = idx;
|
||||
else
|
||||
{
|
||||
instruction.operand = lvi;
|
||||
instruction.argument = variables[lvi.LocalIndex];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction.operand = GetParameter(idx);
|
||||
instruction.argument = idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
var min = 0;
|
||||
var max = lastInstructionIndex;
|
||||
while (min <= max)
|
||||
{
|
||||
var mid = min + ((max - min) / 2);
|
||||
var instruction = ilInstructions[mid];
|
||||
|
||||
if (isEndOfInstruction)
|
||||
{
|
||||
if (offset == instruction.offset + instruction.GetSize() - 1)
|
||||
return instruction;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset == instruction.offset)
|
||||
return instruction;
|
||||
}
|
||||
|
||||
if (offset < instruction.offset)
|
||||
max = mid - 1;
|
||||
else
|
||||
min = mid + 1;
|
||||
}
|
||||
|
||||
throw new Exception("Cannot find instruction for " + offset.ToString("X4"));
|
||||
}
|
||||
|
||||
static bool TargetsLocalVariable(OpCode opcode)
|
||||
{
|
||||
return opcode.Name.Contains("loc");
|
||||
}
|
||||
|
||||
LocalVariableInfo GetLocalVariable(int index)
|
||||
{
|
||||
return locals?[index];
|
||||
}
|
||||
|
||||
ParameterInfo GetParameter(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
return this_parameter;
|
||||
|
||||
return parameters[index - 1];
|
||||
}
|
||||
|
||||
OpCode ReadOpCode()
|
||||
{
|
||||
var op = ilBytes.ReadByte();
|
||||
return op != 0xfe
|
||||
? one_byte_opcodes[op]
|
||||
: two_bytes_opcodes[ilBytes.ReadByte()];
|
||||
}
|
||||
|
||||
MethodInfo EmitMethodForType(Type type)
|
||||
{
|
||||
foreach (var entry in emitMethods)
|
||||
if (entry.Key == type) return entry.Value;
|
||||
foreach (var entry in emitMethods)
|
||||
if (entry.Key.IsAssignableFrom(type)) return entry.Value;
|
||||
return null;
|
||||
}
|
||||
|
||||
// static initializer to prep opcodes
|
||||
|
||||
static readonly OpCode[] one_byte_opcodes;
|
||||
static readonly OpCode[] two_bytes_opcodes;
|
||||
|
||||
static readonly Dictionary<Type, MethodInfo> emitMethods;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
static MethodBodyReader()
|
||||
{
|
||||
one_byte_opcodes = new OpCode[0xe1];
|
||||
two_bytes_opcodes = new OpCode[0x1f];
|
||||
|
||||
var fields = typeof(OpCodes).GetFields(
|
||||
BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var opcode = (OpCode)field.GetValue(null);
|
||||
if (opcode.OpCodeType == OpCodeType.Nternal)
|
||||
continue;
|
||||
|
||||
if (opcode.Size == 1)
|
||||
one_byte_opcodes[opcode.Value] = opcode;
|
||||
else
|
||||
two_bytes_opcodes[opcode.Value & 0xff] = opcode;
|
||||
}
|
||||
|
||||
emitMethods = new Dictionary<Type, MethodInfo>();
|
||||
typeof(ILGenerator).GetMethods().ToList()
|
||||
.Do(method =>
|
||||
{
|
||||
if (method.Name != "Emit") return;
|
||||
var pinfos = method.GetParameters();
|
||||
if (pinfos.Length != 2) return;
|
||||
var types = pinfos.Select(p => p.ParameterType).ToArray();
|
||||
if (types[0] != typeof(OpCode)) return;
|
||||
emitMethods[types[1]] = method;
|
||||
});
|
||||
}
|
||||
|
||||
// a custom this parameter
|
||||
|
||||
class ThisParameter : ParameterInfo
|
||||
{
|
||||
public ThisParameter(MethodBase method)
|
||||
{
|
||||
MemberImpl = method;
|
||||
ClassImpl = method.DeclaringType;
|
||||
NameImpl = "this";
|
||||
PositionImpl = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,271 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.Remoting.Contexts;
|
||||
using System.Linq;
|
||||
|
||||
namespace Harmony.ILCopying
|
||||
{
|
||||
/*
|
||||
* TODO - this needs to be worked on. The purpose is to decode the signature into
|
||||
* a high level reflection based calling signature that is valid in the
|
||||
* current assembly
|
||||
*
|
||||
* See also where OperandType.InlineSig is handled in MethodCopier.cs
|
||||
*
|
||||
public static class Signature
|
||||
{
|
||||
internal const byte DEFAULT = 0x00;
|
||||
internal const byte VARARG = 0x05;
|
||||
internal const byte GENERIC = 0x10;
|
||||
internal const byte HASTHIS = 0x20;
|
||||
internal const byte EXPLICITTHIS = 0x40;
|
||||
internal const byte FIELD = 0x06;
|
||||
internal const byte LOCAL_SIG = 0x07;
|
||||
internal const byte PROPERTY = 0x08;
|
||||
internal const byte GENERICINST = 0x0A;
|
||||
internal const byte SENTINEL = 0x41;
|
||||
internal const byte ELEMENT_TYPE_VOID = 0x01;
|
||||
internal const byte ELEMENT_TYPE_BOOLEAN = 0x02;
|
||||
internal const byte ELEMENT_TYPE_CHAR = 0x03;
|
||||
internal const byte ELEMENT_TYPE_I1 = 0x04;
|
||||
internal const byte ELEMENT_TYPE_U1 = 0x05;
|
||||
internal const byte ELEMENT_TYPE_I2 = 0x06;
|
||||
internal const byte ELEMENT_TYPE_U2 = 0x07;
|
||||
internal const byte ELEMENT_TYPE_I4 = 0x08;
|
||||
internal const byte ELEMENT_TYPE_U4 = 0x09;
|
||||
internal const byte ELEMENT_TYPE_I8 = 0x0a;
|
||||
internal const byte ELEMENT_TYPE_U8 = 0x0b;
|
||||
internal const byte ELEMENT_TYPE_R4 = 0x0c;
|
||||
internal const byte ELEMENT_TYPE_R8 = 0x0d;
|
||||
internal const byte ELEMENT_TYPE_STRING = 0x0e;
|
||||
internal const byte ELEMENT_TYPE_PTR = 0x0f;
|
||||
internal const byte ELEMENT_TYPE_BYREF = 0x10;
|
||||
internal const byte ELEMENT_TYPE_VALUETYPE = 0x11;
|
||||
internal const byte ELEMENT_TYPE_CLASS = 0x12;
|
||||
internal const byte ELEMENT_TYPE_VAR = 0x13;
|
||||
internal const byte ELEMENT_TYPE_ARRAY = 0x14;
|
||||
internal const byte ELEMENT_TYPE_GENERICINST = 0x15;
|
||||
internal const byte ELEMENT_TYPE_TYPEDBYREF = 0x16;
|
||||
internal const byte ELEMENT_TYPE_I = 0x18;
|
||||
internal const byte ELEMENT_TYPE_U = 0x19;
|
||||
internal const byte ELEMENT_TYPE_FNPTR = 0x1b;
|
||||
internal const byte ELEMENT_TYPE_OBJECT = 0x1c;
|
||||
internal const byte ELEMENT_TYPE_SZARRAY = 0x1d;
|
||||
internal const byte ELEMENT_TYPE_MVAR = 0x1e;
|
||||
internal const byte ELEMENT_TYPE_CMOD_REQD = 0x1f;
|
||||
internal const byte ELEMENT_TYPE_CMOD_OPT = 0x20;
|
||||
internal const byte ELEMENT_TYPE_PINNED = 0x45;
|
||||
|
||||
static int ReadCompressedUInt(byte[] bytes, ref int n)
|
||||
{
|
||||
var b1 = bytes[n++];
|
||||
if (b1 <= 0x7F)
|
||||
{
|
||||
return b1;
|
||||
}
|
||||
else if ((b1 & 0xC0) == 0x80)
|
||||
{
|
||||
var b2 = bytes[n++];
|
||||
return ((b1 & 0x3F) << 8) | b2;
|
||||
}
|
||||
else
|
||||
{
|
||||
var b2 = bytes[n++];
|
||||
var b3 = bytes[n++];
|
||||
var b4 = bytes[n++];
|
||||
return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
|
||||
}
|
||||
}
|
||||
|
||||
static Type ReadTypeOrVoid(Module module, byte[] bytes, ref int n, Context context)
|
||||
{
|
||||
if (bytes[n] == ELEMENT_TYPE_VOID)
|
||||
{
|
||||
n++;
|
||||
return module.GetType("System.Void");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadType(module, br, context);
|
||||
}
|
||||
}
|
||||
|
||||
static Type ReadFunctionPointer(Module module, byte[] bytes, ref int n, Context context)
|
||||
{
|
||||
var len = bytes.Length - n;
|
||||
var newBytes = new byte[len];
|
||||
for (var i = 0; i < len; i++)
|
||||
newBytes[i] = bytes[n + i];
|
||||
|
||||
var sig = ReadStandaloneSignature(module, newBytes, context);
|
||||
if (module.universe.EnableFunctionPointers)
|
||||
{
|
||||
return FunctionPointerType.Make(module.universe, sig);
|
||||
}
|
||||
else
|
||||
{
|
||||
// by default, like .NET we return System.IntPtr here
|
||||
return module.universe.System_IntPtr;
|
||||
}
|
||||
}
|
||||
|
||||
static Type ReadType(Module module, byte[] bytes, ref int n, Context context)
|
||||
{
|
||||
CustomModifiers mods;
|
||||
switch (bytes[n++])
|
||||
{
|
||||
case ELEMENT_TYPE_CLASS:
|
||||
return ReadTypeDefOrRefEncoded(module, br, context).MarkNotValueType();
|
||||
case ELEMENT_TYPE_VALUETYPE:
|
||||
return ReadTypeDefOrRefEncoded(module, br, context).MarkValueType();
|
||||
case ELEMENT_TYPE_BOOLEAN:
|
||||
return module.GetType("System.Boolean");
|
||||
case ELEMENT_TYPE_CHAR:
|
||||
return module.GetType("System.Char");
|
||||
case ELEMENT_TYPE_I1:
|
||||
return module.GetType("System.SByte");
|
||||
case ELEMENT_TYPE_U1:
|
||||
return module.GetType("System.Byte");
|
||||
case ELEMENT_TYPE_I2:
|
||||
return module.GetType("System.Int16");
|
||||
case ELEMENT_TYPE_U2:
|
||||
return module.GetType("System.UInt16");
|
||||
case ELEMENT_TYPE_I4:
|
||||
return module.GetType("System.Int32");
|
||||
case ELEMENT_TYPE_U4:
|
||||
return module.GetType("System.UInt32");
|
||||
case ELEMENT_TYPE_I8:
|
||||
return module.GetType("System.Int64");
|
||||
case ELEMENT_TYPE_U8:
|
||||
return module.GetType("System.UInt64");
|
||||
case ELEMENT_TYPE_R4:
|
||||
return module.GetType("System.Single");
|
||||
case ELEMENT_TYPE_R8:
|
||||
return module.GetType("System.Double");
|
||||
case ELEMENT_TYPE_I:
|
||||
return module.GetType("System.IntPtr");
|
||||
case ELEMENT_TYPE_U:
|
||||
return module.GetType("System.UIntPtr");
|
||||
case ELEMENT_TYPE_STRING:
|
||||
return module.GetType("System.String");
|
||||
case ELEMENT_TYPE_OBJECT:
|
||||
return module.GetType("System.Object");
|
||||
case ELEMENT_TYPE_VAR:
|
||||
return context.GetGenericTypeArgument(br.ReadCompressedUInt());
|
||||
case ELEMENT_TYPE_MVAR:
|
||||
return context.GetGenericMethodArgument(br.ReadCompressedUInt());
|
||||
case ELEMENT_TYPE_GENERICINST:
|
||||
return ReadGenericInst(module, br, context);
|
||||
case ELEMENT_TYPE_SZARRAY:
|
||||
mods = CustomModifiers.Read(module, br, context);
|
||||
return ReadType(module, br, context).__MakeArrayType(mods);
|
||||
case ELEMENT_TYPE_ARRAY:
|
||||
mods = CustomModifiers.Read(module, br, context);
|
||||
return ReadType(module, br, context).__MakeArrayType(br.ReadCompressedUInt(), ReadArraySizes(br), ReadArrayBounds(br), mods);
|
||||
case ELEMENT_TYPE_PTR:
|
||||
mods = CustomModifiers.Read(module, br, context);
|
||||
return ReadTypeOrVoid(module, br, context).__MakePointerType(mods);
|
||||
case ELEMENT_TYPE_FNPTR:
|
||||
return ReadFunctionPointer(module, br, context);
|
||||
default:
|
||||
throw new BadImageFormatException();
|
||||
}
|
||||
}
|
||||
|
||||
static Type ReadTypeOrByRef(Module module, byte[] bytes, ref int n, Context context)
|
||||
{
|
||||
if (bytes[n] == ELEMENT_TYPE_BYREF)
|
||||
{
|
||||
n++;
|
||||
// LAMESPEC it is allowed (by C++/CLI, ilasm and peverify) to have custom modifiers after the BYREF
|
||||
// (which makes sense, as it is analogous to pointers)
|
||||
CustomModifiers mods = CustomModifiers.Read(module, br, context);
|
||||
// C++/CLI generates void& local variables, so we need to use ReadTypeOrVoid here
|
||||
return ReadTypeOrVoid(module, br, context).__MakeByRefType(mods);
|
||||
}
|
||||
return ReadType(module, br, context);
|
||||
}
|
||||
|
||||
static Type ReadRetType(Module module, byte[] bytes, ref int n, Context context)
|
||||
{
|
||||
switch (bytes[n])
|
||||
{
|
||||
case ELEMENT_TYPE_VOID:
|
||||
n++;
|
||||
return module.GetType("System.Void");
|
||||
case ELEMENT_TYPE_TYPEDBYREF:
|
||||
n++;
|
||||
return module.GetType("System.TypedReference");
|
||||
default:
|
||||
return ReadTypeOrByRef(module, br, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadStandaloneSignature(Module module, byte[] bytes, Context context)
|
||||
{
|
||||
CallingConvention unmanagedCallingConvention;
|
||||
CallingConventions callingConvention;
|
||||
|
||||
var n = 0;
|
||||
unmanagedCallingConvention = 0;
|
||||
callingConvention = 0;
|
||||
|
||||
var flags = bytes[n++];
|
||||
bool unmanaged;
|
||||
switch (flags & 7)
|
||||
{
|
||||
case DEFAULT:
|
||||
callingConvention = CallingConventions.Standard;
|
||||
unmanaged = false;
|
||||
break;
|
||||
case 0x01: // C
|
||||
unmanagedCallingConvention = CallingConvention.Cdecl;
|
||||
unmanaged = true;
|
||||
break;
|
||||
case 0x02: // STDCALL
|
||||
unmanagedCallingConvention = CallingConvention.StdCall;
|
||||
unmanaged = true;
|
||||
break;
|
||||
case 0x03: // THISCALL
|
||||
unmanagedCallingConvention = CallingConvention.ThisCall;
|
||||
unmanaged = true;
|
||||
break;
|
||||
case 0x04: // FASTCALL
|
||||
unmanagedCallingConvention = CallingConvention.FastCall;
|
||||
unmanaged = true;
|
||||
break;
|
||||
case VARARG:
|
||||
callingConvention = CallingConventions.VarArgs;
|
||||
unmanaged = false;
|
||||
break;
|
||||
default:
|
||||
throw new BadImageFormatException();
|
||||
}
|
||||
if ((flags & HASTHIS) != 0) callingConvention |= CallingConventions.HasThis;
|
||||
if ((flags & EXPLICITTHIS) != 0) callingConvention |= CallingConventions.ExplicitThis;
|
||||
if ((flags & GENERIC) != 0) throw new BadImageFormatException();
|
||||
var paramCount = ReadCompressedUInt(bytes, ref n);
|
||||
CustomModifiers[] customModifiers = null;
|
||||
PackedCustomModifiers.Pack(ref customModifiers, 0, CustomModifiers.Read(module, br, context), paramCount + 1);
|
||||
Type returnType = ReadRetType(module, br, context);
|
||||
List<Type> parameterTypes = new List<Type>();
|
||||
List<Type> optionalParameterTypes = new List<Type>();
|
||||
List<Type> curr = parameterTypes;
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
if (br.PeekByte() == SENTINEL)
|
||||
{
|
||||
br.ReadByte();
|
||||
curr = optionalParameterTypes;
|
||||
}
|
||||
PackedCustomModifiers.Pack(ref customModifiers, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1);
|
||||
curr.Add(ReadParam(module, br, context));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,419 @@
|
|||
using Harmony.ILCopying;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class MethodPatcher
|
||||
{
|
||||
// special parameter names that can be used in prefix and postfix methods
|
||||
//
|
||||
public static string INSTANCE_PARAM = "__instance";
|
||||
public static string ORIGINAL_METHOD_PARAM = "__originalMethod";
|
||||
public static string RESULT_VAR = "__result";
|
||||
public static string STATE_VAR = "__state";
|
||||
public static string PARAM_INDEX_PREFIX = "__";
|
||||
public static string INSTANCE_FIELD_PREFIX = "___";
|
||||
|
||||
// in case of trouble, set to true to write dynamic method to desktop as a dll
|
||||
// won't work for all methods because of the inability to extend a type compared
|
||||
// to the way DynamicTools.CreateDynamicMethod works
|
||||
//
|
||||
static readonly bool DEBUG_METHOD_GENERATION_BY_DLL_CREATION = false;
|
||||
|
||||
// for fixing old harmony bugs
|
||||
[UpgradeToLatestVersion(1)]
|
||||
public static DynamicMethod CreatePatchedMethod(MethodBase original, List<MethodInfo> prefixes, List<MethodInfo> postfixes, List<MethodInfo> transpilers)
|
||||
{
|
||||
return CreatePatchedMethod(original, "HARMONY_PATCH_1.1.1", prefixes, postfixes, transpilers);
|
||||
}
|
||||
|
||||
public static DynamicMethod CreatePatchedMethod(MethodBase original, string harmonyInstanceID, List<MethodInfo> prefixes, List<MethodInfo> postfixes, List<MethodInfo> transpilers)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (HarmonyInstance.DEBUG) FileLog.LogBuffered("### Patch " + original.DeclaringType + ", " + original);
|
||||
|
||||
var idx = prefixes.Count() + postfixes.Count();
|
||||
var patch = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx);
|
||||
if (patch == null)
|
||||
return null;
|
||||
|
||||
var il = patch.GetILGenerator();
|
||||
|
||||
// for debugging
|
||||
AssemblyBuilder assemblyBuilder = null;
|
||||
TypeBuilder typeBuilder = null;
|
||||
if (DEBUG_METHOD_GENERATION_BY_DLL_CREATION)
|
||||
il = DynamicTools.CreateSaveableMethod(original, "_Patch" + idx, out assemblyBuilder, out typeBuilder);
|
||||
|
||||
var originalVariables = DynamicTools.DeclareLocalVariables(original, il);
|
||||
var privateVars = new Dictionary<string, LocalBuilder>();
|
||||
|
||||
LocalBuilder resultVariable = null;
|
||||
if (idx > 0)
|
||||
{
|
||||
resultVariable = DynamicTools.DeclareLocalVariable(il, AccessTools.GetReturnedType(original));
|
||||
privateVars[RESULT_VAR] = resultVariable;
|
||||
}
|
||||
|
||||
prefixes.ForEach(prefix =>
|
||||
{
|
||||
prefix.GetParameters()
|
||||
.Where(patchParam => patchParam.Name == STATE_VAR)
|
||||
.Do(patchParam =>
|
||||
{
|
||||
var privateStateVariable = DynamicTools.DeclareLocalVariable(il, patchParam.ParameterType);
|
||||
privateVars[prefix.DeclaringType.FullName] = privateStateVariable;
|
||||
});
|
||||
});
|
||||
|
||||
var skipOriginalLabel = il.DefineLabel();
|
||||
var canHaveJump = AddPrefixes(il, original, prefixes, privateVars, skipOriginalLabel);
|
||||
|
||||
var copier = new MethodCopier(original, il, originalVariables);
|
||||
foreach (var transpiler in transpilers)
|
||||
copier.AddTranspiler(transpiler);
|
||||
|
||||
var endLabels = new List<Label>();
|
||||
var endBlocks = new List<ExceptionBlock>();
|
||||
copier.Finalize(endLabels, endBlocks);
|
||||
|
||||
foreach (var label in endLabels)
|
||||
Emitter.MarkLabel(il, label);
|
||||
foreach (var block in endBlocks)
|
||||
Emitter.MarkBlockAfter(il, block);
|
||||
if (resultVariable != null)
|
||||
Emitter.Emit(il, OpCodes.Stloc, resultVariable);
|
||||
if (canHaveJump)
|
||||
Emitter.MarkLabel(il, skipOriginalLabel);
|
||||
|
||||
AddPostfixes(il, original, postfixes, privateVars, false);
|
||||
|
||||
if (resultVariable != null)
|
||||
Emitter.Emit(il, OpCodes.Ldloc, resultVariable);
|
||||
|
||||
AddPostfixes(il, original, postfixes, privateVars, true);
|
||||
|
||||
Emitter.Emit(il, OpCodes.Ret);
|
||||
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
FileLog.LogBuffered("DONE");
|
||||
FileLog.LogBuffered("");
|
||||
FileLog.FlushBuffer();
|
||||
}
|
||||
|
||||
// for debugging
|
||||
if (DEBUG_METHOD_GENERATION_BY_DLL_CREATION)
|
||||
{
|
||||
DynamicTools.SaveMethod(assemblyBuilder, typeBuilder);
|
||||
return null;
|
||||
}
|
||||
|
||||
DynamicTools.PrepareDynamicMethod(patch);
|
||||
return patch;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Exception from HarmonyInstance \"" + harmonyInstanceID + "\"", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (HarmonyInstance.DEBUG)
|
||||
FileLog.FlushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
static OpCode LoadIndOpCodeFor(Type type)
|
||||
{
|
||||
if (type.IsEnum) return OpCodes.Ldind_I4;
|
||||
|
||||
if (type == typeof(float)) return OpCodes.Ldind_R4;
|
||||
if (type == typeof(double)) return OpCodes.Ldind_R8;
|
||||
|
||||
if (type == typeof(byte)) return OpCodes.Ldind_U1;
|
||||
if (type == typeof(ushort)) return OpCodes.Ldind_U2;
|
||||
if (type == typeof(uint)) return OpCodes.Ldind_U4;
|
||||
if (type == typeof(ulong)) return OpCodes.Ldind_I8;
|
||||
|
||||
if (type == typeof(sbyte)) return OpCodes.Ldind_I1;
|
||||
if (type == typeof(short)) return OpCodes.Ldind_I2;
|
||||
if (type == typeof(int)) return OpCodes.Ldind_I4;
|
||||
if (type == typeof(long)) return OpCodes.Ldind_I8;
|
||||
|
||||
return OpCodes.Ldind_Ref;
|
||||
}
|
||||
|
||||
static HarmonyArgument GetArgumentAttribute(this ParameterInfo parameter)
|
||||
{
|
||||
return parameter.GetCustomAttributes(false).FirstOrDefault(attr => attr is HarmonyArgument) as HarmonyArgument;
|
||||
}
|
||||
|
||||
static HarmonyArgument[] GetArgumentAttributes(this MethodInfo method)
|
||||
{
|
||||
return method.GetCustomAttributes(false).Where(attr => attr is HarmonyArgument).Cast<HarmonyArgument>().ToArray();
|
||||
}
|
||||
|
||||
static HarmonyArgument[] GetArgumentAttributes(this Type type)
|
||||
{
|
||||
return type.GetCustomAttributes(false).Where(attr => attr is HarmonyArgument).Cast<HarmonyArgument>().ToArray();
|
||||
}
|
||||
|
||||
static string GetOriginalArgumentName(this ParameterInfo parameter, string[] originalParameterNames)
|
||||
{
|
||||
var attribute = parameter.GetArgumentAttribute();
|
||||
if (attribute == null)
|
||||
return null;
|
||||
|
||||
if (string.IsNullOrEmpty(attribute.OriginalName) == false)
|
||||
return attribute.OriginalName;
|
||||
|
||||
if (attribute.Index >= 0 && attribute.Index < originalParameterNames.Length)
|
||||
return originalParameterNames[attribute.Index];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string GetOriginalArgumentName(HarmonyArgument[] attributes, string name, string[] originalParameterNames)
|
||||
{
|
||||
if (attributes.Length <= 0)
|
||||
return null;
|
||||
|
||||
var attribute = attributes.SingleOrDefault(p => p.NewName == name);
|
||||
if (attribute == null)
|
||||
return null;
|
||||
|
||||
if (string.IsNullOrEmpty(attribute.OriginalName) == false)
|
||||
return attribute.OriginalName;
|
||||
|
||||
if (attribute.Index >= 0 && attribute.Index < originalParameterNames.Length)
|
||||
return originalParameterNames[attribute.Index];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string GetOriginalArgumentName(this MethodInfo method, string[] originalParameterNames, string name)
|
||||
{
|
||||
string argumentName;
|
||||
|
||||
argumentName = GetOriginalArgumentName(method.GetArgumentAttributes(), name, originalParameterNames);
|
||||
if (argumentName != null)
|
||||
return argumentName;
|
||||
|
||||
argumentName = GetOriginalArgumentName(method.DeclaringType.GetArgumentAttributes(), name, originalParameterNames);
|
||||
if (argumentName != null)
|
||||
return argumentName;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private static int GetArgumentIndex(MethodInfo patch, string[] originalParameterNames, ParameterInfo patchParam)
|
||||
{
|
||||
var originalName = patchParam.GetOriginalArgumentName(originalParameterNames);
|
||||
if (originalName != null)
|
||||
return Array.IndexOf(originalParameterNames, originalName);
|
||||
|
||||
var patchParamName = patchParam.Name;
|
||||
originalName = patch.GetOriginalArgumentName(originalParameterNames, patchParamName);
|
||||
if (originalName != null)
|
||||
return Array.IndexOf(originalParameterNames, originalName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static MethodInfo getMethodMethod = typeof(MethodBase).GetMethod("GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) });
|
||||
|
||||
static void EmitCallParameter(ILGenerator il, MethodBase original, MethodInfo patch, Dictionary<string, LocalBuilder> variables, bool allowFirsParamPassthrough)
|
||||
{
|
||||
var isInstance = original.IsStatic == false;
|
||||
var originalParameters = original.GetParameters();
|
||||
var originalParameterNames = originalParameters.Select(p => p.Name).ToArray();
|
||||
|
||||
// check for passthrough using first parameter (which must have same type as return type)
|
||||
var parameters = patch.GetParameters().ToList();
|
||||
if (allowFirsParamPassthrough && patch.ReturnType != typeof(void) && parameters.Count > 0 && parameters[0].ParameterType == patch.ReturnType)
|
||||
parameters.RemoveRange(0, 1);
|
||||
|
||||
foreach (var patchParam in parameters)
|
||||
{
|
||||
if (patchParam.Name == ORIGINAL_METHOD_PARAM)
|
||||
{
|
||||
var constructorInfo = original as ConstructorInfo;
|
||||
if (constructorInfo != null)
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldtoken, constructorInfo);
|
||||
Emitter.Emit(il, OpCodes.Call, getMethodMethod);
|
||||
continue;
|
||||
}
|
||||
var methodInfo = original as MethodInfo;
|
||||
if (methodInfo != null)
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldtoken, methodInfo);
|
||||
Emitter.Emit(il, OpCodes.Call, getMethodMethod);
|
||||
continue;
|
||||
}
|
||||
Emitter.Emit(il, OpCodes.Ldnull);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (patchParam.Name == INSTANCE_PARAM)
|
||||
{
|
||||
if (original.IsStatic)
|
||||
Emitter.Emit(il, OpCodes.Ldnull);
|
||||
else if (patchParam.ParameterType.IsByRef)
|
||||
Emitter.Emit(il, OpCodes.Ldarga, 0); // probably won't work or will be useless
|
||||
else
|
||||
Emitter.Emit(il, OpCodes.Ldarg_0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (patchParam.Name.StartsWith(INSTANCE_FIELD_PREFIX))
|
||||
{
|
||||
var fieldName = patchParam.Name.Substring(INSTANCE_FIELD_PREFIX.Length);
|
||||
FieldInfo fieldInfo;
|
||||
if (fieldName.All(char.IsDigit))
|
||||
{
|
||||
fieldInfo = AccessTools.Field(original.DeclaringType, int.Parse(fieldName));
|
||||
if (fieldInfo == null)
|
||||
throw new ArgumentException("No field found at given index in class " + original.DeclaringType.FullName, fieldName);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldInfo = AccessTools.Field(original.DeclaringType, fieldName);
|
||||
if (fieldInfo == null)
|
||||
throw new ArgumentException("No such field defined in class " + original.DeclaringType.FullName, fieldName);
|
||||
}
|
||||
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
if (patchParam.ParameterType.IsByRef)
|
||||
Emitter.Emit(il, OpCodes.Ldsflda, fieldInfo);
|
||||
else
|
||||
Emitter.Emit(il, OpCodes.Ldsfld, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (patchParam.ParameterType.IsByRef)
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldarg_0);
|
||||
Emitter.Emit(il, OpCodes.Ldflda, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldarg_0);
|
||||
Emitter.Emit(il, OpCodes.Ldfld, fieldInfo);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (patchParam.Name == STATE_VAR)
|
||||
{
|
||||
var ldlocCode = patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
|
||||
Emitter.Emit(il, ldlocCode, variables[patch.DeclaringType.FullName]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (patchParam.Name == RESULT_VAR)
|
||||
{
|
||||
if (AccessTools.GetReturnedType(original) == typeof(void))
|
||||
throw new Exception("Cannot get result from void method " + original.FullDescription());
|
||||
var ldlocCode = patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
|
||||
Emitter.Emit(il, ldlocCode, variables[RESULT_VAR]);
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx;
|
||||
if (patchParam.Name.StartsWith(PARAM_INDEX_PREFIX))
|
||||
{
|
||||
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");
|
||||
if (idx < 0 || idx >= originalParameters.Length)
|
||||
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());
|
||||
}
|
||||
|
||||
// original -> patch opcode
|
||||
// --------------------------------------
|
||||
// 1 normal -> normal : LDARG
|
||||
// 2 normal -> ref/out : LDARGA
|
||||
// 3 ref/out -> normal : LDARG, LDIND_x
|
||||
// 4 ref/out -> ref/out : LDARG
|
||||
//
|
||||
var originalIsNormal = originalParameters[idx].IsOut == false && originalParameters[idx].ParameterType.IsByRef == false;
|
||||
var patchIsNormal = patchParam.IsOut == false && patchParam.ParameterType.IsByRef == false;
|
||||
var patchArgIndex = idx + (isInstance ? 1 : 0);
|
||||
|
||||
// Case 1 + 4
|
||||
if (originalIsNormal == patchIsNormal)
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldarg, patchArgIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 2
|
||||
if (originalIsNormal && patchIsNormal == false)
|
||||
{
|
||||
Emitter.Emit(il, OpCodes.Ldarga, patchArgIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 3
|
||||
Emitter.Emit(il, OpCodes.Ldarg, patchArgIndex);
|
||||
Emitter.Emit(il, LoadIndOpCodeFor(originalParameters[idx].ParameterType));
|
||||
}
|
||||
}
|
||||
|
||||
static bool AddPrefixes(ILGenerator il, MethodBase original, List<MethodInfo> prefixes, Dictionary<string, LocalBuilder> variables, Label label)
|
||||
{
|
||||
var canHaveJump = false;
|
||||
prefixes.ForEach(fix =>
|
||||
{
|
||||
EmitCallParameter(il, original, fix, variables, false);
|
||||
Emitter.Emit(il, OpCodes.Call, fix);
|
||||
|
||||
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);
|
||||
Emitter.Emit(il, OpCodes.Brfalse, label);
|
||||
canHaveJump = true;
|
||||
}
|
||||
});
|
||||
return canHaveJump;
|
||||
}
|
||||
|
||||
static void AddPostfixes(ILGenerator il, MethodBase original, List<MethodInfo> postfixes, Dictionary<string, LocalBuilder> variables, bool passthroughPatches)
|
||||
{
|
||||
postfixes
|
||||
.Where(fix => passthroughPatches == (fix.ReturnType != typeof(void)))
|
||||
.Do(fix =>
|
||||
{
|
||||
EmitCallParameter(il, original, fix, variables, true);
|
||||
Emitter.Emit(il, OpCodes.Call, fix);
|
||||
|
||||
if (fix.ReturnType != typeof(void))
|
||||
{
|
||||
var firstFixParam = fix.GetParameters().FirstOrDefault();
|
||||
var hasPassThroughResultParam = firstFixParam != null && fix.ReturnType == firstFixParam.ParameterType;
|
||||
if (!hasPassThroughResultParam)
|
||||
{
|
||||
if (firstFixParam != null)
|
||||
throw new Exception("Return type of postfix patch " + fix + " does match type of its first parameter");
|
||||
|
||||
throw new Exception("Postfix patch " + fix + " must have a \"void\" return type");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class PatchInfoSerialization
|
||||
{
|
||||
class Binder : SerializationBinder
|
||||
{
|
||||
public override Type BindToType(string assemblyName, string typeName)
|
||||
{
|
||||
var types = new Type[] {
|
||||
typeof(PatchInfo),
|
||||
typeof(Patch[]),
|
||||
typeof(Patch)
|
||||
};
|
||||
foreach (var type in types)
|
||||
if (typeName == type.FullName)
|
||||
return type;
|
||||
var typeToDeserialize = Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
|
||||
return typeToDeserialize;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Serialize(this PatchInfo patchInfo)
|
||||
{
|
||||
#pragma warning disable XS0001
|
||||
using (var streamMemory = new MemoryStream())
|
||||
{
|
||||
var formatter = new BinaryFormatter();
|
||||
formatter.Serialize(streamMemory, patchInfo);
|
||||
return streamMemory.GetBuffer();
|
||||
}
|
||||
#pragma warning restore XS0001
|
||||
}
|
||||
|
||||
public static PatchInfo Deserialize(byte[] bytes)
|
||||
{
|
||||
var formatter = new BinaryFormatter { Binder = new Binder() };
|
||||
#pragma warning disable XS0001
|
||||
var streamMemory = new MemoryStream(bytes);
|
||||
#pragma warning restore XS0001
|
||||
return (PatchInfo)formatter.Deserialize(streamMemory);
|
||||
}
|
||||
|
||||
// general sorting by (in that order): before, after, priority and index
|
||||
public static int PriorityComparer(object obj, int index, int priority, string[] before, string[] after)
|
||||
{
|
||||
var trv = Traverse.Create(obj);
|
||||
var theirOwner = trv.Field("owner").GetValue<string>();
|
||||
var theirPriority = trv.Field("priority").GetValue<int>();
|
||||
var theirIndex = trv.Field("index").GetValue<int>();
|
||||
|
||||
if (before != null && Array.IndexOf(before, theirOwner) > -1)
|
||||
return -1;
|
||||
if (after != null && Array.IndexOf(after, theirOwner) > -1)
|
||||
return 1;
|
||||
|
||||
if (priority != theirPriority)
|
||||
return -(priority.CompareTo(theirPriority));
|
||||
|
||||
return index.CompareTo(theirIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PatchInfo
|
||||
{
|
||||
public Patch[] prefixes;
|
||||
public Patch[] postfixes;
|
||||
public Patch[] transpilers;
|
||||
|
||||
public PatchInfo()
|
||||
{
|
||||
prefixes = new Patch[0];
|
||||
postfixes = new Patch[0];
|
||||
transpilers = new Patch[0];
|
||||
}
|
||||
|
||||
public void AddPrefix(MethodInfo patch, string owner, int priority, string[] before, string[] after)
|
||||
{
|
||||
var l = prefixes.ToList();
|
||||
l.Add(new Patch(patch, prefixes.Count() + 1, owner, priority, before, after));
|
||||
prefixes = l.ToArray();
|
||||
}
|
||||
|
||||
public void RemovePrefix(string owner)
|
||||
{
|
||||
if (owner == "*")
|
||||
{
|
||||
prefixes = new Patch[0];
|
||||
return;
|
||||
}
|
||||
prefixes = prefixes.Where(patch => patch.owner != owner).ToArray();
|
||||
}
|
||||
|
||||
public void AddPostfix(MethodInfo patch, string owner, int priority, string[] before, string[] after)
|
||||
{
|
||||
var l = postfixes.ToList();
|
||||
l.Add(new Patch(patch, postfixes.Count() + 1, owner, priority, before, after));
|
||||
postfixes = l.ToArray();
|
||||
}
|
||||
|
||||
public void RemovePostfix(string owner)
|
||||
{
|
||||
if (owner == "*")
|
||||
{
|
||||
postfixes = new Patch[0];
|
||||
return;
|
||||
}
|
||||
postfixes = postfixes.Where(patch => patch.owner != owner).ToArray();
|
||||
}
|
||||
|
||||
public void AddTranspiler(MethodInfo patch, string owner, int priority, string[] before, string[] after)
|
||||
{
|
||||
var l = transpilers.ToList();
|
||||
l.Add(new Patch(patch, transpilers.Count() + 1, owner, priority, before, after));
|
||||
transpilers = l.ToArray();
|
||||
}
|
||||
|
||||
public void RemoveTranspiler(string owner)
|
||||
{
|
||||
if (owner == "*")
|
||||
{
|
||||
transpilers = new Patch[0];
|
||||
return;
|
||||
}
|
||||
transpilers = transpilers.Where(patch => patch.owner != owner).ToArray();
|
||||
}
|
||||
|
||||
public void RemovePatch(MethodInfo patch)
|
||||
{
|
||||
prefixes = prefixes.Where(p => p.patch != patch).ToArray();
|
||||
postfixes = postfixes.Where(p => p.patch != patch).ToArray();
|
||||
transpilers = transpilers.Where(p => p.patch != patch).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Patch : IComparable
|
||||
{
|
||||
readonly public int index;
|
||||
readonly public string owner;
|
||||
readonly public int priority;
|
||||
readonly public string[] before;
|
||||
readonly public string[] after;
|
||||
|
||||
readonly public MethodInfo patch;
|
||||
|
||||
public Patch(MethodInfo patch, int index, string owner, int priority, string[] before, string[] after)
|
||||
{
|
||||
if (patch is DynamicMethod) throw new Exception("Cannot directly reference dynamic method \"" + patch.FullDescription() + "\" in Harmony. Use a factory method instead that will return the dynamic method.");
|
||||
|
||||
this.index = index;
|
||||
this.owner = owner;
|
||||
this.priority = priority;
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
this.patch = patch;
|
||||
}
|
||||
|
||||
public MethodInfo GetMethod(MethodBase original)
|
||||
{
|
||||
if (patch.ReturnType != typeof(DynamicMethod)) return patch;
|
||||
if (patch.IsStatic == false) return patch;
|
||||
var parameters = patch.GetParameters();
|
||||
if (parameters.Count() != 1) return patch;
|
||||
if (parameters[0].ParameterType != typeof(MethodBase)) return patch;
|
||||
|
||||
// we have a DynamicMethod factory, let's use it
|
||||
return patch.Invoke(null, new object[] { original }) as DynamicMethod;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return ((obj != null) && (obj is Patch) && (patch == ((Patch)obj).patch));
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
return PatchInfoSerialization.PriorityComparer(obj, index, priority, before, after);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return patch.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
using Harmony.ILCopying;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class PatchFunctions
|
||||
{
|
||||
public static void AddPrefix(PatchInfo patchInfo, string owner, HarmonyMethod info)
|
||||
{
|
||||
if (info == null || info.method == null) return;
|
||||
|
||||
var priority = info.prioritiy == -1 ? Priority.Normal : info.prioritiy;
|
||||
var before = info.before ?? new string[0];
|
||||
var after = info.after ?? new string[0];
|
||||
|
||||
patchInfo.AddPrefix(info.method, owner, priority, before, after);
|
||||
}
|
||||
|
||||
public static void RemovePrefix(PatchInfo patchInfo, string owner)
|
||||
{
|
||||
patchInfo.RemovePrefix(owner);
|
||||
}
|
||||
|
||||
public static void AddPostfix(PatchInfo patchInfo, string owner, HarmonyMethod info)
|
||||
{
|
||||
if (info == null || info.method == null) return;
|
||||
|
||||
var priority = info.prioritiy == -1 ? Priority.Normal : info.prioritiy;
|
||||
var before = info.before ?? new string[0];
|
||||
var after = info.after ?? new string[0];
|
||||
|
||||
patchInfo.AddPostfix(info.method, owner, priority, before, after);
|
||||
}
|
||||
|
||||
public static void RemovePostfix(PatchInfo patchInfo, string owner)
|
||||
{
|
||||
patchInfo.RemovePostfix(owner);
|
||||
}
|
||||
|
||||
public static void AddTranspiler(PatchInfo patchInfo, string owner, HarmonyMethod info)
|
||||
{
|
||||
if (info == null || info.method == null) return;
|
||||
|
||||
var priority = info.prioritiy == -1 ? Priority.Normal : info.prioritiy;
|
||||
var before = info.before ?? new string[0];
|
||||
var after = info.after ?? new string[0];
|
||||
|
||||
patchInfo.AddTranspiler(info.method, owner, priority, before, after);
|
||||
}
|
||||
|
||||
public static void RemoveTranspiler(PatchInfo patchInfo, string owner)
|
||||
{
|
||||
patchInfo.RemoveTranspiler(owner);
|
||||
}
|
||||
|
||||
public static void RemovePatch(PatchInfo patchInfo, MethodInfo patch)
|
||||
{
|
||||
patchInfo.RemovePatch(patch);
|
||||
}
|
||||
|
||||
// pass in a generator that will create local variables for the returned instructions
|
||||
//
|
||||
public static List<ILInstruction> GetInstructions(ILGenerator generator, MethodBase method)
|
||||
{
|
||||
return MethodBodyReader.GetInstructions(generator, method);
|
||||
}
|
||||
|
||||
public static List<MethodInfo> GetSortedPatchMethods(MethodBase original, Patch[] patches)
|
||||
{
|
||||
return patches
|
||||
.Where(p => p.patch != null)
|
||||
.OrderBy(p => p)
|
||||
.Select(p => p.GetMethod(original))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
|
||||
{
|
||||
var sortedPrefixes = GetSortedPatchMethods(original, patchInfo.prefixes);
|
||||
var sortedPostfixes = GetSortedPatchMethods(original, patchInfo.postfixes);
|
||||
var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);
|
||||
|
||||
var replacement = MethodPatcher.CreatePatchedMethod(original, instanceID, sortedPrefixes, sortedPostfixes, sortedTranspilers);
|
||||
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);
|
||||
|
||||
PatchTools.RememberObject(original, replacement); // no gc for new value + release old value to gc
|
||||
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class PatchProcessor
|
||||
{
|
||||
static object locker = new object();
|
||||
|
||||
readonly HarmonyInstance instance;
|
||||
|
||||
readonly Type container;
|
||||
readonly HarmonyMethod containerAttributes;
|
||||
|
||||
List<MethodBase> originals = new List<MethodBase>();
|
||||
HarmonyMethod prefix;
|
||||
HarmonyMethod postfix;
|
||||
HarmonyMethod transpiler;
|
||||
|
||||
public PatchProcessor(HarmonyInstance instance, Type type, HarmonyMethod attributes)
|
||||
{
|
||||
this.instance = instance;
|
||||
container = type;
|
||||
containerAttributes = attributes ?? new HarmonyMethod(null);
|
||||
prefix = containerAttributes.Clone();
|
||||
postfix = containerAttributes.Clone();
|
||||
transpiler = containerAttributes.Clone();
|
||||
PrepareType();
|
||||
}
|
||||
|
||||
public PatchProcessor(HarmonyInstance instance, List<MethodBase> originals, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.originals = originals;
|
||||
this.prefix = prefix ?? new HarmonyMethod(null);
|
||||
this.postfix = postfix ?? new HarmonyMethod(null);
|
||||
this.transpiler = transpiler ?? new HarmonyMethod(null);
|
||||
}
|
||||
|
||||
public static Patches GetPatchInfo(MethodBase method)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
var patchInfo = HarmonySharedState.GetPatchInfo(method);
|
||||
if (patchInfo == null) return null;
|
||||
return new Patches(patchInfo.prefixes, patchInfo.postfixes, patchInfo.transpilers);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodBase> AllPatchedMethods()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return HarmonySharedState.GetPatchedMethods();
|
||||
}
|
||||
}
|
||||
|
||||
public List<DynamicMethod> Patch()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
var dynamicMethods = new List<DynamicMethod>();
|
||||
foreach (var original in originals)
|
||||
{
|
||||
if (original == null)
|
||||
throw new NullReferenceException("original");
|
||||
|
||||
var individualPrepareResult = RunMethod<HarmonyPrepare, bool>(true, original);
|
||||
if (individualPrepareResult)
|
||||
{
|
||||
var patchInfo = HarmonySharedState.GetPatchInfo(original);
|
||||
if (patchInfo == null) patchInfo = new PatchInfo();
|
||||
|
||||
PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix);
|
||||
PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix);
|
||||
PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler);
|
||||
dynamicMethods.Add(PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id));
|
||||
|
||||
HarmonySharedState.UpdatePatchInfo(original, patchInfo);
|
||||
|
||||
RunMethod<HarmonyCleanup>(original);
|
||||
}
|
||||
}
|
||||
return dynamicMethods;
|
||||
}
|
||||
}
|
||||
|
||||
public void Unpatch(HarmonyPatchType type, string harmonyID)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
foreach (var original in originals)
|
||||
{
|
||||
var patchInfo = HarmonySharedState.GetPatchInfo(original);
|
||||
if (patchInfo == null) patchInfo = new PatchInfo();
|
||||
|
||||
if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix)
|
||||
PatchFunctions.RemovePrefix(patchInfo, harmonyID);
|
||||
if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix)
|
||||
PatchFunctions.RemovePostfix(patchInfo, harmonyID);
|
||||
if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler)
|
||||
PatchFunctions.RemoveTranspiler(patchInfo, harmonyID);
|
||||
PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id);
|
||||
|
||||
HarmonySharedState.UpdatePatchInfo(original, patchInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unpatch(MethodInfo patch)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
foreach (var original in originals)
|
||||
{
|
||||
var patchInfo = HarmonySharedState.GetPatchInfo(original);
|
||||
if (patchInfo == null) patchInfo = new PatchInfo();
|
||||
|
||||
PatchFunctions.RemovePatch(patchInfo, patch);
|
||||
PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id);
|
||||
|
||||
HarmonySharedState.UpdatePatchInfo(original, patchInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrepareType()
|
||||
{
|
||||
var mainPrepareResult = RunMethod<HarmonyPrepare, bool>(true);
|
||||
if (mainPrepareResult == false)
|
||||
return;
|
||||
|
||||
var customOriginals = RunMethod<HarmonyTargetMethods, IEnumerable<MethodBase>>(null);
|
||||
if (customOriginals != null)
|
||||
{
|
||||
originals = customOriginals.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
var originalMethodType = containerAttributes.methodType;
|
||||
|
||||
// MethodType default is Normal
|
||||
if (containerAttributes.methodType == null)
|
||||
containerAttributes.methodType = MethodType.Normal;
|
||||
|
||||
var isPatchAll = Attribute.GetCustomAttribute(container, typeof(HarmonyPatchAll)) != null;
|
||||
if (isPatchAll)
|
||||
{
|
||||
var type = containerAttributes.declaringType;
|
||||
originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast<MethodBase>());
|
||||
originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast<MethodBase>());
|
||||
}
|
||||
else
|
||||
{
|
||||
var original = RunMethod<HarmonyTargetMethod, MethodBase>(null);
|
||||
|
||||
if (original == null)
|
||||
original = GetOriginalMethod();
|
||||
|
||||
if (original == null)
|
||||
{
|
||||
var info = "(";
|
||||
info += "declaringType=" + containerAttributes.declaringType + ", ";
|
||||
info += "methodName =" + containerAttributes.methodName + ", ";
|
||||
info += "methodType=" + originalMethodType + ", ";
|
||||
info += "argumentTypes=" + containerAttributes.argumentTypes.Description();
|
||||
info += ")";
|
||||
throw new ArgumentException("No target method specified for class " + container.FullName + " " + info);
|
||||
}
|
||||
|
||||
originals.Add(original);
|
||||
}
|
||||
}
|
||||
|
||||
PatchTools.GetPatches(container, out prefix.method, out postfix.method, out transpiler.method);
|
||||
|
||||
if (prefix.method != null)
|
||||
{
|
||||
if (prefix.method.IsStatic == false)
|
||||
throw new ArgumentException("Patch method " + prefix.method.FullDescription() + " must be static");
|
||||
|
||||
var prefixAttributes = prefix.method.GetHarmonyMethods();
|
||||
containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix);
|
||||
}
|
||||
|
||||
if (postfix.method != null)
|
||||
{
|
||||
if (postfix.method.IsStatic == false)
|
||||
throw new ArgumentException("Patch method " + postfix.method.FullDescription() + " must be static");
|
||||
|
||||
var postfixAttributes = postfix.method.GetHarmonyMethods();
|
||||
containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix);
|
||||
}
|
||||
|
||||
if (transpiler.method != null)
|
||||
{
|
||||
if (transpiler.method.IsStatic == false)
|
||||
throw new ArgumentException("Patch method " + transpiler.method.FullDescription() + " must be static");
|
||||
|
||||
var infixAttributes = transpiler.method.GetHarmonyMethods();
|
||||
containerAttributes.Merge(HarmonyMethod.Merge(infixAttributes)).CopyTo(transpiler);
|
||||
}
|
||||
}
|
||||
|
||||
MethodBase GetOriginalMethod()
|
||||
{
|
||||
var attr = containerAttributes;
|
||||
if (attr.declaringType == null) return null;
|
||||
|
||||
switch (attr.methodType)
|
||||
{
|
||||
case MethodType.Normal:
|
||||
if (attr.methodName == null)
|
||||
return null;
|
||||
return AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes);
|
||||
|
||||
case MethodType.Getter:
|
||||
if (attr.methodName == null)
|
||||
return null;
|
||||
return AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetGetMethod(true);
|
||||
|
||||
case MethodType.Setter:
|
||||
if (attr.methodName == null)
|
||||
return null;
|
||||
return AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetSetMethod(true);
|
||||
|
||||
case MethodType.Constructor:
|
||||
return AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes);
|
||||
|
||||
case MethodType.StaticConstructor:
|
||||
return AccessTools.GetDeclaredConstructors(attr.declaringType)
|
||||
.Where(c => c.IsStatic)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
T RunMethod<S, T>(T defaultIfNotExisting, params object[] parameters)
|
||||
{
|
||||
if (container == null)
|
||||
return defaultIfNotExisting;
|
||||
|
||||
var methodName = typeof(S).Name.Replace("Harmony", "");
|
||||
|
||||
var paramList = new List<object> { instance };
|
||||
paramList.AddRange(parameters);
|
||||
var paramTypes = AccessTools.GetTypes(paramList.ToArray());
|
||||
var method = PatchTools.GetPatchMethod<S>(container, methodName, paramTypes);
|
||||
if (method != null && typeof(T).IsAssignableFrom(method.ReturnType))
|
||||
return (T)method.Invoke(null, paramList.ToArray());
|
||||
|
||||
method = PatchTools.GetPatchMethod<S>(container, methodName, new Type[] { typeof(HarmonyInstance) });
|
||||
if (method != null && typeof(T).IsAssignableFrom(method.ReturnType))
|
||||
return (T)method.Invoke(null, new object[] { instance });
|
||||
|
||||
method = PatchTools.GetPatchMethod<S>(container, methodName, Type.EmptyTypes);
|
||||
if (method != null)
|
||||
{
|
||||
if (typeof(T).IsAssignableFrom(method.ReturnType))
|
||||
return (T)method.Invoke(null, Type.EmptyTypes);
|
||||
|
||||
method.Invoke(null, Type.EmptyTypes);
|
||||
return defaultIfNotExisting;
|
||||
}
|
||||
|
||||
return defaultIfNotExisting;
|
||||
}
|
||||
|
||||
void RunMethod<S>(params object[] parameters)
|
||||
{
|
||||
if (container == null)
|
||||
return;
|
||||
|
||||
var methodName = typeof(S).Name.Replace("Harmony", "");
|
||||
|
||||
var paramList = new List<object> { instance };
|
||||
paramList.AddRange(parameters);
|
||||
var paramTypes = AccessTools.GetTypes(paramList.ToArray());
|
||||
var method = PatchTools.GetPatchMethod<S>(container, methodName, paramTypes);
|
||||
if (method != null)
|
||||
{
|
||||
method.Invoke(null, paramList.ToArray());
|
||||
return;
|
||||
}
|
||||
|
||||
method = PatchTools.GetPatchMethod<S>(container, methodName, new Type[] { typeof(HarmonyInstance) });
|
||||
if (method != null)
|
||||
{
|
||||
method.Invoke(null, new object[] { instance });
|
||||
return;
|
||||
}
|
||||
|
||||
method = PatchTools.GetPatchMethod<S>(container, methodName, Type.EmptyTypes);
|
||||
if (method != null)
|
||||
{
|
||||
method.Invoke(null, Type.EmptyTypes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
namespace Harmony
|
||||
{
|
||||
public static class Priority
|
||||
{
|
||||
public const int Last = 0;
|
||||
public const int VeryLow = 100;
|
||||
public const int Low = 200;
|
||||
public const int LowerThanNormal = 300;
|
||||
public const int Normal = 400;
|
||||
public const int HigherThanNormal = 500;
|
||||
public const int High = 600;
|
||||
public const int VeryHigh = 700;
|
||||
public const int First = 800;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class AccessCache
|
||||
{
|
||||
Dictionary<Type, Dictionary<string, FieldInfo>> fields = new Dictionary<Type, Dictionary<string, FieldInfo>>();
|
||||
Dictionary<Type, Dictionary<string, PropertyInfo>> properties = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
|
||||
readonly Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>> methods = new Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>>();
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
public FieldInfo GetFieldInfo(Type type, string name)
|
||||
{
|
||||
Dictionary<string, FieldInfo> fieldsByType = null;
|
||||
if (fields.TryGetValue(type, out fieldsByType) == false)
|
||||
{
|
||||
fieldsByType = new Dictionary<string, FieldInfo>();
|
||||
fields.Add(type, fieldsByType);
|
||||
}
|
||||
|
||||
FieldInfo field = null;
|
||||
if (fieldsByType.TryGetValue(name, out field) == false)
|
||||
{
|
||||
field = AccessTools.Field(type, name);
|
||||
fieldsByType.Add(name, field);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
public PropertyInfo GetPropertyInfo(Type type, string name)
|
||||
{
|
||||
Dictionary<string, PropertyInfo> propertiesByType = null;
|
||||
if (properties.TryGetValue(type, out propertiesByType) == false)
|
||||
{
|
||||
propertiesByType = new Dictionary<string, PropertyInfo>();
|
||||
properties.Add(type, propertiesByType);
|
||||
}
|
||||
|
||||
PropertyInfo property = null;
|
||||
if (propertiesByType.TryGetValue(name, out property) == false)
|
||||
{
|
||||
property = AccessTools.Property(type, name);
|
||||
propertiesByType.Add(name, property);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
static int CombinedHashCode(IEnumerable<object> objects)
|
||||
{
|
||||
var hash1 = (5381 << 16) + 5381;
|
||||
var hash2 = hash1;
|
||||
var i = 0;
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ obj.GetHashCode();
|
||||
else
|
||||
hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ obj.GetHashCode();
|
||||
++i;
|
||||
}
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
|
||||
public MethodBase GetMethodInfo(Type type, string name, Type[] arguments)
|
||||
{
|
||||
Dictionary<string, Dictionary<int, MethodBase>> methodsByName = null;
|
||||
methods.TryGetValue(type, out methodsByName);
|
||||
if (methodsByName == null)
|
||||
{
|
||||
methodsByName = new Dictionary<string, Dictionary<int, MethodBase>>();
|
||||
methods.Add(type, methodsByName);
|
||||
}
|
||||
|
||||
Dictionary<int, MethodBase> methodsByArguments = null;
|
||||
methodsByName.TryGetValue(name, out methodsByArguments);
|
||||
if (methodsByArguments == null)
|
||||
{
|
||||
methodsByArguments = new Dictionary<int, MethodBase>();
|
||||
methodsByName.Add(name, methodsByArguments);
|
||||
}
|
||||
|
||||
MethodBase method = null;
|
||||
var argumentsHash = CombinedHashCode(arguments);
|
||||
methodsByArguments.TryGetValue(argumentsHash, out method);
|
||||
if (method == null)
|
||||
{
|
||||
method = AccessTools.Method(type, name, arguments);
|
||||
methodsByArguments.Add(argumentsHash, method);
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,398 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class AccessTools
|
||||
{
|
||||
public static BindingFlags all = BindingFlags.Public
|
||||
| BindingFlags.NonPublic
|
||||
| BindingFlags.Instance
|
||||
| BindingFlags.Static
|
||||
| BindingFlags.GetField
|
||||
| BindingFlags.SetField
|
||||
| BindingFlags.GetProperty
|
||||
| BindingFlags.SetProperty;
|
||||
|
||||
public static Type TypeByName(string name)
|
||||
{
|
||||
var type = Type.GetType(name, false);
|
||||
if (type == null)
|
||||
type = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(x => x.GetTypes())
|
||||
.FirstOrDefault(x => x.FullName == name);
|
||||
if (type == null)
|
||||
type = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(x => x.GetTypes())
|
||||
.FirstOrDefault(x => x.Name == name);
|
||||
return type;
|
||||
}
|
||||
|
||||
public static T FindIncludingBaseTypes<T>(Type type, Func<Type, T> action)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var result = action(type);
|
||||
if (result != null) return result;
|
||||
if (type == typeof(object)) return default(T);
|
||||
type = type.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static T FindIncludingInnerTypes<T>(Type type, Func<Type, T> action)
|
||||
{
|
||||
var result = action(type);
|
||||
if (result != null) return result;
|
||||
foreach (var subType in type.GetNestedTypes(all))
|
||||
{
|
||||
result = FindIncludingInnerTypes(subType, action);
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FieldInfo Field(Type type, string name)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
return FindIncludingBaseTypes(type, t => t.GetField(name, all));
|
||||
}
|
||||
|
||||
public static FieldInfo Field(Type type, int idx)
|
||||
{
|
||||
return GetDeclaredFields(type).ElementAtOrDefault(idx);
|
||||
}
|
||||
|
||||
public static PropertyInfo DeclaredProperty(Type type, string name)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
return type.GetProperty(name, all);
|
||||
}
|
||||
|
||||
public static PropertyInfo Property(Type type, string name)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
return FindIncludingBaseTypes(type, t => t.GetProperty(name, all));
|
||||
}
|
||||
|
||||
public static MethodInfo DeclaredMethod(Type type, string name, Type[] parameters = null, Type[] generics = null)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
MethodInfo result;
|
||||
var modifiers = new ParameterModifier[] { };
|
||||
|
||||
if (parameters == null)
|
||||
result = type.GetMethod(name, all);
|
||||
else
|
||||
result = type.GetMethod(name, all, null, parameters, modifiers);
|
||||
|
||||
if (result == null) return null;
|
||||
if (generics != null) result = result.MakeGenericMethod(generics);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static MethodInfo Method(Type type, string name, Type[] parameters = null, Type[] generics = null)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
MethodInfo result;
|
||||
var modifiers = new ParameterModifier[] { };
|
||||
if (parameters == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all));
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all, null, new Type[0], modifiers));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all, null, parameters, modifiers));
|
||||
}
|
||||
if (result == null) return null;
|
||||
if (generics != null) result = result.MakeGenericMethod(generics);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static MethodInfo Method(string typeColonMethodname, Type[] parameters = null, Type[] generics = null)
|
||||
{
|
||||
if (typeColonMethodname == null) return null;
|
||||
var parts = typeColonMethodname.Split(':');
|
||||
if (parts.Length != 2)
|
||||
throw new ArgumentException("Method must be specified as 'Namespace.Type1.Type2:MethodName", nameof(typeColonMethodname));
|
||||
|
||||
var type = TypeByName(parts[0]);
|
||||
return Method(type, parts[1], parameters, generics);
|
||||
}
|
||||
|
||||
public static List<string> GetMethodNames(Type type)
|
||||
{
|
||||
if (type == null) return new List<string>();
|
||||
return type.GetMethods(all).Select(m => m.Name).ToList();
|
||||
}
|
||||
|
||||
public static List<string> GetMethodNames(object instance)
|
||||
{
|
||||
if (instance == null) return new List<string>();
|
||||
return GetMethodNames(instance.GetType());
|
||||
}
|
||||
|
||||
public static ConstructorInfo DeclaredConstructor(Type type, Type[] parameters = null)
|
||||
{
|
||||
if (type == null) return null;
|
||||
if (parameters == null) parameters = new Type[0];
|
||||
return type.GetConstructor(all, null, parameters, new ParameterModifier[] { });
|
||||
}
|
||||
|
||||
public static ConstructorInfo Constructor(Type type, Type[] parameters = null)
|
||||
{
|
||||
if (type == null) return null;
|
||||
if (parameters == null) parameters = new Type[0];
|
||||
return FindIncludingBaseTypes(type, t => t.GetConstructor(all, null, parameters, new ParameterModifier[] { }));
|
||||
}
|
||||
|
||||
public static List<ConstructorInfo> GetDeclaredConstructors(Type type)
|
||||
{
|
||||
return type.GetConstructors(all).Where(method => method.DeclaringType == type).ToList();
|
||||
}
|
||||
|
||||
public static List<MethodInfo> GetDeclaredMethods(Type type)
|
||||
{
|
||||
return type.GetMethods(all).Where(method => method.DeclaringType == type).ToList();
|
||||
}
|
||||
|
||||
public static List<PropertyInfo> GetDeclaredProperties(Type type)
|
||||
{
|
||||
return type.GetProperties(all).Where(property => property.DeclaringType == type).ToList();
|
||||
}
|
||||
|
||||
public static List<FieldInfo> GetDeclaredFields(Type type)
|
||||
{
|
||||
return type.GetFields(all).Where(field => field.DeclaringType == type).ToList();
|
||||
}
|
||||
|
||||
public static Type GetReturnedType(MethodBase method)
|
||||
{
|
||||
var constructor = method as ConstructorInfo;
|
||||
if (constructor != null) return typeof(void);
|
||||
return ((MethodInfo)method).ReturnType;
|
||||
}
|
||||
|
||||
public static Type Inner(Type type, string name)
|
||||
{
|
||||
if (type == null || name == null) return null;
|
||||
return FindIncludingBaseTypes(type, t => t.GetNestedType(name, all));
|
||||
}
|
||||
|
||||
public static Type FirstInner(Type type, Func<Type, bool> predicate)
|
||||
{
|
||||
if (type == null || predicate == null) return null;
|
||||
return type.GetNestedTypes(all).FirstOrDefault(subType => predicate(subType));
|
||||
}
|
||||
|
||||
public static MethodInfo FirstMethod(Type type, Func<MethodInfo, bool> predicate)
|
||||
{
|
||||
if (type == null || predicate == null) return null;
|
||||
return type.GetMethods(all).FirstOrDefault(method => predicate(method));
|
||||
}
|
||||
|
||||
public static ConstructorInfo FirstConstructor(Type type, Func<ConstructorInfo, bool> predicate)
|
||||
{
|
||||
if (type == null || predicate == null) return null;
|
||||
return type.GetConstructors(all).FirstOrDefault(constructor => predicate(constructor));
|
||||
}
|
||||
|
||||
public static PropertyInfo FirstProperty(Type type, Func<PropertyInfo, bool> predicate)
|
||||
{
|
||||
if (type == null || predicate == null) return null;
|
||||
return type.GetProperties(all).FirstOrDefault(property => predicate(property));
|
||||
}
|
||||
|
||||
public static Type[] GetTypes(object[] parameters)
|
||||
{
|
||||
if (parameters == null) return new Type[0];
|
||||
return parameters.Select(p => p == null ? typeof(object) : p.GetType()).ToArray();
|
||||
}
|
||||
|
||||
public static List<string> GetFieldNames(Type type)
|
||||
{
|
||||
if (type == null) return new List<string>();
|
||||
return type.GetFields(all).Select(f => f.Name).ToList();
|
||||
}
|
||||
|
||||
public static List<string> GetFieldNames(object instance)
|
||||
{
|
||||
if (instance == null) return new List<string>();
|
||||
return GetFieldNames(instance.GetType());
|
||||
}
|
||||
|
||||
public static List<string> GetPropertyNames(Type type)
|
||||
{
|
||||
if (type == null) return new List<string>();
|
||||
return type.GetProperties(all).Select(f => f.Name).ToList();
|
||||
}
|
||||
|
||||
public static List<string> GetPropertyNames(object instance)
|
||||
{
|
||||
if (instance == null) return new List<string>();
|
||||
return GetPropertyNames(instance.GetType());
|
||||
}
|
||||
|
||||
public delegate ref U FieldRef<T, U>(T obj);
|
||||
public static FieldRef<T, U> FieldRefAccess<T, U>(string fieldName)
|
||||
{
|
||||
const BindingFlags bf = BindingFlags.NonPublic |
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.DeclaredOnly;
|
||||
|
||||
var fi = typeof(T).GetField(fieldName, bf);
|
||||
if (fi == null)
|
||||
throw new MissingFieldException(typeof(T).Name, fieldName);
|
||||
|
||||
var s_name = "__refget_" + typeof(T).Name + "_fi_" + fi.Name;
|
||||
|
||||
// workaround for using ref-return with DynamicMethod:
|
||||
// a.) initialize with dummy return value
|
||||
var dm = new DynamicMethod(s_name, typeof(U), new[] { typeof(T) }, typeof(T), true);
|
||||
|
||||
// b.) replace with desired 'ByRef' return value
|
||||
var trv = Traverse.Create(dm);
|
||||
trv.Field("returnType").SetValue(typeof(U).MakeByRefType());
|
||||
trv.Field("m_returnType").SetValue(typeof(U).MakeByRefType());
|
||||
|
||||
var il = dm.GetILGenerator();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldflda, fi);
|
||||
il.Emit(OpCodes.Ret);
|
||||
return (FieldRef<T, U>)dm.CreateDelegate(typeof(FieldRef<T, U>));
|
||||
}
|
||||
|
||||
public static ref U FieldRefAccess<T, U>(T instance, string fieldName)
|
||||
{
|
||||
return ref FieldRefAccess<T, U>(fieldName)(instance);
|
||||
}
|
||||
|
||||
public static void ThrowMissingMemberException(Type type, params string[] names)
|
||||
{
|
||||
var fields = string.Join(",", GetFieldNames(type).ToArray());
|
||||
var properties = string.Join(",", GetPropertyNames(type).ToArray());
|
||||
throw new MissingMemberException(string.Join(",", names) + "; available fields: " + fields + "; available properties: " + properties);
|
||||
}
|
||||
|
||||
public static object GetDefaultValue(Type type)
|
||||
{
|
||||
if (type == null) return null;
|
||||
if (type == typeof(void)) return null;
|
||||
if (type.IsValueType)
|
||||
return Activator.CreateInstance(type);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static object CreateInstance(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new NullReferenceException("Cannot create instance for NULL type");
|
||||
var ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[0], null);
|
||||
if (ctor != null)
|
||||
return Activator.CreateInstance(type);
|
||||
return FormatterServices.GetUninitializedObject(type);
|
||||
}
|
||||
|
||||
public static object MakeDeepCopy(object source, Type resultType, Func<string, Traverse, Traverse, object> processor = null, string pathRoot = "")
|
||||
{
|
||||
if (source == null)
|
||||
return null;
|
||||
|
||||
var type = source.GetType();
|
||||
|
||||
if (type.IsPrimitive)
|
||||
return source;
|
||||
|
||||
if (type.IsEnum)
|
||||
return Enum.ToObject(resultType, (int)source);
|
||||
|
||||
if (type.IsGenericType && resultType.IsGenericType)
|
||||
{
|
||||
var addOperation = FirstMethod(resultType, m => m.Name == "Add" && m.GetParameters().Count() == 1);
|
||||
if (addOperation != null)
|
||||
{
|
||||
var addableResult = Activator.CreateInstance(resultType);
|
||||
var addInvoker = MethodInvoker.GetHandler(addOperation);
|
||||
var newElementType = resultType.GetGenericArguments()[0];
|
||||
var i = 0;
|
||||
foreach (var element in source as IEnumerable)
|
||||
{
|
||||
var iStr = (i++).ToString();
|
||||
var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr;
|
||||
var newElement = MakeDeepCopy(element, newElementType, processor, path);
|
||||
addInvoker(addableResult, new object[] { newElement });
|
||||
}
|
||||
return addableResult;
|
||||
}
|
||||
|
||||
// TODO: add dictionaries support
|
||||
// maybe use methods in Dictionary<KeyValuePair<TKey,TVal>>
|
||||
}
|
||||
|
||||
if (type.IsArray && resultType.IsArray)
|
||||
{
|
||||
var elementType = resultType.GetElementType();
|
||||
var length = ((Array)source).Length;
|
||||
var arrayResult = Activator.CreateInstance(resultType, new object[] { length }) as object[];
|
||||
var originalArray = source as object[];
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var iStr = i.ToString();
|
||||
var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr;
|
||||
arrayResult[i] = MakeDeepCopy(originalArray[i], elementType, processor, path);
|
||||
}
|
||||
return arrayResult;
|
||||
}
|
||||
|
||||
var ns = type.Namespace;
|
||||
if (ns == "System" || (ns?.StartsWith("System.") ?? false))
|
||||
return source;
|
||||
|
||||
var result = CreateInstance(resultType);
|
||||
Traverse.IterateFields(source, result, (name, src, dst) =>
|
||||
{
|
||||
var path = pathRoot.Length > 0 ? pathRoot + "." + name : name;
|
||||
var value = processor != null ? processor(path, src, dst) : src.GetValue();
|
||||
dst.SetValue(MakeDeepCopy(value, dst.GetValueType(), processor, path));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void MakeDeepCopy<T>(object source, out T result, Func<string, Traverse, Traverse, object> processor = null, string pathRoot = "")
|
||||
{
|
||||
result = (T)MakeDeepCopy(source, typeof(T), processor, pathRoot);
|
||||
}
|
||||
|
||||
public static bool IsStruct(Type type)
|
||||
{
|
||||
return type.IsValueType && !IsValue(type) && !IsVoid(type);
|
||||
}
|
||||
|
||||
public static bool IsClass(Type type)
|
||||
{
|
||||
return !type.IsValueType;
|
||||
}
|
||||
|
||||
public static bool IsValue(Type type)
|
||||
{
|
||||
return type.IsPrimitive || type.IsEnum;
|
||||
}
|
||||
|
||||
public static bool IsVoid(Type type)
|
||||
{
|
||||
return type == typeof(void);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
using Harmony.ILCopying;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class DynamicTools
|
||||
{
|
||||
/* TODO add support for functions that return structs larger than 8 bytes
|
||||
*
|
||||
* https://github.com/dotnet/coreclr/issues/12503
|
||||
* https://stackoverflow.com/questions/44641195/what-could-cause-p-invoke-arguments-to-be-out-of-order-when-passed
|
||||
*
|
||||
* ERROR
|
||||
* Managed Debugging Assistant 'FatalExecutionEngineError'
|
||||
* The runtime has encountered a fatal error. The address of the error was at 0x72747d0e, on thread 0x9c38. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
|
||||
*
|
||||
* Calling signatures change:
|
||||
* .NET <4.5 jits to void Func(ref LargeReturnStruct, object this, params)
|
||||
* .NET 4.5+ jits to Func(object this, ref LargeReturnStruct, params)
|
||||
*
|
||||
* // Test case
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct Struct1
|
||||
{
|
||||
public double foo;
|
||||
public double bar;
|
||||
}
|
||||
|
||||
public class StructTest1
|
||||
{
|
||||
public Struct1 PatchMe()
|
||||
{
|
||||
return default(Struct1);
|
||||
}
|
||||
}
|
||||
*
|
||||
*/
|
||||
public static DynamicMethod CreateDynamicMethod(MethodBase original, string suffix)
|
||||
{
|
||||
if (original == null) throw new ArgumentNullException("original cannot be null");
|
||||
var patchName = original.Name + suffix;
|
||||
patchName = patchName.Replace("<>", "");
|
||||
|
||||
var parameters = original.GetParameters();
|
||||
var result = parameters.Types().ToList();
|
||||
if (original.IsStatic == false)
|
||||
result.Insert(0, typeof(object));
|
||||
var paramTypes = result.ToArray();
|
||||
var returnType = AccessTools.GetReturnedType(original);
|
||||
|
||||
// DynamicMethod does not support byref return types
|
||||
if (returnType == null || returnType.IsByRef)
|
||||
return null;
|
||||
|
||||
DynamicMethod method;
|
||||
try
|
||||
{
|
||||
method = new DynamicMethod(
|
||||
patchName,
|
||||
MethodAttributes.Public | MethodAttributes.Static,
|
||||
CallingConventions.Standard,
|
||||
returnType,
|
||||
paramTypes,
|
||||
original.DeclaringType,
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
public static ILGenerator CreateSaveableMethod(MethodBase original, string suffix, out AssemblyBuilder assemblyBuilder, out TypeBuilder typeBuilder)
|
||||
{
|
||||
var assemblyName = new AssemblyName("DebugAssembly");
|
||||
var path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, path);
|
||||
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
|
||||
typeBuilder = moduleBuilder.DefineType("Debug" + original.DeclaringType.Name, TypeAttributes.Public);
|
||||
|
||||
if (original == null) throw new ArgumentNullException("original cannot be null");
|
||||
var patchName = original.Name + suffix;
|
||||
patchName = patchName.Replace("<>", "");
|
||||
|
||||
var parameters = original.GetParameters();
|
||||
var result = parameters.Types().ToList();
|
||||
if (original.IsStatic == false)
|
||||
result.Insert(0, typeof(object));
|
||||
var paramTypes = result.ToArray();
|
||||
|
||||
var methodBuilder = typeBuilder.DefineMethod(
|
||||
patchName,
|
||||
MethodAttributes.Public | MethodAttributes.Static,
|
||||
CallingConventions.Standard,
|
||||
AccessTools.GetReturnedType(original),
|
||||
paramTypes
|
||||
);
|
||||
|
||||
return methodBuilder.GetILGenerator();
|
||||
}
|
||||
|
||||
public static void SaveMethod(AssemblyBuilder assemblyBuilder, TypeBuilder typeBuilder)
|
||||
{
|
||||
var t = typeBuilder.CreateType();
|
||||
assemblyBuilder.Save("HarmonyDebugAssembly.dll");
|
||||
}
|
||||
|
||||
public static LocalBuilder[] DeclareLocalVariables(MethodBase original, ILGenerator il, bool logOutput = true)
|
||||
{
|
||||
var vars = original.GetMethodBody()?.LocalVariables;
|
||||
if (vars == null)
|
||||
return new LocalBuilder[0];
|
||||
return vars.Select(lvi =>
|
||||
{
|
||||
var localBuilder = il.DeclareLocal(lvi.LocalType, lvi.IsPinned);
|
||||
if (logOutput)
|
||||
Emitter.LogLocalVariable(il, localBuilder);
|
||||
return localBuilder;
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
public static LocalBuilder DeclareLocalVariable(ILGenerator il, Type type)
|
||||
{
|
||||
if (type.IsByRef) type = type.GetElementType();
|
||||
|
||||
if (AccessTools.IsClass(type))
|
||||
{
|
||||
var v = il.DeclareLocal(type);
|
||||
Emitter.LogLocalVariable(il, v);
|
||||
Emitter.Emit(il, OpCodes.Ldnull);
|
||||
Emitter.Emit(il, OpCodes.Stloc, v);
|
||||
return v;
|
||||
}
|
||||
if (AccessTools.IsStruct(type))
|
||||
{
|
||||
var v = il.DeclareLocal(type);
|
||||
Emitter.LogLocalVariable(il, v);
|
||||
Emitter.Emit(il, OpCodes.Ldloca, v);
|
||||
Emitter.Emit(il, OpCodes.Initobj, type);
|
||||
return v;
|
||||
}
|
||||
if (AccessTools.IsValue(type))
|
||||
{
|
||||
var v = il.DeclareLocal(type);
|
||||
Emitter.LogLocalVariable(il, v);
|
||||
if (type == typeof(float))
|
||||
Emitter.Emit(il, OpCodes.Ldc_R4, (float)0);
|
||||
else if (type == typeof(double))
|
||||
Emitter.Emit(il, OpCodes.Ldc_R8, (double)0);
|
||||
else if (type == typeof(long))
|
||||
Emitter.Emit(il, OpCodes.Ldc_I8, (long)0);
|
||||
else
|
||||
Emitter.Emit(il, OpCodes.Ldc_I4, 0);
|
||||
Emitter.Emit(il, OpCodes.Stloc, v);
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void PrepareDynamicMethod(DynamicMethod method)
|
||||
{
|
||||
var nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
var nonPublicStatic = BindingFlags.NonPublic | BindingFlags.Static;
|
||||
|
||||
// on mono, just call 'CreateDynMethod'
|
||||
//
|
||||
var m_CreateDynMethod = typeof(DynamicMethod).GetMethod("CreateDynMethod", nonPublicInstance);
|
||||
if (m_CreateDynMethod != null)
|
||||
{
|
||||
m_CreateDynMethod.Invoke(method, new object[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// on all .NET Core versions, call 'RuntimeHelpers._CompileMethod' but with a different parameter:
|
||||
//
|
||||
var m__CompileMethod = typeof(RuntimeHelpers).GetMethod("_CompileMethod", nonPublicStatic);
|
||||
|
||||
var m_GetMethodDescriptor = typeof(DynamicMethod).GetMethod("GetMethodDescriptor", nonPublicInstance);
|
||||
var handle = (RuntimeMethodHandle)m_GetMethodDescriptor.Invoke(method, new object[0]);
|
||||
|
||||
// 1) RuntimeHelpers._CompileMethod(handle.GetMethodInfo())
|
||||
//
|
||||
var m_GetMethodInfo = typeof(RuntimeMethodHandle).GetMethod("GetMethodInfo", nonPublicInstance);
|
||||
if (m_GetMethodInfo != null)
|
||||
{
|
||||
var runtimeMethodInfo = m_GetMethodInfo.Invoke(handle, new object[0]);
|
||||
try
|
||||
{
|
||||
// this can throw BadImageFormatException "An attempt was made to load a program with an incorrect format"
|
||||
m__CompileMethod.Invoke(null, new object[] { runtimeMethodInfo });
|
||||
return;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// 2) RuntimeHelpers._CompileMethod(handle.Value)
|
||||
//
|
||||
if (m__CompileMethod.GetParameters()[0].ParameterType.IsAssignableFrom(handle.Value.GetType()))
|
||||
{
|
||||
m__CompileMethod.Invoke(null, new object[] { handle.Value });
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) RuntimeHelpers._CompileMethod(handle)
|
||||
//
|
||||
if (m__CompileMethod.GetParameters()[0].ParameterType.IsAssignableFrom(handle.GetType()))
|
||||
{
|
||||
m__CompileMethod.Invoke(null, new object[] { handle });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class GeneralExtensions
|
||||
{
|
||||
public static string Join<T>(this IEnumerable<T> enumeration, Func<T, string> converter = null, string delimiter = ", ")
|
||||
{
|
||||
if (converter == null) converter = t => t.ToString();
|
||||
return enumeration.Aggregate("", (prev, curr) => prev + (prev != "" ? delimiter : "") + converter(curr));
|
||||
}
|
||||
|
||||
public static string Description(this Type[] parameters)
|
||||
{
|
||||
if (parameters == null) return "NULL";
|
||||
var pattern = @", \w+, Version=[0-9.]+, Culture=neutral, PublicKeyToken=[0-9a-f]+";
|
||||
return "(" + parameters.Join(p => p?.FullName == null ? "null" : Regex.Replace(p.FullName, pattern, "")) + ")";
|
||||
}
|
||||
|
||||
public static string FullDescription(this MethodBase method)
|
||||
{
|
||||
var parameters = method.GetParameters().Select(p => p.ParameterType).ToArray();
|
||||
return method.DeclaringType.FullName + "." + method.Name + parameters.Description();
|
||||
}
|
||||
|
||||
public static Type[] Types(this ParameterInfo[] pinfo)
|
||||
{
|
||||
return pinfo.Select(pi => pi.ParameterType).ToArray();
|
||||
}
|
||||
|
||||
public static T GetValueSafe<S, T>(this Dictionary<S, T> dictionary, S key)
|
||||
{
|
||||
T result;
|
||||
if (dictionary.TryGetValue(key, out result))
|
||||
return result;
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static T GetTypedValue<T>(this Dictionary<string, object> dictionary, string key)
|
||||
{
|
||||
object result;
|
||||
if (dictionary.TryGetValue(key, out result))
|
||||
if (result is T)
|
||||
return (T)result;
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
public static void Do<T>(this IEnumerable<T> sequence, Action<T> action)
|
||||
{
|
||||
if (sequence == null) return;
|
||||
var enumerator = sequence.GetEnumerator();
|
||||
while (enumerator.MoveNext()) action(enumerator.Current);
|
||||
}
|
||||
|
||||
public static void DoIf<T>(this IEnumerable<T> sequence, Func<T, bool> condition, Action<T> action)
|
||||
{
|
||||
sequence.Where(condition).Do(action);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Add<T>(this IEnumerable<T> sequence, T item)
|
||||
{
|
||||
return (sequence ?? Enumerable.Empty<T>()).Concat(new[] { item });
|
||||
}
|
||||
|
||||
public static T[] AddRangeToArray<T>(this T[] sequence, T[] items)
|
||||
{
|
||||
return (sequence ?? Enumerable.Empty<T>()).Concat(items).ToArray();
|
||||
}
|
||||
|
||||
public static T[] AddToArray<T>(this T[] sequence, T item)
|
||||
{
|
||||
return Add(sequence, item).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class FileLog
|
||||
{
|
||||
public static string logPath;
|
||||
public static char indentChar = '\t';
|
||||
public static int indentLevel = 0;
|
||||
static List<string> buffer = new List<string>();
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
static FileLog()
|
||||
{
|
||||
logPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + Path.DirectorySeparatorChar + "harmony.log.txt";
|
||||
}
|
||||
|
||||
static string IndentString()
|
||||
{
|
||||
return new string(indentChar, indentLevel);
|
||||
}
|
||||
|
||||
public static void ChangeIndent(int delta)
|
||||
{
|
||||
indentLevel = Math.Max(0, indentLevel + delta);
|
||||
}
|
||||
|
||||
// use this method only if you are sure that FlushBuffer will be called
|
||||
// or else logging information is incomplete in case of a crash
|
||||
//
|
||||
public static void LogBuffered(string str)
|
||||
{
|
||||
lock (logPath)
|
||||
{
|
||||
buffer.Add(IndentString() + str);
|
||||
}
|
||||
}
|
||||
|
||||
public static void FlushBuffer()
|
||||
{
|
||||
lock (logPath)
|
||||
{
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
using (var writer = File.AppendText(logPath))
|
||||
{
|
||||
foreach (var str in buffer)
|
||||
writer.WriteLine(str);
|
||||
}
|
||||
buffer.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is the slower method that flushes changes directly to the file
|
||||
// to prevent missing information in case of a cache
|
||||
//
|
||||
public static void Log(string str)
|
||||
{
|
||||
lock (logPath)
|
||||
{
|
||||
using (var writer = File.AppendText(logPath))
|
||||
{
|
||||
writer.WriteLine(IndentString() + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
lock (logPath)
|
||||
{
|
||||
var path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + Path.DirectorySeparatorChar + "harmony.log.txt";
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void LogBytes(long ptr, int len)
|
||||
{
|
||||
lock (logPath)
|
||||
{
|
||||
var p = (byte*)ptr;
|
||||
var s = "";
|
||||
for (var i = 1; i <= len; i++)
|
||||
{
|
||||
if (s == "") s = "# ";
|
||||
s = s + (*p).ToString("X2") + " ";
|
||||
if (i > 1 || len == 1)
|
||||
{
|
||||
if (i % 8 == 0 || i == len)
|
||||
{
|
||||
Log(s);
|
||||
s = "";
|
||||
}
|
||||
else if (i % 4 == 0)
|
||||
s = s + " ";
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
var arr = new byte[len];
|
||||
Marshal.Copy((IntPtr)ptr, arr, 0, len);
|
||||
var md5Hash = MD5.Create();
|
||||
var hash = md5Hash.ComputeHash(arr);
|
||||
#pragma warning disable XS0001
|
||||
var sBuilder = new StringBuilder();
|
||||
#pragma warning restore XS0001
|
||||
for (var i = 0; i < hash.Length; i++)
|
||||
sBuilder.Append(hash[i].ToString("X2"));
|
||||
Log("HASH: " + sBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class PatchTools
|
||||
{
|
||||
// this holds all the objects we want to keep alive so they don't get garbage-collected
|
||||
static Dictionary<object, object> objectReferences = new Dictionary<object, object>();
|
||||
public static void RememberObject(object key, object value)
|
||||
{
|
||||
objectReferences[key] = value;
|
||||
}
|
||||
|
||||
public static MethodInfo GetPatchMethod<T>(Type patchType, string name, Type[] parameters = null)
|
||||
{
|
||||
var method = patchType.GetMethods(AccessTools.all)
|
||||
.FirstOrDefault(m => m.GetCustomAttributes(typeof(T), true).Any());
|
||||
if (method == null)
|
||||
method = AccessTools.Method(patchType, name, parameters);
|
||||
return method;
|
||||
}
|
||||
|
||||
public static void GetPatches(Type patchType, out MethodInfo prefix, out MethodInfo postfix, out MethodInfo transpiler)
|
||||
{
|
||||
prefix = GetPatchMethod<HarmonyPrefix>(patchType, "Prefix");
|
||||
postfix = GetPatchMethod<HarmonyPostfix>(patchType, "Postfix");
|
||||
transpiler = GetPatchMethod<HarmonyTranspiler>(patchType, "Transpiler");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
using Harmony.ILCopying;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Harmony.Tools
|
||||
{
|
||||
internal class SelfPatching
|
||||
{
|
||||
static readonly int upgradeToLatestVersionFullNameHash = typeof(UpgradeToLatestVersion).FullName.GetHashCode();
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
static int GetVersion(MethodBase method)
|
||||
{
|
||||
var attribute = method.GetCustomAttributes(false)
|
||||
.Where(attr => attr.GetType().FullName.GetHashCode() == upgradeToLatestVersionFullNameHash)
|
||||
.FirstOrDefault();
|
||||
if (attribute == null)
|
||||
return -1;
|
||||
return Traverse.Create(attribute).Field("version").GetValue<int>();
|
||||
}
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
static string MethodKey(MethodBase method)
|
||||
{
|
||||
return method.FullDescription();
|
||||
}
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
static bool IsHarmonyAssembly(Assembly assembly)
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.ReflectionOnly == false && assembly.GetType(typeof(HarmonyInstance).FullName) != null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<MethodBase> GetAllMethods(Assembly assembly)
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
return types
|
||||
.SelectMany(type => type.GetMethods(AccessTools.all).Cast<MethodBase>())
|
||||
.Concat(types.SelectMany(type => type.GetConstructors(AccessTools.all)).Cast<MethodBase>())
|
||||
.Concat(types.SelectMany(type => type.GetProperties(AccessTools.all)).Select(prop => prop.GetGetMethod()).Cast<MethodBase>())
|
||||
.Concat(types.SelectMany(type => type.GetProperties(AccessTools.all)).Select(prop => prop.GetSetMethod()).Cast<MethodBase>())
|
||||
.Where(method => method != null && method.DeclaringType.Assembly == assembly)
|
||||
.OrderBy(method => method.FullDescription())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static string AssemblyInfo(Assembly assembly)
|
||||
{
|
||||
var version = assembly.GetName().Version;
|
||||
var location = assembly.Location;
|
||||
if (location == null || location == "") location = new Uri(assembly.CodeBase).LocalPath;
|
||||
return location + "(v" + version + (assembly.GlobalAssemblyCache ? ", cached" : "") + ")";
|
||||
}
|
||||
|
||||
[UpgradeToLatestVersion(1)]
|
||||
public static void PatchOldHarmonyMethods()
|
||||
{
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
var ourAssembly = new StackTrace(true).GetFrame(1).GetMethod().DeclaringType.Assembly;
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
var originalVersion = ourAssembly.GetName().Version;
|
||||
var runningVersion = typeof(SelfPatching).Assembly.GetName().Version;
|
||||
if (runningVersion > originalVersion)
|
||||
{
|
||||
// log start because FileLog has not done it
|
||||
FileLog.Log("### Harmony v" + originalVersion + " started");
|
||||
FileLog.Log("### Self-patching unnecessary because we are already patched by v" + runningVersion);
|
||||
FileLog.Log("### At " + DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss"));
|
||||
return;
|
||||
}
|
||||
FileLog.Log("Self-patching started (v" + originalVersion + ")");
|
||||
}
|
||||
|
||||
var potentialMethodsToUpgrade = new Dictionary<string, MethodBase>();
|
||||
GetAllMethods(ourAssembly)
|
||||
.Where(method => method != null && method.GetCustomAttributes(false).Any(attr => attr is UpgradeToLatestVersion))
|
||||
.Do(method => potentialMethodsToUpgrade.Add(MethodKey(method), method));
|
||||
|
||||
var otherHarmonyAssemblies = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Where(assembly => IsHarmonyAssembly(assembly) && assembly != ourAssembly)
|
||||
.ToList();
|
||||
|
||||
if (HarmonyInstance.DEBUG)
|
||||
{
|
||||
otherHarmonyAssemblies.Do(assembly => FileLog.Log("Found Harmony " + AssemblyInfo(assembly)));
|
||||
|
||||
FileLog.Log("Potential methods to upgrade:");
|
||||
potentialMethodsToUpgrade.Values.OrderBy(method => method.FullDescription()).Do(method => FileLog.Log("- " + method.FullDescription()));
|
||||
}
|
||||
|
||||
var totalCounter = 0;
|
||||
var potentialCounter = 0;
|
||||
var patchedCounter = 0;
|
||||
foreach (var assembly in otherHarmonyAssemblies)
|
||||
{
|
||||
foreach (var oldMethod in GetAllMethods(assembly))
|
||||
{
|
||||
totalCounter++;
|
||||
|
||||
if (potentialMethodsToUpgrade.TryGetValue(MethodKey(oldMethod), out var newMethod))
|
||||
{
|
||||
var newVersion = GetVersion(newMethod);
|
||||
potentialCounter++;
|
||||
|
||||
var oldVersion = GetVersion(oldMethod);
|
||||
if (oldVersion < newVersion)
|
||||
{
|
||||
if (HarmonyInstance.DEBUG)
|
||||
FileLog.Log("Self-patching " + oldMethod.FullDescription() + " in " + AssemblyInfo(assembly));
|
||||
patchedCounter++;
|
||||
Memory.DetourMethod(oldMethod, newMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HarmonyInstance.DEBUG)
|
||||
FileLog.Log("Self-patched " + patchedCounter + " out of " + totalCounter + " methods (" + (potentialCounter - patchedCounter) + " skipped) in " + watch.ElapsedMilliseconds + "ms");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class SymbolExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Given a lambda expression that calls a method, returns the method info.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="expression">The expression.</param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo(Expression<Action> expression)
|
||||
{
|
||||
return GetMethodInfo((LambdaExpression)expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a lambda expression that calls a method, returns the method info.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="expression">The expression.</param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
|
||||
{
|
||||
return GetMethodInfo((LambdaExpression)expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a lambda expression that calls a method, returns the method info.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="expression">The expression.</param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression)
|
||||
{
|
||||
return GetMethodInfo((LambdaExpression)expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a lambda expression that calls a method, returns the method info.
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression.</param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo(LambdaExpression expression)
|
||||
{
|
||||
var outermostExpression = expression.Body as MethodCallExpression;
|
||||
|
||||
if (outermostExpression == null)
|
||||
throw new ArgumentException("Invalid Expression. Expression should consist of a Method call only.");
|
||||
|
||||
var method = outermostExpression.Method;
|
||||
if (method == null)
|
||||
throw new Exception("Cannot find method for expression " + expression);
|
||||
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,298 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public class Traverse<T>
|
||||
{
|
||||
private Traverse traverse;
|
||||
|
||||
Traverse()
|
||||
{
|
||||
}
|
||||
|
||||
public Traverse(Traverse traverse)
|
||||
{
|
||||
this.traverse = traverse;
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get => traverse.GetValue<T>();
|
||||
set => traverse.SetValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public class Traverse
|
||||
{
|
||||
static AccessCache Cache;
|
||||
|
||||
Type _type;
|
||||
object _root;
|
||||
MemberInfo _info;
|
||||
MethodBase _method;
|
||||
object[] _params;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
static Traverse()
|
||||
{
|
||||
if (Cache == null)
|
||||
Cache = new AccessCache();
|
||||
}
|
||||
|
||||
public static Traverse Create(Type type)
|
||||
{
|
||||
return new Traverse(type);
|
||||
}
|
||||
|
||||
public static Traverse Create<T>()
|
||||
{
|
||||
return Create(typeof(T));
|
||||
}
|
||||
|
||||
public static Traverse Create(object root)
|
||||
{
|
||||
return new Traverse(root);
|
||||
}
|
||||
|
||||
public static Traverse CreateWithType(string name)
|
||||
{
|
||||
return new Traverse(AccessTools.TypeByName(name));
|
||||
}
|
||||
|
||||
Traverse()
|
||||
{
|
||||
}
|
||||
|
||||
public Traverse(Type type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public Traverse(object root)
|
||||
{
|
||||
_root = root;
|
||||
_type = root?.GetType();
|
||||
}
|
||||
|
||||
Traverse(object root, MemberInfo info, object[] index)
|
||||
{
|
||||
_root = root;
|
||||
_type = root?.GetType();
|
||||
_info = info;
|
||||
_params = index;
|
||||
}
|
||||
|
||||
Traverse(object root, MethodInfo method, object[] parameter)
|
||||
{
|
||||
_root = root;
|
||||
_type = method.ReturnType;
|
||||
_method = method;
|
||||
_params = parameter;
|
||||
}
|
||||
|
||||
public object GetValue()
|
||||
{
|
||||
if (_info is FieldInfo)
|
||||
return ((FieldInfo)_info).GetValue(_root);
|
||||
if (_info is PropertyInfo)
|
||||
return ((PropertyInfo)_info).GetValue(_root, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
|
||||
if (_method != null)
|
||||
return _method.Invoke(_root, _params);
|
||||
if (_root == null && _type != null) return _type;
|
||||
return _root;
|
||||
}
|
||||
|
||||
public T GetValue<T>()
|
||||
{
|
||||
var value = GetValue();
|
||||
if (value == null) return default(T);
|
||||
return (T)value;
|
||||
}
|
||||
|
||||
public object GetValue(params object[] arguments)
|
||||
{
|
||||
if (_method == null)
|
||||
throw new Exception("cannot get method value without method");
|
||||
return _method.Invoke(_root, arguments);
|
||||
}
|
||||
|
||||
public T GetValue<T>(params object[] arguments)
|
||||
{
|
||||
if (_method == null)
|
||||
throw new Exception("cannot get method value without method");
|
||||
return (T)_method.Invoke(_root, arguments);
|
||||
}
|
||||
|
||||
public Traverse SetValue(object value)
|
||||
{
|
||||
if (_info is FieldInfo)
|
||||
((FieldInfo)_info).SetValue(_root, value, AccessTools.all, null, CultureInfo.CurrentCulture);
|
||||
if (_info is PropertyInfo)
|
||||
((PropertyInfo)_info).SetValue(_root, value, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
|
||||
if (_method != null)
|
||||
throw new Exception("cannot set value of method " + _method.FullDescription());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Type GetValueType()
|
||||
{
|
||||
if (_info is FieldInfo)
|
||||
return ((FieldInfo)_info).FieldType;
|
||||
if (_info is PropertyInfo)
|
||||
return ((PropertyInfo)_info).PropertyType;
|
||||
return null;
|
||||
}
|
||||
|
||||
Traverse Resolve()
|
||||
{
|
||||
if (_root == null && _type != null) return this;
|
||||
return new Traverse(GetValue());
|
||||
}
|
||||
|
||||
public Traverse Type(string name)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null");
|
||||
if (_type == null) return new Traverse();
|
||||
var type = AccessTools.Inner(_type, name);
|
||||
if (type == null) return new Traverse();
|
||||
return new Traverse(type);
|
||||
}
|
||||
|
||||
public Traverse Field(string name)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null");
|
||||
var resolved = Resolve();
|
||||
if (resolved._type == null) return new Traverse();
|
||||
var info = Cache.GetFieldInfo(resolved._type, name);
|
||||
if (info == null) return new Traverse();
|
||||
if (info.IsStatic == false && resolved._root == null) return new Traverse();
|
||||
return new Traverse(resolved._root, info, null);
|
||||
}
|
||||
|
||||
public Traverse<T> Field<T>(string name)
|
||||
{
|
||||
return new Traverse<T>(Field(name));
|
||||
}
|
||||
|
||||
public List<string> Fields()
|
||||
{
|
||||
var resolved = Resolve();
|
||||
return AccessTools.GetFieldNames(resolved._type);
|
||||
}
|
||||
|
||||
public Traverse Property(string name, object[] index = null)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null");
|
||||
var resolved = Resolve();
|
||||
if (resolved._root == null || resolved._type == null) return new Traverse();
|
||||
var info = Cache.GetPropertyInfo(resolved._type, name);
|
||||
if (info == null) return new Traverse();
|
||||
return new Traverse(resolved._root, info, index);
|
||||
}
|
||||
|
||||
public Traverse<T> Property<T>(string name, object[] index = null)
|
||||
{
|
||||
return new Traverse<T>(Property(name, index));
|
||||
}
|
||||
|
||||
public List<string> Properties()
|
||||
{
|
||||
var resolved = Resolve();
|
||||
return AccessTools.GetPropertyNames(resolved._type);
|
||||
}
|
||||
|
||||
public Traverse Method(string name, params object[] arguments)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null");
|
||||
var resolved = Resolve();
|
||||
if (resolved._type == null) return new Traverse();
|
||||
var types = AccessTools.GetTypes(arguments);
|
||||
var method = Cache.GetMethodInfo(resolved._type, name, types);
|
||||
if (method == null) return new Traverse();
|
||||
return new Traverse(resolved._root, (MethodInfo)method, arguments);
|
||||
}
|
||||
|
||||
public Traverse Method(string name, Type[] paramTypes, object[] arguments = null)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null");
|
||||
var resolved = Resolve();
|
||||
if (resolved._type == null) return new Traverse();
|
||||
var method = Cache.GetMethodInfo(resolved._type, name, paramTypes);
|
||||
if (method == null) return new Traverse();
|
||||
return new Traverse(resolved._root, (MethodInfo)method, arguments);
|
||||
}
|
||||
|
||||
public List<string> Methods()
|
||||
{
|
||||
var resolved = Resolve();
|
||||
return AccessTools.GetMethodNames(resolved._type);
|
||||
}
|
||||
|
||||
public bool FieldExists()
|
||||
{
|
||||
return _info != null;
|
||||
}
|
||||
|
||||
public bool MethodExists()
|
||||
{
|
||||
return _method != null;
|
||||
}
|
||||
|
||||
public bool TypeExists()
|
||||
{
|
||||
return _type != null;
|
||||
}
|
||||
|
||||
public static void IterateFields(object source, Action<Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
AccessTools.GetFieldNames(source).ForEach(f => action(sourceTrv.Field(f)));
|
||||
}
|
||||
|
||||
public static void IterateFields(object source, object target, Action<Traverse, Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
var targetTrv = Create(target);
|
||||
AccessTools.GetFieldNames(source).ForEach(f => action(sourceTrv.Field(f), targetTrv.Field(f)));
|
||||
}
|
||||
|
||||
public static void IterateFields(object source, object target, Action<string, Traverse, Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
var targetTrv = Create(target);
|
||||
AccessTools.GetFieldNames(source).ForEach(f => action(f, sourceTrv.Field(f), targetTrv.Field(f)));
|
||||
}
|
||||
|
||||
public static void IterateProperties(object source, Action<Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
AccessTools.GetPropertyNames(source).ForEach(f => action(sourceTrv.Property(f)));
|
||||
}
|
||||
|
||||
public static void IterateProperties(object source, object target, Action<Traverse, Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
var targetTrv = Create(target);
|
||||
AccessTools.GetPropertyNames(source).ForEach(f => action(sourceTrv.Property(f), targetTrv.Property(f)));
|
||||
}
|
||||
|
||||
public static void IterateProperties(object source, object target, Action<string, Traverse, Traverse> action)
|
||||
{
|
||||
var sourceTrv = Create(source);
|
||||
var targetTrv = Create(target);
|
||||
AccessTools.GetPropertyNames(source).ForEach(f => action(f, sourceTrv.Property(f), targetTrv.Property(f)));
|
||||
}
|
||||
|
||||
public static Action<Traverse, Traverse> CopyFields = (from, to) => { to.SetValue(from.GetValue()); };
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var value = _method ?? GetValue();
|
||||
return value?.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Harmony
|
||||
{
|
||||
public static class Transpilers
|
||||
{
|
||||
public static IEnumerable<CodeInstruction> MethodReplacer(this IEnumerable<CodeInstruction> instructions, MethodBase from, MethodBase to)
|
||||
{
|
||||
if (from == null)
|
||||
throw new ArgumentException("Unexpected null argument", nameof(from));
|
||||
if (to == null)
|
||||
throw new ArgumentException("Unexpected null argument", nameof(to));
|
||||
|
||||
foreach (var instruction in instructions)
|
||||
{
|
||||
var method = instruction.operand as MethodBase;
|
||||
if (method == from)
|
||||
{
|
||||
instruction.opcode = to.IsConstructor ? OpCodes.Newobj : OpCodes.Call;
|
||||
instruction.operand = to;
|
||||
}
|
||||
yield return instruction;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<CodeInstruction> DebugLogger(this IEnumerable<CodeInstruction> instructions, string text)
|
||||
{
|
||||
yield return new CodeInstruction(OpCodes.Ldstr, text);
|
||||
yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(FileLog), nameof(FileLog.Log)));
|
||||
foreach (var instruction in instructions) yield return instruction;
|
||||
}
|
||||
|
||||
// more added soon
|
||||
}
|
||||
}
|
|
@ -0,0 +1,831 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{23B6885E-0282-435B-A854-D49ABF1391D6}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Mod</RootNamespace>
|
||||
<AssemblyName>Mod</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Harmony\Attributes.cs" />
|
||||
<Compile Include="Harmony\CodeInstruction.cs" />
|
||||
<Compile Include="Harmony\CodeTranspiler.cs" />
|
||||
<Compile Include="Harmony\Extras\DelegateTypeFactory.cs" />
|
||||
<Compile Include="Harmony\Extras\FastAccess.cs" />
|
||||
<Compile Include="Harmony\Extras\MethodInvoker.cs" />
|
||||
<Compile Include="Harmony\GlobalSuppressions.cs" />
|
||||
<Compile Include="Harmony\HarmonyInstance.cs" />
|
||||
<Compile Include="Harmony\HarmonyMethod.cs" />
|
||||
<Compile Include="Harmony\HarmonySharedState.cs" />
|
||||
<Compile Include="Harmony\ILCopying\ByteBuffer.cs" />
|
||||
<Compile Include="Harmony\ILCopying\Emitter.cs" />
|
||||
<Compile Include="Harmony\ILCopying\ILInstruction.cs" />
|
||||
<Compile Include="Harmony\ILCopying\Memory.cs" />
|
||||
<Compile Include="Harmony\ILCopying\MethodCopier.cs" />
|
||||
<Compile Include="Harmony\ILCopying\Signature.cs" />
|
||||
<Compile Include="Harmony\MethodPatcher.cs" />
|
||||
<Compile Include="Harmony\Patch.cs" />
|
||||
<Compile Include="Harmony\PatchFunctions.cs" />
|
||||
<Compile Include="Harmony\PatchProcessor.cs" />
|
||||
<Compile Include="Harmony\Priority.cs" />
|
||||
<Compile Include="Harmony\Tools\AccessCache.cs" />
|
||||
<Compile Include="Harmony\Tools\AccessTools.cs" />
|
||||
<Compile Include="Harmony\Tools\DynamicTools.cs" />
|
||||
<Compile Include="Harmony\Tools\Extensions.cs" />
|
||||
<Compile Include="Harmony\Tools\FileLog.cs" />
|
||||
<Compile Include="Harmony\Tools\PatchTools.cs" />
|
||||
<Compile Include="Harmony\Tools\SelfPatching.cs" />
|
||||
<Compile Include="Harmony\Tools\SymbolExtensions.cs" />
|
||||
<Compile Include="Harmony\Tools\Traverse.cs" />
|
||||
<Compile Include="Harmony\Transpilers.cs" />
|
||||
<Compile Include="ModEntry.cs" />
|
||||
<Compile Include="Mono\Cecil\ArrayType.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyFlags.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyHashAlgorithm.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyLinkedResource.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyNameDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyNameReference.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyReader.cs" />
|
||||
<Compile Include="Mono\Cecil\AssemblyWriter.cs" />
|
||||
<Compile Include="Mono\Cecil\BaseAssemblyResolver.cs" />
|
||||
<Compile Include="Mono\Cecil\CallSite.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\Code.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\CodeReader.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\CodeWriter.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\Document.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\ExceptionHandler.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\ILProcessor.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\Instruction.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\MethodBody.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\OpCode.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\OpCodes.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\PortablePdb.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\SequencePoint.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\Symbols.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\VariableDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\Cil\VariableReference.cs" />
|
||||
<Compile Include="Mono\Cecil\Consts.cs" />
|
||||
<Compile Include="Mono\Cecil\CustomAttribute.cs" />
|
||||
<Compile Include="Mono\Cecil\DefaultAssemblyResolver.cs" />
|
||||
<Compile Include="Mono\Cecil\EmbeddedResource.cs" />
|
||||
<Compile Include="Mono\Cecil\EventAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\EventDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\EventReference.cs" />
|
||||
<Compile Include="Mono\Cecil\ExportedType.cs" />
|
||||
<Compile Include="Mono\Cecil\FieldAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\FieldDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\FieldReference.cs" />
|
||||
<Compile Include="Mono\Cecil\FileAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\FunctionPointerType.cs" />
|
||||
<Compile Include="Mono\Cecil\GenericInstanceMethod.cs" />
|
||||
<Compile Include="Mono\Cecil\GenericInstanceType.cs" />
|
||||
<Compile Include="Mono\Cecil\GenericParameter.cs" />
|
||||
<Compile Include="Mono\Cecil\GenericParameterAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\IConstantProvider.cs" />
|
||||
<Compile Include="Mono\Cecil\ICustomAttributeProvider.cs" />
|
||||
<Compile Include="Mono\Cecil\IGenericInstance.cs" />
|
||||
<Compile Include="Mono\Cecil\IGenericParameterProvider.cs" />
|
||||
<Compile Include="Mono\Cecil\IMarshalInfoProvider.cs" />
|
||||
<Compile Include="Mono\Cecil\IMemberDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\IMetadataScope.cs" />
|
||||
<Compile Include="Mono\Cecil\IMetadataTokenProvider.cs" />
|
||||
<Compile Include="Mono\Cecil\IMethodSignature.cs" />
|
||||
<Compile Include="Mono\Cecil\Import.cs" />
|
||||
<Compile Include="Mono\Cecil\LinkedResource.cs" />
|
||||
<Compile Include="Mono\Cecil\ManifestResourceAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\MarshalInfo.cs" />
|
||||
<Compile Include="Mono\Cecil\MemberDefinitionCollection.cs" />
|
||||
<Compile Include="Mono\Cecil\MemberReference.cs" />
|
||||
<Compile Include="Mono\Cecil\MetadataResolver.cs" />
|
||||
<Compile Include="Mono\Cecil\MetadataSystem.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\BlobHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\Buffers.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\CodedIndex.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\ElementType.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\GuidHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\Heap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\MetadataToken.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\PdbHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\Row.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\StringHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\TableHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\TokenType.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\UserStringHeap.cs" />
|
||||
<Compile Include="Mono\Cecil\Metadata\Utilities.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodCallingConvention.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodImplAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodReference.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodReturnType.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodSemanticsAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\MethodSpecification.cs" />
|
||||
<Compile Include="Mono\Cecil\Modifiers.cs" />
|
||||
<Compile Include="Mono\Cecil\ModuleDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\ModuleKind.cs" />
|
||||
<Compile Include="Mono\Cecil\ModuleReference.cs" />
|
||||
<Compile Include="Mono\Cecil\NativeType.cs" />
|
||||
<Compile Include="Mono\Cecil\ParameterAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\ParameterDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\ParameterDefinitionCollection.cs" />
|
||||
<Compile Include="Mono\Cecil\ParameterReference.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\BinaryStreamReader.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\BinaryStreamWriter.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\ByteBuffer.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\ByteBufferEqualityComparer.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\DataDirectory.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\Image.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\ImageReader.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\ImageWriter.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\Section.cs" />
|
||||
<Compile Include="Mono\Cecil\PE\TextMap.cs" />
|
||||
<Compile Include="Mono\Cecil\PinnedType.cs" />
|
||||
<Compile Include="Mono\Cecil\PInvokeAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\PInvokeInfo.cs" />
|
||||
<Compile Include="Mono\Cecil\PointerType.cs" />
|
||||
<Compile Include="Mono\Cecil\PropertyAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\PropertyDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\PropertyReference.cs" />
|
||||
<Compile Include="Mono\Cecil\ReferenceType.cs" />
|
||||
<Compile Include="Mono\Cecil\Resource.cs" />
|
||||
<Compile Include="Mono\Cecil\SecurityDeclaration.cs" />
|
||||
<Compile Include="Mono\Cecil\SentinelType.cs" />
|
||||
<Compile Include="Mono\Cecil\TargetRuntime.cs" />
|
||||
<Compile Include="Mono\Cecil\Treatments.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeAttributes.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeDefinition.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeDefinitionCollection.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeParser.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeReference.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeSpecification.cs" />
|
||||
<Compile Include="Mono\Cecil\TypeSystem.cs" />
|
||||
<Compile Include="Mono\Cecil\VariantType.cs" />
|
||||
<Compile Include="Mono\Cecil\WindowsRuntimeProjections.cs" />
|
||||
<Compile Include="Mono\Collections\Generic\Collection.cs" />
|
||||
<Compile Include="Mono\Collections\Generic\ReadOnlyCollection.cs" />
|
||||
<Compile Include="Mono\Disposable.cs" />
|
||||
<Compile Include="Mono\Empty.cs" />
|
||||
<Compile Include="Mono\MergeSort.cs" />
|
||||
<Compile Include="Mono\Security\Cryptography\CryptoConvert.cs" />
|
||||
<Compile Include="Mono\Security\Cryptography\CryptoService.cs" />
|
||||
<Compile Include="Mono\Type.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonBinaryType.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonBinaryWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonObjectId.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonToken.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonType.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Bson\BsonWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\ConstructorHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\BinaryConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\BsonObjectIdConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\CustomCreationConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\DataSetConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\DataTableConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\DateTimeConverterBase.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\DiscriminatedUnionConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\EntityKeyMemberConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\ExpandoObjectConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\IsoDateTimeConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\JavaScriptDateTimeConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\KeyValuePairConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\RegexConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\StringEnumConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\UnixDateTimeConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\VersionConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Converters\XmlNodeConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\DateFormatHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\DateParseHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\DateTimeZoneHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\DefaultJsonNameTable.cs" />
|
||||
<Compile Include="Newtonsoft.Json\DefaultValueHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\FloatFormatHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\FloatParseHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\FormatterAssemblyStyle.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Formatting.cs" />
|
||||
<Compile Include="Newtonsoft.Json\IArrayPool.cs" />
|
||||
<Compile Include="Newtonsoft.Json\IJsonLineInfo.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonArrayAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonConstructorAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonContainerAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonConvert.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonConverterAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonConverterCollection.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonException.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonIgnoreAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonNameTable.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonObjectAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonPosition.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonPropertyAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonReader.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonReaderException.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonRequiredAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonSerializationException.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonSerializer.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonSerializerSettings.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonTextReader.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonTextReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonTextWriter.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonTextWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonToken.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonValidatingReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonWriter.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\JsonWriterException.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\CommentHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\DuplicatePropertyNameHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\Extensions.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\IJEnumerable.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JArray.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JArray.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JConstructor.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JConstructor.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JContainer.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JContainer.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JEnumerable.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JObject.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JObject.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JProperty.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JProperty.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JRaw.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JRaw.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonLoadSettings.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\FieldFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\FieldMultipleFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\JPath.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\PathFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\QueryExpression.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\QueryFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\QueryScanFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\RootFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\ScanFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JsonPath\ScanMultipleFilter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JToken.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JToken.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JTokenEqualityComparer.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JTokenReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JTokenType.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JTokenWriter.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JTokenWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JValue.Async.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\JValue.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\LineInfoHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Linq\MergeNullValueHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\MemberSerialization.cs" />
|
||||
<Compile Include="Newtonsoft.Json\MetadataPropertyHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\MissingMemberHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\NullValueHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\ObjectCreationHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\PreserveReferencesHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\ReferenceLoopHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Required.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\Extensions.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchema.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaBuilder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaConstants.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaException.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaGenerator.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaModel.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaModelBuilder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaNode.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaNodeCollection.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaType.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\JsonSchemaWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\UndefinedSchemaIdHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\ValidationEventArgs.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Schema\ValidationEventHandler.cs" />
|
||||
<Compile Include="Newtonsoft.Json\SerializationBinder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\CachedAttributeGetter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\CamelCaseNamingStrategy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\CamelCasePropertyNamesContractResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DefaultContractResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DefaultNamingStrategy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DefaultReferenceResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DefaultSerializationBinder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DiagnosticsTraceWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\DynamicValueProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ErrorContext.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ErrorEventArgs.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ExpressionValueProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\FormatterConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\IAttributeProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\IContractResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\IReferenceResolver.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ISerializationBinder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ITraceWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\IValueProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonArrayContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonContainerContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonDictionaryContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonDynamicContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonFormatterConverter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonISerializableContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonLinqContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonObjectContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonPrimitiveContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonProperty.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonPropertyCollection.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonSerializerInternalBase.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonSerializerProxy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonStringContract.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\MemoryTraceWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\NamingStrategy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ObjectConstructor.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\OnErrorAttribute.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ReflectionAttributeProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\ReflectionValueProvider.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\SerializationBinderAdapter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\SnakeCaseNamingStrategy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\TraceJsonReader.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Serialization\TraceJsonWriter.cs" />
|
||||
<Compile Include="Newtonsoft.Json\StringEscapeHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\TraceLevel.cs" />
|
||||
<Compile Include="Newtonsoft.Json\TypeNameAssemblyFormatHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\TypeNameHandling.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\AsyncUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\Base64Encoder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\BidirectionalDictionary.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\CollectionUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\CollectionWrapper.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ConvertUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DateTimeParser.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DateTimeUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DictionaryWrapper.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DynamicProxy.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DynamicProxyMetaObject.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DynamicReflectionDelegateFactory.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\DynamicUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\EnumInfo.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\EnumUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ExpressionReflectionDelegateFactory.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\FSharpUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ILGeneratorExtensions.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ImmutableCollectionsUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\JavaScriptUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\JsonTokenUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\LateBoundReflectionDelegateFactory.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\LinqBridge.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\MathUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\MethodBinder.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\MethodCall.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\MiscellaneousUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ReflectionDelegateFactory.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ReflectionObject.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ReflectionUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\StringBuffer.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\StringReference.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\StringUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\StructMultiKey.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ThreadSafeStore.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\TypeExtensions.cs" />
|
||||
<Compile Include="Newtonsoft.Json\Utilities\ValidationUtils.cs" />
|
||||
<Compile Include="Newtonsoft.Json\WriteState.cs" />
|
||||
<Compile Include="Options\ModOptionsCheckbox.cs" />
|
||||
<Compile Include="Options\ModOptionsSlider.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SMAPI\Constants.cs" />
|
||||
<Compile Include="SMAPI\ContentSource.cs" />
|
||||
<Compile Include="SMAPI\Context.cs" />
|
||||
<Compile Include="SMAPI\Enums\LoadStage.cs" />
|
||||
<Compile Include="SMAPI\Enums\SkillType.cs" />
|
||||
<Compile Include="SMAPI\Events\BuildingListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ButtonPressedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ButtonReleasedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ChangeType.cs" />
|
||||
<Compile Include="SMAPI\Events\CursorMovedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\DayEndingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\DayStartedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\DebrisListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\GameLaunchedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\IDisplayEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\IGameLoopEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\IInputEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\IModEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\IMultiplayerEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\InventoryChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\IPlayerEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\ISpecialisedEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\ItemStackChange.cs" />
|
||||
<Compile Include="SMAPI\Events\ItemStackSizeChange.cs" />
|
||||
<Compile Include="SMAPI\Events\IWorldEvents.cs" />
|
||||
<Compile Include="SMAPI\Events\LargeTerrainFeatureListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\LevelChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\LoadStageChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\LocationListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\MenuChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ModMessageReceivedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\MouseWheelScrolledEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\NpcListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ObjectListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\OneSecondUpdateTickedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\OneSecondUpdateTickingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\PeerContextReceivedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\PeerDisconnectedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderedActiveMenuEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderedHudEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderedWorldEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderingActiveMenuEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderingHudEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\RenderingWorldEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\ReturnedToTitleEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\SaveCreatedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\SaveCreatingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\SavedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\SaveLoadedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\SavingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\TerrainFeatureListChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\TimeChangedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\UnvalidatedUpdateTickedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\UnvalidatedUpdateTickingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\UpdateTickedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\UpdateTickingEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\WarpedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Events\WindowResizedEventArgs.cs" />
|
||||
<Compile Include="SMAPI\Framework\Command.cs" />
|
||||
<Compile Include="SMAPI\Framework\CommandManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentCoordinator.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentManagers\BaseContentManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentManagers\GameContentManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentManagers\IContentManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentManagers\ModContentManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\ContentPack.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\AssetData.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\AssetDataForDictionary.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\AssetDataForImage.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\AssetDataForObject.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\AssetInfo.cs" />
|
||||
<Compile Include="SMAPI\Framework\Content\ContentCache.cs" />
|
||||
<Compile Include="SMAPI\Framework\CursorPosition.cs" />
|
||||
<Compile Include="SMAPI\Framework\DeprecationLevel.cs" />
|
||||
<Compile Include="SMAPI\Framework\DeprecationManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\DeprecationWarning.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\EventManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ManagedEvent.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModDisplayEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModEventsBase.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModGameLoopEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModInputEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModMultiplayerEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModPlayerEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModSpecialisedEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Events\ModWorldEvents.cs" />
|
||||
<Compile Include="SMAPI\Framework\Exceptions\SAssemblyLoadFailedException.cs" />
|
||||
<Compile Include="SMAPI\Framework\Exceptions\SContentLoadException.cs" />
|
||||
<Compile Include="SMAPI\Framework\GameVersion.cs" />
|
||||
<Compile Include="SMAPI\Framework\IModMetadata.cs" />
|
||||
<Compile Include="SMAPI\Framework\Input\GamePadStateBuilder.cs" />
|
||||
<Compile Include="SMAPI\Framework\Input\InputStatus.cs" />
|
||||
<Compile Include="SMAPI\Framework\Input\SInputState.cs" />
|
||||
<Compile Include="SMAPI\Framework\InternalExtensions.cs" />
|
||||
<Compile Include="SMAPI\Framework\Logging\ConsoleInterceptionManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\Logging\InterceptingTextWriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\Logging\LogFileManager.cs" />
|
||||
<Compile Include="SMAPI\Framework\Models\ModFolderExport.cs" />
|
||||
<Compile Include="SMAPI\Framework\Models\SConfig.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\BaseHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\CommandHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\ContentHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\ContentPackHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\DataHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\InputHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\ModHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\ModRegistryHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\ReflectionHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModHelpers\TranslationHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\AssemblyDefinitionResolver.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\AssemblyLoader.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\AssemblyLoadStatus.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\AssemblyParseResult.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\EventFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\FieldFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\MethodFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\PropertyFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\ReferenceToMemberWithUnexpectedTypeFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\ReferenceToMissingMemberFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Finders\TypeFinder.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\IInstructionHandler.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\IncompatibleInstructionException.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\InstructionHandleResult.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\InvalidModStateException.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\ModDependencyStatus.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\ModMetadata.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\ModMetadataStatus.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\ModResolver.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\PlatformAssemblyMap.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\RewriteHelper.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Rewriters\FieldReplaceRewriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Rewriters\FieldToPropertyRewriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Rewriters\MethodParentRewriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Rewriters\StaticFieldToConstantRewriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\Rewriters\TypeReferenceRewriter.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModLoading\TypeReferenceComparer.cs" />
|
||||
<Compile Include="SMAPI\Framework\ModRegistry.cs" />
|
||||
<Compile Include="SMAPI\Framework\Monitor.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\MessageType.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\ModMessageModel.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\MultiplayerPeer.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\MultiplayerPeerMod.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\RemoteContextModel.cs" />
|
||||
<Compile Include="SMAPI\Framework\Networking\RemoteContextModModel.cs" />
|
||||
<Compile Include="SMAPI\Framework\Patching\GamePatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\Patching\IHarmonyPatch.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\CacheEntry.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\InterfaceProxyBuilder.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\InterfaceProxyFactory.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\ReflectedField.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\ReflectedMethod.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\ReflectedProperty.cs" />
|
||||
<Compile Include="SMAPI\Framework\Reflection\Reflector.cs" />
|
||||
<Compile Include="SMAPI\Framework\RequestExitDelegate.cs" />
|
||||
<Compile Include="SMAPI\Framework\RewriteFacades\SpriteBatchMethods.cs" />
|
||||
<Compile Include="SMAPI\Framework\SCore.cs" />
|
||||
<Compile Include="SMAPI\Framework\Serialisation\ColorConverter.cs" />
|
||||
<Compile Include="SMAPI\Framework\Serialisation\PointConverter.cs" />
|
||||
<Compile Include="SMAPI\Framework\Serialisation\RectangleConverter.cs" />
|
||||
<Compile Include="SMAPI\Framework\SGame.cs" />
|
||||
<Compile Include="SMAPI\Framework\SGameConstructorHack.cs" />
|
||||
<Compile Include="SMAPI\Framework\Singleton.cs" />
|
||||
<Compile Include="SMAPI\Framework\SModHooks.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\Comparers\EquatableComparer.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\Comparers\GenericEqualsComparer.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\Comparers\ObjectReferenceComparer.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\BaseDisposableWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\ComparableListWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\ComparableWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\NetCollectionWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\NetDictionaryWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\NetValueWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\ObservableCollectionWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\FieldWatchers\WatcherFactory.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\ICollectionWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\IDictionaryWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\IValueWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\IWatcher.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\LocationTracker.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\PlayerTracker.cs" />
|
||||
<Compile Include="SMAPI\Framework\StateTracking\WorldLocationsTracker.cs" />
|
||||
<Compile Include="SMAPI\Framework\Utilities\ContextHash.cs" />
|
||||
<Compile Include="SMAPI\Framework\Utilities\Countdown.cs" />
|
||||
<Compile Include="SMAPI\Framework\WatcherCore.cs" />
|
||||
<Compile Include="SMAPI\GamePlatform.cs" />
|
||||
<Compile Include="SMAPI\IAssetData.cs" />
|
||||
<Compile Include="SMAPI\IAssetDataForDictionary.cs" />
|
||||
<Compile Include="SMAPI\IAssetDataForImage.cs" />
|
||||
<Compile Include="SMAPI\IAssetEditor.cs" />
|
||||
<Compile Include="SMAPI\IAssetInfo.cs" />
|
||||
<Compile Include="SMAPI\IAssetLoader.cs" />
|
||||
<Compile Include="SMAPI\ICommandHelper.cs" />
|
||||
<Compile Include="SMAPI\IContentHelper.cs" />
|
||||
<Compile Include="SMAPI\IContentPack.cs" />
|
||||
<Compile Include="SMAPI\IContentPackHelper.cs" />
|
||||
<Compile Include="SMAPI\ICursorPosition.cs" />
|
||||
<Compile Include="SMAPI\IDataHelper.cs" />
|
||||
<Compile Include="SMAPI\IInputHelper.cs" />
|
||||
<Compile Include="SMAPI\IMod.cs" />
|
||||
<Compile Include="SMAPI\IModHelper.cs" />
|
||||
<Compile Include="SMAPI\IModInfo.cs" />
|
||||
<Compile Include="SMAPI\IModLinked.cs" />
|
||||
<Compile Include="SMAPI\IModRegistry.cs" />
|
||||
<Compile Include="SMAPI\IMonitor.cs" />
|
||||
<Compile Include="SMAPI\IMultiplayerPeer.cs" />
|
||||
<Compile Include="SMAPI\IMultiplayerPeerMod.cs" />
|
||||
<Compile Include="SMAPI\Internal\ConsoleWriting\ColorfulConsoleWriter.cs" />
|
||||
<Compile Include="SMAPI\Internal\ConsoleWriting\LogLevel.cs" />
|
||||
<Compile Include="SMAPI\Internal\ConsoleWriting\MonitorColorScheme.cs" />
|
||||
<Compile Include="SMAPI\Internal\EnvironmentUtility.cs" />
|
||||
<Compile Include="SMAPI\Internal\Platform.cs" />
|
||||
<Compile Include="SMAPI\IReflectedField.cs" />
|
||||
<Compile Include="SMAPI\IReflectedMethod.cs" />
|
||||
<Compile Include="SMAPI\IReflectedProperty.cs" />
|
||||
<Compile Include="SMAPI\IReflectionHelper.cs" />
|
||||
<Compile Include="SMAPI\ITranslationHelper.cs" />
|
||||
<Compile Include="SMAPI\LogLevel.cs" />
|
||||
<Compile Include="SMAPI\Metadata\CoreAssetPropagator.cs" />
|
||||
<Compile Include="SMAPI\Metadata\InstructionMetadata.cs" />
|
||||
<Compile Include="SMAPI\Mod.cs" />
|
||||
<Compile Include="SMAPI\Patches\DialogueErrorPatch.cs" />
|
||||
<Compile Include="SMAPI\Patches\LoadForNewGamePatch.cs" />
|
||||
<Compile Include="SMAPI\Patches\ObjectErrorPatch.cs" />
|
||||
<Compile Include="SMAPI\PatchMode.cs" />
|
||||
<Compile Include="SMAPI\Program.cs" />
|
||||
<Compile Include="SMAPI\SButton.cs" />
|
||||
<Compile Include="SMAPI\SemanticVersion.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\CoreInterfaces\IManifest.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\CoreInterfaces\IManifestContentPackFor.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\CoreInterfaces\IManifestDependency.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\CoreInterfaces\ISemanticVersion.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\MetadataModel.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDatabase.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDataField.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDataFieldKey.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDataModel.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDataRecord.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModDataRecordVersionedFields.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModStatus.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModData\ModWarning.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModScanning\ModFolder.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\ModScanning\ModScanner.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\UpdateData\ModRepositoryKey.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Framework\UpdateData\UpdateKey.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\ModToolkit.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\SemanticVersion.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Converters\ManifestContentPackForConverter.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Converters\ManifestDependencyArrayConverter.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Converters\SemanticVersionConverter.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Converters\SimpleReadOnlyConverter.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\InternalExtensions.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\JsonHelper.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Models\Manifest.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Models\ManifestContentPackFor.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\Models\ManifestDependency.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Serialisation\SParseException.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Utilities\FileUtilities.cs" />
|
||||
<Compile Include="SMAPI\Toolkit\Utilities\PathUtilities.cs" />
|
||||
<Compile Include="SMAPI\Translation.cs" />
|
||||
<Compile Include="SMAPI\Utilities\SDate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BmFont, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\BmFont.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Android.Vending.Expansion.Downloader, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Google.Android.Vending.Expansion.Downloader.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Android.Vending.Expansion.ZipFile, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Google.Android.Vending.Expansion.ZipFile.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Android.Vending.Licensing, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Google.Android.Vending.Licensing.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Java.Interop.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.Analytics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Crashes, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.Crashes.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Mono.Android.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Security, Version=2.0.5.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Mono.Security.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewValley.Mod, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\StardewValley.Mod.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
|
||||
<HintPath>..\..\assemblies\System.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
|
||||
<HintPath>..\..\assemblies\System.Xml</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<HintPath>..\..\assemblies\System.Net.Http</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
|
||||
<HintPath>..\..\assemblies\System.Runtime.Serialization</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Arch.Core.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Arch.Lifecycle.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Annotations.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Compat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Core.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Core.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Core.Utils.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Fragment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.Media.Compat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\Xamarin.Android.Support.v4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="xTile, Version=1.0.7033.16602, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\assemblies\xTile.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Newtonsoft.Json\Dynamic.snk" />
|
||||
<None Include="Newtonsoft.Json\Newtonsoft.Json.ruleset" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Newtonsoft.Json\Newtonsoft.Json.csproj" />
|
||||
<Content Include="SMAPI\icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.572
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mod", "Mod.csproj", "{23B6885E-0282-435B-A854-D49ABF1391D6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{23B6885E-0282-435B-A854-D49ABF1391D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23B6885E-0282-435B-A854-D49ABF1391D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23B6885E-0282-435B-A854-D49ABF1391D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23B6885E-0282-435B-A854-D49ABF1391D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C26EAB4E-1CDD-43D2-98C8-69FEC9AAC386}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewValley;
|
||||
using StardewValley.Menus;
|
||||
using StardewModdingAPI.Framework;
|
||||
using StardewModdingAPI.Framework.Events;
|
||||
using StardewModdingAPI.Framework.ModHelpers;
|
||||
using StardewModdingAPI.Framework.Reflection;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewModdingAPI.Framework.Logging;
|
||||
using System.Threading;
|
||||
using StardewModdingAPI.Internal.ConsoleWriting;
|
||||
using StardewModdingAPI.Toolkit.Serialisation;
|
||||
using StardewModdingAPI.Framework.Input;
|
||||
|
||||
namespace SMDroid
|
||||
{
|
||||
public class ModEntry : ModHooks
|
||||
{
|
||||
|
||||
private SCore core;
|
||||
/// <summary>Whether the next content manager requested by the game will be for <see cref="Game1.content"/>.</summary>
|
||||
private bool NextContentManagerIsMain;
|
||||
/// <summary>SMAPI's content manager.</summary>
|
||||
private ContentCoordinator ContentCore { get; set; }
|
||||
|
||||
|
||||
public ModEntry()
|
||||
{
|
||||
this.core = new SCore("/sdcard/SMDroid/Mods", false);
|
||||
}
|
||||
public override LocalizedContentManager OnGame1_CreateContentManager(IServiceProvider serviceProvider, string rootDirectory)
|
||||
{
|
||||
// Game1._temporaryContent initialising from SGame constructor
|
||||
// NOTE: this method is called before the SGame constructor runs. Don't depend on anything being initialised at this point.
|
||||
if (this.ContentCore == null)
|
||||
{
|
||||
this.ContentCore = new ContentCoordinator(serviceProvider, rootDirectory, Thread.CurrentThread.CurrentUICulture, SGame.ConstructorHack.Monitor, SGame.ConstructorHack.Reflection, SGame.ConstructorHack.JsonHelper, SGame.OnLoadingFirstAsset ?? SGame.ConstructorHack?.OnLoadingFirstAsset);
|
||||
this.NextContentManagerIsMain = true;
|
||||
this.core.RunInteractively(this.ContentCore);
|
||||
return this.ContentCore.CreateGameContentManager("Game1._temporaryContent");
|
||||
}
|
||||
|
||||
// Game1.content initialising from LoadContent
|
||||
if (this.NextContentManagerIsMain)
|
||||
{
|
||||
this.NextContentManagerIsMain = false;
|
||||
return this.ContentCore.MainContentManager;
|
||||
}
|
||||
|
||||
// any other content manager
|
||||
return this.ContentCore.CreateGameContentManager("(generated)");
|
||||
}
|
||||
public override void OnGame1_Update(GameTime time)
|
||||
{
|
||||
this.core.GameInstance.Update(time);
|
||||
}
|
||||
public override void OnGame1_NewDayAfterFade(Action action)
|
||||
{
|
||||
this.core.GameInstance.OnNewDayAfterFade();
|
||||
base.OnGame1_NewDayAfterFade(action);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Mono.Collections.Generic;
|
||||
using MD = Mono.Cecil.Metadata;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public struct ArrayDimension {
|
||||
|
||||
int? lower_bound;
|
||||
int? upper_bound;
|
||||
|
||||
public int? LowerBound {
|
||||
get { return lower_bound; }
|
||||
set { lower_bound = value; }
|
||||
}
|
||||
|
||||
public int? UpperBound {
|
||||
get { return upper_bound; }
|
||||
set { upper_bound = value; }
|
||||
}
|
||||
|
||||
public bool IsSized {
|
||||
get { return lower_bound.HasValue || upper_bound.HasValue; }
|
||||
}
|
||||
|
||||
public ArrayDimension (int? lowerBound, int? upperBound)
|
||||
{
|
||||
this.lower_bound = lowerBound;
|
||||
this.upper_bound = upperBound;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return !IsSized
|
||||
? string.Empty
|
||||
: lower_bound + "..." + upper_bound;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ArrayType : TypeSpecification {
|
||||
|
||||
Collection<ArrayDimension> dimensions;
|
||||
|
||||
public Collection<ArrayDimension> Dimensions {
|
||||
get {
|
||||
if (dimensions != null)
|
||||
return dimensions;
|
||||
|
||||
dimensions = new Collection<ArrayDimension> ();
|
||||
dimensions.Add (new ArrayDimension ());
|
||||
return dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
public int Rank {
|
||||
get { return dimensions == null ? 1 : dimensions.Count; }
|
||||
}
|
||||
|
||||
public bool IsVector {
|
||||
get {
|
||||
if (dimensions == null)
|
||||
return true;
|
||||
|
||||
if (dimensions.Count > 1)
|
||||
return false;
|
||||
|
||||
var dimension = dimensions [0];
|
||||
|
||||
return !dimension.IsSized;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsValueType {
|
||||
get { return false; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return base.Name + Suffix; }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get { return base.FullName + Suffix; }
|
||||
}
|
||||
|
||||
string Suffix {
|
||||
get {
|
||||
if (IsVector)
|
||||
return "[]";
|
||||
|
||||
var suffix = new StringBuilder ();
|
||||
suffix.Append ("[");
|
||||
for (int i = 0; i < dimensions.Count; i++) {
|
||||
if (i > 0)
|
||||
suffix.Append (",");
|
||||
|
||||
suffix.Append (dimensions [i].ToString ());
|
||||
}
|
||||
suffix.Append ("]");
|
||||
|
||||
return suffix.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsArray {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public ArrayType (TypeReference type)
|
||||
: base (type)
|
||||
{
|
||||
Mixin.CheckType (type);
|
||||
this.etype = MD.ElementType.Array;
|
||||
}
|
||||
|
||||
public ArrayType (TypeReference type, int rank)
|
||||
: this (type)
|
||||
{
|
||||
Mixin.CheckType (type);
|
||||
|
||||
if (rank == 1)
|
||||
return;
|
||||
|
||||
dimensions = new Collection<ArrayDimension> (rank);
|
||||
for (int i = 0; i < rank; i++)
|
||||
dimensions.Add (new ArrayDimension ());
|
||||
this.etype = MD.ElementType.Array;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider, IDisposable {
|
||||
|
||||
AssemblyNameDefinition name;
|
||||
|
||||
internal ModuleDefinition main_module;
|
||||
Collection<ModuleDefinition> modules;
|
||||
Collection<CustomAttribute> custom_attributes;
|
||||
Collection<SecurityDeclaration> security_declarations;
|
||||
|
||||
public AssemblyNameDefinition Name {
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
|
||||
public string FullName {
|
||||
get { return name != null ? name.FullName : string.Empty; }
|
||||
}
|
||||
|
||||
public MetadataToken MetadataToken {
|
||||
get { return new MetadataToken (TokenType.Assembly, 1); }
|
||||
set { }
|
||||
}
|
||||
|
||||
public Collection<ModuleDefinition> Modules {
|
||||
get {
|
||||
if (modules != null)
|
||||
return modules;
|
||||
|
||||
if (main_module.HasImage)
|
||||
return main_module.Read (ref modules, this, (_, reader) => reader.ReadModules ());
|
||||
|
||||
return modules = new Collection<ModuleDefinition> (1) { main_module };
|
||||
}
|
||||
}
|
||||
|
||||
public ModuleDefinition MainModule {
|
||||
get { return main_module; }
|
||||
}
|
||||
|
||||
public MethodDefinition EntryPoint {
|
||||
get { return main_module.EntryPoint; }
|
||||
set { main_module.EntryPoint = value; }
|
||||
}
|
||||
|
||||
public bool HasCustomAttributes {
|
||||
get {
|
||||
if (custom_attributes != null)
|
||||
return custom_attributes.Count > 0;
|
||||
|
||||
return this.GetHasCustomAttributes (main_module);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttribute> CustomAttributes {
|
||||
get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, main_module)); }
|
||||
}
|
||||
|
||||
public bool HasSecurityDeclarations {
|
||||
get {
|
||||
if (security_declarations != null)
|
||||
return security_declarations.Count > 0;
|
||||
|
||||
return this.GetHasSecurityDeclarations (main_module);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<SecurityDeclaration> SecurityDeclarations {
|
||||
get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, main_module)); }
|
||||
}
|
||||
|
||||
internal AssemblyDefinition ()
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (this.modules == null) {
|
||||
main_module.Dispose ();
|
||||
return;
|
||||
}
|
||||
|
||||
var modules = this.Modules;
|
||||
for (int i = 0; i < modules.Count; i++)
|
||||
modules [i].Dispose ();
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleKind kind)
|
||||
{
|
||||
return CreateAssembly (assemblyName, moduleName, new ModuleParameters { Kind = kind });
|
||||
}
|
||||
|
||||
public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleParameters parameters)
|
||||
{
|
||||
if (assemblyName == null)
|
||||
throw new ArgumentNullException ("assemblyName");
|
||||
if (moduleName == null)
|
||||
throw new ArgumentNullException ("moduleName");
|
||||
Mixin.CheckParameters (parameters);
|
||||
if (parameters.Kind == ModuleKind.NetModule)
|
||||
throw new ArgumentException ("kind");
|
||||
|
||||
var assembly = ModuleDefinition.CreateModule (moduleName, parameters).Assembly;
|
||||
assembly.Name = assemblyName;
|
||||
|
||||
return assembly;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static AssemblyDefinition ReadAssembly (string fileName)
|
||||
{
|
||||
return ReadAssembly (ModuleDefinition.ReadModule (fileName));
|
||||
}
|
||||
|
||||
public static AssemblyDefinition ReadAssembly (string fileName, ReaderParameters parameters)
|
||||
{
|
||||
return ReadAssembly (ModuleDefinition.ReadModule (fileName, parameters));
|
||||
}
|
||||
|
||||
public static AssemblyDefinition ReadAssembly (Stream stream)
|
||||
{
|
||||
return ReadAssembly (ModuleDefinition.ReadModule (stream));
|
||||
}
|
||||
|
||||
public static AssemblyDefinition ReadAssembly (Stream stream, ReaderParameters parameters)
|
||||
{
|
||||
return ReadAssembly (ModuleDefinition.ReadModule (stream, parameters));
|
||||
}
|
||||
|
||||
static AssemblyDefinition ReadAssembly (ModuleDefinition module)
|
||||
{
|
||||
var assembly = module.Assembly;
|
||||
if (assembly == null)
|
||||
throw new ArgumentException ();
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
public void Write (string fileName)
|
||||
{
|
||||
Write (fileName, new WriterParameters ());
|
||||
}
|
||||
|
||||
public void Write (string fileName, WriterParameters parameters)
|
||||
{
|
||||
main_module.Write (fileName, parameters);
|
||||
}
|
||||
|
||||
public void Write ()
|
||||
{
|
||||
main_module.Write ();
|
||||
}
|
||||
|
||||
public void Write (WriterParameters parameters)
|
||||
{
|
||||
main_module.Write (parameters);
|
||||
}
|
||||
|
||||
public void Write (Stream stream)
|
||||
{
|
||||
Write (stream, new WriterParameters ());
|
||||
}
|
||||
|
||||
public void Write (Stream stream, WriterParameters parameters)
|
||||
{
|
||||
main_module.Write (stream, parameters);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return this.FullName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
[Flags]
|
||||
public enum AssemblyAttributes : uint {
|
||||
PublicKey = 0x0001,
|
||||
SideBySideCompatible = 0x0000,
|
||||
Retargetable = 0x0100,
|
||||
WindowsRuntime = 0x0200,
|
||||
DisableJITCompileOptimizer = 0x4000,
|
||||
EnableJITCompileTracking = 0x8000,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public enum AssemblyHashAlgorithm : uint {
|
||||
None = 0x0000,
|
||||
Reserved = 0x8003, // MD5
|
||||
SHA1 = 0x8004
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class AssemblyLinkedResource : Resource {
|
||||
|
||||
AssemblyNameReference reference;
|
||||
|
||||
public AssemblyNameReference Assembly {
|
||||
get { return reference; }
|
||||
set { reference = value; }
|
||||
}
|
||||
|
||||
public override ResourceType ResourceType {
|
||||
get { return ResourceType.AssemblyLinked; }
|
||||
}
|
||||
|
||||
public AssemblyLinkedResource (string name, ManifestResourceAttributes flags)
|
||||
: base (name, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public AssemblyLinkedResource (string name, ManifestResourceAttributes flags, AssemblyNameReference reference)
|
||||
: base (name, flags)
|
||||
{
|
||||
this.reference = reference;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class AssemblyNameDefinition : AssemblyNameReference {
|
||||
|
||||
public override byte [] Hash {
|
||||
get { return Empty<byte>.Array; }
|
||||
}
|
||||
|
||||
internal AssemblyNameDefinition ()
|
||||
{
|
||||
this.token = new MetadataToken (TokenType.Assembly, 1);
|
||||
}
|
||||
|
||||
public AssemblyNameDefinition (string name, Version version)
|
||||
: base (name, version)
|
||||
{
|
||||
this.token = new MetadataToken (TokenType.Assembly, 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public class AssemblyNameReference : IMetadataScope {
|
||||
|
||||
string name;
|
||||
string culture;
|
||||
Version version;
|
||||
uint attributes;
|
||||
byte [] public_key;
|
||||
byte [] public_key_token;
|
||||
AssemblyHashAlgorithm hash_algorithm;
|
||||
byte [] hash;
|
||||
|
||||
internal MetadataToken token;
|
||||
|
||||
string full_name;
|
||||
|
||||
public string Name {
|
||||
get { return name; }
|
||||
set {
|
||||
name = value;
|
||||
full_name = null;
|
||||
}
|
||||
}
|
||||
|
||||
public string Culture {
|
||||
get { return culture; }
|
||||
set {
|
||||
culture = value;
|
||||
full_name = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Version Version {
|
||||
get { return version; }
|
||||
set {
|
||||
version = Mixin.CheckVersion (value);
|
||||
full_name = null;
|
||||
}
|
||||
}
|
||||
|
||||
public AssemblyAttributes Attributes {
|
||||
get { return (AssemblyAttributes) attributes; }
|
||||
set { attributes = (uint) value; }
|
||||
}
|
||||
|
||||
public bool HasPublicKey {
|
||||
get { return attributes.GetAttributes ((uint) AssemblyAttributes.PublicKey); }
|
||||
set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.PublicKey, value); }
|
||||
}
|
||||
|
||||
public bool IsSideBySideCompatible {
|
||||
get { return attributes.GetAttributes ((uint) AssemblyAttributes.SideBySideCompatible); }
|
||||
set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.SideBySideCompatible, value); }
|
||||
}
|
||||
|
||||
public bool IsRetargetable {
|
||||
get { return attributes.GetAttributes ((uint) AssemblyAttributes.Retargetable); }
|
||||
set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.Retargetable, value); }
|
||||
}
|
||||
|
||||
public bool IsWindowsRuntime {
|
||||
get { return attributes.GetAttributes ((uint) AssemblyAttributes.WindowsRuntime); }
|
||||
set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.WindowsRuntime, value); }
|
||||
}
|
||||
|
||||
public byte [] PublicKey {
|
||||
get { return public_key ?? Empty<byte>.Array; }
|
||||
set {
|
||||
public_key = value;
|
||||
HasPublicKey = !public_key.IsNullOrEmpty ();
|
||||
public_key_token = Empty<byte>.Array;
|
||||
full_name = null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte [] PublicKeyToken {
|
||||
get {
|
||||
if (public_key_token.IsNullOrEmpty () && !public_key.IsNullOrEmpty ()) {
|
||||
var hash = HashPublicKey ();
|
||||
// we need the last 8 bytes in reverse order
|
||||
var local_public_key_token = new byte [8];
|
||||
Array.Copy (hash, (hash.Length - 8), local_public_key_token, 0, 8);
|
||||
Array.Reverse (local_public_key_token, 0, 8);
|
||||
public_key_token = local_public_key_token; // publish only once finished (required for thread-safety)
|
||||
}
|
||||
return public_key_token ?? Empty<byte>.Array;
|
||||
}
|
||||
set {
|
||||
public_key_token = value;
|
||||
full_name = null;
|
||||
}
|
||||
}
|
||||
|
||||
byte [] HashPublicKey ()
|
||||
{
|
||||
HashAlgorithm algorithm;
|
||||
|
||||
switch (hash_algorithm) {
|
||||
case AssemblyHashAlgorithm.Reserved:
|
||||
algorithm = MD5.Create ();
|
||||
break;
|
||||
default:
|
||||
// None default to SHA1
|
||||
algorithm = SHA1.Create ();
|
||||
break;
|
||||
}
|
||||
|
||||
using (algorithm)
|
||||
return algorithm.ComputeHash (public_key);
|
||||
}
|
||||
|
||||
public virtual MetadataScopeType MetadataScopeType {
|
||||
get { return MetadataScopeType.AssemblyNameReference; }
|
||||
}
|
||||
|
||||
public string FullName {
|
||||
get {
|
||||
if (full_name != null)
|
||||
return full_name;
|
||||
|
||||
const string sep = ", ";
|
||||
|
||||
var builder = new StringBuilder ();
|
||||
builder.Append (name);
|
||||
builder.Append (sep);
|
||||
builder.Append ("Version=");
|
||||
builder.Append (version.ToString (fieldCount: 4));
|
||||
builder.Append (sep);
|
||||
builder.Append ("Culture=");
|
||||
builder.Append (string.IsNullOrEmpty (culture) ? "neutral" : culture);
|
||||
builder.Append (sep);
|
||||
builder.Append ("PublicKeyToken=");
|
||||
|
||||
var pk_token = PublicKeyToken;
|
||||
if (!pk_token.IsNullOrEmpty () && pk_token.Length > 0) {
|
||||
for (int i = 0 ; i < pk_token.Length ; i++) {
|
||||
builder.Append (pk_token [i].ToString ("x2"));
|
||||
}
|
||||
} else
|
||||
builder.Append ("null");
|
||||
|
||||
if (IsRetargetable) {
|
||||
builder.Append (sep);
|
||||
builder.Append ("Retargetable=Yes");
|
||||
}
|
||||
|
||||
return full_name = builder.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public static AssemblyNameReference Parse (string fullName)
|
||||
{
|
||||
if (fullName == null)
|
||||
throw new ArgumentNullException ("fullName");
|
||||
if (fullName.Length == 0)
|
||||
throw new ArgumentException ("Name can not be empty");
|
||||
|
||||
var name = new AssemblyNameReference ();
|
||||
var tokens = fullName.Split (',');
|
||||
for (int i = 0; i < tokens.Length; i++) {
|
||||
var token = tokens [i].Trim ();
|
||||
|
||||
if (i == 0) {
|
||||
name.Name = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
var parts = token.Split ('=');
|
||||
if (parts.Length != 2)
|
||||
throw new ArgumentException ("Malformed name");
|
||||
|
||||
switch (parts [0].ToLowerInvariant ()) {
|
||||
case "version":
|
||||
name.Version = new Version (parts [1]);
|
||||
break;
|
||||
case "culture":
|
||||
name.Culture = parts [1] == "neutral" ? "" : parts [1];
|
||||
break;
|
||||
case "publickeytoken":
|
||||
var pk_token = parts [1];
|
||||
if (pk_token == "null")
|
||||
break;
|
||||
|
||||
name.PublicKeyToken = new byte [pk_token.Length / 2];
|
||||
for (int j = 0; j < name.PublicKeyToken.Length; j++)
|
||||
name.PublicKeyToken [j] = Byte.Parse (pk_token.Substring (j * 2, 2), NumberStyles.HexNumber);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public AssemblyHashAlgorithm HashAlgorithm {
|
||||
get { return hash_algorithm; }
|
||||
set { hash_algorithm = value; }
|
||||
}
|
||||
|
||||
public virtual byte [] Hash {
|
||||
get { return hash; }
|
||||
set { hash = value; }
|
||||
}
|
||||
|
||||
public MetadataToken MetadataToken {
|
||||
get { return token; }
|
||||
set { token = value; }
|
||||
}
|
||||
|
||||
internal AssemblyNameReference ()
|
||||
{
|
||||
this.version = Mixin.ZeroVersion;
|
||||
this.token = new MetadataToken (TokenType.AssemblyRef);
|
||||
}
|
||||
|
||||
public AssemblyNameReference (string name, Version version)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
|
||||
this.name = name;
|
||||
this.version = Mixin.CheckVersion (version);
|
||||
this.hash_algorithm = AssemblyHashAlgorithm.None;
|
||||
this.token = new MetadataToken (TokenType.AssemblyRef);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return this.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
partial class Mixin {
|
||||
|
||||
public static Version ZeroVersion = new Version (0, 0, 0 ,0);
|
||||
|
||||
public static Version CheckVersion (Version version)
|
||||
{
|
||||
if (version == null)
|
||||
return ZeroVersion;
|
||||
|
||||
if (version.Build == -1)
|
||||
return new Version (version.Major, version.Minor, 0, 0);
|
||||
|
||||
if (version.Revision == -1)
|
||||
return new Version (version.Major, version.Minor, version.Build, 0);
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,410 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference);
|
||||
|
||||
public sealed class AssemblyResolveEventArgs : EventArgs {
|
||||
|
||||
readonly AssemblyNameReference reference;
|
||||
|
||||
public AssemblyNameReference AssemblyReference {
|
||||
get { return reference; }
|
||||
}
|
||||
|
||||
public AssemblyResolveEventArgs (AssemblyNameReference reference)
|
||||
{
|
||||
this.reference = reference;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NET_CORE
|
||||
[Serializable]
|
||||
#endif
|
||||
public sealed class AssemblyResolutionException : FileNotFoundException {
|
||||
|
||||
readonly AssemblyNameReference reference;
|
||||
|
||||
public AssemblyNameReference AssemblyReference {
|
||||
get { return reference; }
|
||||
}
|
||||
|
||||
public AssemblyResolutionException (AssemblyNameReference reference)
|
||||
: this (reference, null)
|
||||
{
|
||||
}
|
||||
|
||||
public AssemblyResolutionException (AssemblyNameReference reference, Exception innerException)
|
||||
: base (string.Format ("Failed to resolve assembly: '{0}'", reference), innerException)
|
||||
{
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
#if !NET_CORE
|
||||
AssemblyResolutionException (
|
||||
System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract class BaseAssemblyResolver : IAssemblyResolver {
|
||||
|
||||
static readonly bool on_mono = Type.GetType ("Mono.Runtime") != null;
|
||||
|
||||
readonly Collection<string> directories;
|
||||
|
||||
#if NET_CORE
|
||||
// Maps file names of available trusted platform assemblies to their full paths.
|
||||
// Internal for testing.
|
||||
internal static readonly Lazy<Dictionary<string, string>> TrustedPlatformAssemblies = new Lazy<Dictionary<string, string>> (CreateTrustedPlatformAssemblyMap);
|
||||
#else
|
||||
Collection<string> gac_paths;
|
||||
#endif
|
||||
|
||||
public void AddSearchDirectory (string directory)
|
||||
{
|
||||
directories.Add (directory);
|
||||
}
|
||||
|
||||
public void RemoveSearchDirectory (string directory)
|
||||
{
|
||||
directories.Remove (directory);
|
||||
}
|
||||
|
||||
public string [] GetSearchDirectories ()
|
||||
{
|
||||
var directories = new string [this.directories.size];
|
||||
Array.Copy (this.directories.items, directories, directories.Length);
|
||||
return directories;
|
||||
}
|
||||
|
||||
public event AssemblyResolveEventHandler ResolveFailure;
|
||||
|
||||
protected BaseAssemblyResolver ()
|
||||
{
|
||||
directories = new Collection<string> (2) { ".", "bin" };
|
||||
}
|
||||
|
||||
AssemblyDefinition GetAssembly (string file, ReaderParameters parameters)
|
||||
{
|
||||
if (parameters.AssemblyResolver == null)
|
||||
parameters.AssemblyResolver = this;
|
||||
|
||||
return ModuleDefinition.ReadModule (file, parameters).Assembly;
|
||||
}
|
||||
|
||||
public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
|
||||
{
|
||||
return Resolve (name, new ReaderParameters ());
|
||||
}
|
||||
|
||||
public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
Mixin.CheckParameters (parameters);
|
||||
|
||||
var assembly = SearchDirectory (name, directories, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
|
||||
if (name.IsRetargetable) {
|
||||
// if the reference is retargetable, zero it
|
||||
name = new AssemblyNameReference (name.Name, Mixin.ZeroVersion) {
|
||||
PublicKeyToken = Empty<byte>.Array,
|
||||
};
|
||||
}
|
||||
|
||||
#if NET_CORE
|
||||
assembly = SearchTrustedPlatformAssemblies (name, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
#else
|
||||
var framework_dir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName);
|
||||
var framework_dirs = on_mono
|
||||
? new [] { framework_dir, Path.Combine (framework_dir, "Facades") }
|
||||
: new [] { framework_dir };
|
||||
|
||||
if (IsZero (name.Version)) {
|
||||
assembly = SearchDirectory (name, framework_dirs, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
}
|
||||
|
||||
if (name.Name == "mscorlib") {
|
||||
assembly = GetCorlib (name, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
}
|
||||
|
||||
assembly = GetAssemblyInGac (name, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
|
||||
assembly = SearchDirectory (name, framework_dirs, parameters);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
#endif
|
||||
if (ResolveFailure != null) {
|
||||
assembly = ResolveFailure (this, name);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
}
|
||||
|
||||
throw new AssemblyResolutionException (name);
|
||||
}
|
||||
|
||||
#if NET_CORE
|
||||
AssemblyDefinition SearchTrustedPlatformAssemblies (AssemblyNameReference name, ReaderParameters parameters)
|
||||
{
|
||||
if (name.IsWindowsRuntime)
|
||||
return null;
|
||||
|
||||
if (TrustedPlatformAssemblies.Value.TryGetValue (name.Name, out string path))
|
||||
return GetAssembly (path, parameters);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Dictionary<string, string> CreateTrustedPlatformAssemblyMap ()
|
||||
{
|
||||
var result = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
string paths;
|
||||
|
||||
try {
|
||||
// AppContext is only available on platforms that implement .NET Standard 1.6
|
||||
var appContextType = Type.GetType ("System.AppContext, System.AppContext, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
||||
var getData = appContextType?.GetTypeInfo ().GetDeclaredMethod ("GetData");
|
||||
paths = (string) getData?.Invoke (null, new [] { "TRUSTED_PLATFORM_ASSEMBLIES" });
|
||||
} catch {
|
||||
paths = null;
|
||||
}
|
||||
|
||||
if (paths == null)
|
||||
return result;
|
||||
|
||||
foreach (var path in paths.Split (Path.PathSeparator))
|
||||
if (string.Equals (Path.GetExtension (path), ".dll", StringComparison.OrdinalIgnoreCase))
|
||||
result [Path.GetFileNameWithoutExtension (path)] = path;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected virtual AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable<string> directories, ReaderParameters parameters)
|
||||
{
|
||||
var extensions = name.IsWindowsRuntime ? new [] { ".winmd", ".dll" } : new [] { ".exe", ".dll" };
|
||||
foreach (var directory in directories) {
|
||||
foreach (var extension in extensions) {
|
||||
string file = Path.Combine (directory, name.Name + extension);
|
||||
if (!File.Exists (file))
|
||||
continue;
|
||||
try {
|
||||
return GetAssembly (file, parameters);
|
||||
} catch (System.BadImageFormatException) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool IsZero (Version version)
|
||||
{
|
||||
return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
|
||||
}
|
||||
|
||||
#if !NET_CORE
|
||||
AssemblyDefinition GetCorlib (AssemblyNameReference reference, ReaderParameters parameters)
|
||||
{
|
||||
var version = reference.Version;
|
||||
var corlib = typeof (object).Assembly.GetName ();
|
||||
if (corlib.Version == version || IsZero (version))
|
||||
return GetAssembly (typeof (object).Module.FullyQualifiedName, parameters);
|
||||
|
||||
var path = Directory.GetParent (
|
||||
Directory.GetParent (
|
||||
typeof (object).Module.FullyQualifiedName).FullName
|
||||
).FullName;
|
||||
|
||||
if (on_mono) {
|
||||
if (version.Major == 1)
|
||||
path = Path.Combine (path, "1.0");
|
||||
else if (version.Major == 2) {
|
||||
if (version.MajorRevision == 5)
|
||||
path = Path.Combine (path, "2.1");
|
||||
else
|
||||
path = Path.Combine (path, "2.0");
|
||||
} else if (version.Major == 4)
|
||||
path = Path.Combine (path, "4.0");
|
||||
else
|
||||
throw new NotSupportedException ("Version not supported: " + version);
|
||||
} else {
|
||||
switch (version.Major) {
|
||||
case 1:
|
||||
if (version.MajorRevision == 3300)
|
||||
path = Path.Combine (path, "v1.0.3705");
|
||||
else
|
||||
path = Path.Combine (path, "v1.1.4322");
|
||||
break;
|
||||
case 2:
|
||||
path = Path.Combine (path, "v2.0.50727");
|
||||
break;
|
||||
case 4:
|
||||
path = Path.Combine (path, "v4.0.30319");
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException ("Version not supported: " + version);
|
||||
}
|
||||
}
|
||||
|
||||
var file = Path.Combine (path, "mscorlib.dll");
|
||||
if (File.Exists (file))
|
||||
return GetAssembly (file, parameters);
|
||||
|
||||
if (on_mono && Directory.Exists (path + "-api")) {
|
||||
file = Path.Combine (path + "-api", "mscorlib.dll");
|
||||
if (File.Exists (file))
|
||||
return GetAssembly (file, parameters);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Collection<string> GetGacPaths ()
|
||||
{
|
||||
if (on_mono)
|
||||
return GetDefaultMonoGacPaths ();
|
||||
|
||||
var paths = new Collection<string> (2);
|
||||
var windir = Environment.GetEnvironmentVariable ("WINDIR");
|
||||
if (windir == null)
|
||||
return paths;
|
||||
|
||||
paths.Add (Path.Combine (windir, "assembly"));
|
||||
paths.Add (Path.Combine (windir, Path.Combine ("Microsoft.NET", "assembly")));
|
||||
return paths;
|
||||
}
|
||||
|
||||
static Collection<string> GetDefaultMonoGacPaths ()
|
||||
{
|
||||
var paths = new Collection<string> (1);
|
||||
var gac = GetCurrentMonoGac ();
|
||||
if (gac != null)
|
||||
paths.Add (gac);
|
||||
|
||||
var gac_paths_env = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX");
|
||||
if (string.IsNullOrEmpty (gac_paths_env))
|
||||
return paths;
|
||||
|
||||
var prefixes = gac_paths_env.Split (Path.PathSeparator);
|
||||
foreach (var prefix in prefixes) {
|
||||
if (string.IsNullOrEmpty (prefix))
|
||||
continue;
|
||||
|
||||
var gac_path = Path.Combine (Path.Combine (Path.Combine (prefix, "lib"), "mono"), "gac");
|
||||
if (Directory.Exists (gac_path) && !paths.Contains (gac))
|
||||
paths.Add (gac_path);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
static string GetCurrentMonoGac ()
|
||||
{
|
||||
return Path.Combine (
|
||||
Directory.GetParent (
|
||||
Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName)).FullName,
|
||||
"gac");
|
||||
}
|
||||
|
||||
AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters)
|
||||
{
|
||||
if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
|
||||
return null;
|
||||
|
||||
if (gac_paths == null)
|
||||
gac_paths = GetGacPaths ();
|
||||
|
||||
if (on_mono)
|
||||
return GetAssemblyInMonoGac (reference, parameters);
|
||||
|
||||
return GetAssemblyInNetGac (reference, parameters);
|
||||
}
|
||||
|
||||
AssemblyDefinition GetAssemblyInMonoGac (AssemblyNameReference reference, ReaderParameters parameters)
|
||||
{
|
||||
for (int i = 0; i < gac_paths.Count; i++) {
|
||||
var gac_path = gac_paths [i];
|
||||
var file = GetAssemblyFile (reference, string.Empty, gac_path);
|
||||
if (File.Exists (file))
|
||||
return GetAssembly (file, parameters);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
AssemblyDefinition GetAssemblyInNetGac (AssemblyNameReference reference, ReaderParameters parameters)
|
||||
{
|
||||
var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" };
|
||||
var prefixes = new [] { string.Empty, "v4.0_" };
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < gacs.Length; j++) {
|
||||
var gac = Path.Combine (gac_paths [i], gacs [j]);
|
||||
var file = GetAssemblyFile (reference, prefixes [i], gac);
|
||||
if (Directory.Exists (gac) && File.Exists (file))
|
||||
return GetAssembly (file, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
static string GetAssemblyFile (AssemblyNameReference reference, string prefix, string gac)
|
||||
{
|
||||
var gac_folder = new StringBuilder ()
|
||||
.Append (prefix)
|
||||
.Append (reference.Version)
|
||||
.Append ("__");
|
||||
|
||||
for (int i = 0; i < reference.PublicKeyToken.Length; i++)
|
||||
gac_folder.Append (reference.PublicKeyToken [i].ToString ("x2"));
|
||||
|
||||
return Path.Combine (
|
||||
Path.Combine (
|
||||
Path.Combine (gac, reference.Name), gac_folder.ToString ()),
|
||||
reference.Name + ".dll");
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class CallSite : IMethodSignature {
|
||||
|
||||
readonly MethodReference signature;
|
||||
|
||||
public bool HasThis {
|
||||
get { return signature.HasThis; }
|
||||
set { signature.HasThis = value; }
|
||||
}
|
||||
|
||||
public bool ExplicitThis {
|
||||
get { return signature.ExplicitThis; }
|
||||
set { signature.ExplicitThis = value; }
|
||||
}
|
||||
|
||||
public MethodCallingConvention CallingConvention {
|
||||
get { return signature.CallingConvention; }
|
||||
set { signature.CallingConvention = value; }
|
||||
}
|
||||
|
||||
public bool HasParameters {
|
||||
get { return signature.HasParameters; }
|
||||
}
|
||||
|
||||
public Collection<ParameterDefinition> Parameters {
|
||||
get { return signature.Parameters; }
|
||||
}
|
||||
|
||||
public TypeReference ReturnType {
|
||||
get { return signature.MethodReturnType.ReturnType; }
|
||||
set { signature.MethodReturnType.ReturnType = value; }
|
||||
}
|
||||
|
||||
public MethodReturnType MethodReturnType {
|
||||
get { return signature.MethodReturnType; }
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get { return string.Empty; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public string Namespace {
|
||||
get { return string.Empty; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public ModuleDefinition Module {
|
||||
get { return ReturnType.Module; }
|
||||
}
|
||||
|
||||
public IMetadataScope Scope {
|
||||
get { return signature.ReturnType.Scope; }
|
||||
}
|
||||
|
||||
public MetadataToken MetadataToken {
|
||||
get { return signature.token; }
|
||||
set { signature.token = value; }
|
||||
}
|
||||
|
||||
public string FullName {
|
||||
get {
|
||||
var signature = new StringBuilder ();
|
||||
signature.Append (ReturnType.FullName);
|
||||
this.MethodSignatureFullName (signature);
|
||||
return signature.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
internal CallSite ()
|
||||
{
|
||||
this.signature = new MethodReference ();
|
||||
this.signature.token = new MetadataToken (TokenType.Signature, 0);
|
||||
}
|
||||
|
||||
public CallSite (TypeReference returnType)
|
||||
: this ()
|
||||
{
|
||||
if (returnType == null)
|
||||
throw new ArgumentNullException ("returnType");
|
||||
|
||||
this.signature.ReturnType = returnType;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return FullName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public enum Code {
|
||||
Nop,
|
||||
Break,
|
||||
Ldarg_0,
|
||||
Ldarg_1,
|
||||
Ldarg_2,
|
||||
Ldarg_3,
|
||||
Ldloc_0,
|
||||
Ldloc_1,
|
||||
Ldloc_2,
|
||||
Ldloc_3,
|
||||
Stloc_0,
|
||||
Stloc_1,
|
||||
Stloc_2,
|
||||
Stloc_3,
|
||||
Ldarg_S,
|
||||
Ldarga_S,
|
||||
Starg_S,
|
||||
Ldloc_S,
|
||||
Ldloca_S,
|
||||
Stloc_S,
|
||||
Ldnull,
|
||||
Ldc_I4_M1,
|
||||
Ldc_I4_0,
|
||||
Ldc_I4_1,
|
||||
Ldc_I4_2,
|
||||
Ldc_I4_3,
|
||||
Ldc_I4_4,
|
||||
Ldc_I4_5,
|
||||
Ldc_I4_6,
|
||||
Ldc_I4_7,
|
||||
Ldc_I4_8,
|
||||
Ldc_I4_S,
|
||||
Ldc_I4,
|
||||
Ldc_I8,
|
||||
Ldc_R4,
|
||||
Ldc_R8,
|
||||
Dup,
|
||||
Pop,
|
||||
Jmp,
|
||||
Call,
|
||||
Calli,
|
||||
Ret,
|
||||
Br_S,
|
||||
Brfalse_S,
|
||||
Brtrue_S,
|
||||
Beq_S,
|
||||
Bge_S,
|
||||
Bgt_S,
|
||||
Ble_S,
|
||||
Blt_S,
|
||||
Bne_Un_S,
|
||||
Bge_Un_S,
|
||||
Bgt_Un_S,
|
||||
Ble_Un_S,
|
||||
Blt_Un_S,
|
||||
Br,
|
||||
Brfalse,
|
||||
Brtrue,
|
||||
Beq,
|
||||
Bge,
|
||||
Bgt,
|
||||
Ble,
|
||||
Blt,
|
||||
Bne_Un,
|
||||
Bge_Un,
|
||||
Bgt_Un,
|
||||
Ble_Un,
|
||||
Blt_Un,
|
||||
Switch,
|
||||
Ldind_I1,
|
||||
Ldind_U1,
|
||||
Ldind_I2,
|
||||
Ldind_U2,
|
||||
Ldind_I4,
|
||||
Ldind_U4,
|
||||
Ldind_I8,
|
||||
Ldind_I,
|
||||
Ldind_R4,
|
||||
Ldind_R8,
|
||||
Ldind_Ref,
|
||||
Stind_Ref,
|
||||
Stind_I1,
|
||||
Stind_I2,
|
||||
Stind_I4,
|
||||
Stind_I8,
|
||||
Stind_R4,
|
||||
Stind_R8,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Div_Un,
|
||||
Rem,
|
||||
Rem_Un,
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Shl,
|
||||
Shr,
|
||||
Shr_Un,
|
||||
Neg,
|
||||
Not,
|
||||
Conv_I1,
|
||||
Conv_I2,
|
||||
Conv_I4,
|
||||
Conv_I8,
|
||||
Conv_R4,
|
||||
Conv_R8,
|
||||
Conv_U4,
|
||||
Conv_U8,
|
||||
Callvirt,
|
||||
Cpobj,
|
||||
Ldobj,
|
||||
Ldstr,
|
||||
Newobj,
|
||||
Castclass,
|
||||
Isinst,
|
||||
Conv_R_Un,
|
||||
Unbox,
|
||||
Throw,
|
||||
Ldfld,
|
||||
Ldflda,
|
||||
Stfld,
|
||||
Ldsfld,
|
||||
Ldsflda,
|
||||
Stsfld,
|
||||
Stobj,
|
||||
Conv_Ovf_I1_Un,
|
||||
Conv_Ovf_I2_Un,
|
||||
Conv_Ovf_I4_Un,
|
||||
Conv_Ovf_I8_Un,
|
||||
Conv_Ovf_U1_Un,
|
||||
Conv_Ovf_U2_Un,
|
||||
Conv_Ovf_U4_Un,
|
||||
Conv_Ovf_U8_Un,
|
||||
Conv_Ovf_I_Un,
|
||||
Conv_Ovf_U_Un,
|
||||
Box,
|
||||
Newarr,
|
||||
Ldlen,
|
||||
Ldelema,
|
||||
Ldelem_I1,
|
||||
Ldelem_U1,
|
||||
Ldelem_I2,
|
||||
Ldelem_U2,
|
||||
Ldelem_I4,
|
||||
Ldelem_U4,
|
||||
Ldelem_I8,
|
||||
Ldelem_I,
|
||||
Ldelem_R4,
|
||||
Ldelem_R8,
|
||||
Ldelem_Ref,
|
||||
Stelem_I,
|
||||
Stelem_I1,
|
||||
Stelem_I2,
|
||||
Stelem_I4,
|
||||
Stelem_I8,
|
||||
Stelem_R4,
|
||||
Stelem_R8,
|
||||
Stelem_Ref,
|
||||
Ldelem_Any,
|
||||
Stelem_Any,
|
||||
Unbox_Any,
|
||||
Conv_Ovf_I1,
|
||||
Conv_Ovf_U1,
|
||||
Conv_Ovf_I2,
|
||||
Conv_Ovf_U2,
|
||||
Conv_Ovf_I4,
|
||||
Conv_Ovf_U4,
|
||||
Conv_Ovf_I8,
|
||||
Conv_Ovf_U8,
|
||||
Refanyval,
|
||||
Ckfinite,
|
||||
Mkrefany,
|
||||
Ldtoken,
|
||||
Conv_U2,
|
||||
Conv_U1,
|
||||
Conv_I,
|
||||
Conv_Ovf_I,
|
||||
Conv_Ovf_U,
|
||||
Add_Ovf,
|
||||
Add_Ovf_Un,
|
||||
Mul_Ovf,
|
||||
Mul_Ovf_Un,
|
||||
Sub_Ovf,
|
||||
Sub_Ovf_Un,
|
||||
Endfinally,
|
||||
Leave,
|
||||
Leave_S,
|
||||
Stind_I,
|
||||
Conv_U,
|
||||
Arglist,
|
||||
Ceq,
|
||||
Cgt,
|
||||
Cgt_Un,
|
||||
Clt,
|
||||
Clt_Un,
|
||||
Ldftn,
|
||||
Ldvirtftn,
|
||||
Ldarg,
|
||||
Ldarga,
|
||||
Starg,
|
||||
Ldloc,
|
||||
Ldloca,
|
||||
Stloc,
|
||||
Localloc,
|
||||
Endfilter,
|
||||
Unaligned,
|
||||
Volatile,
|
||||
Tail,
|
||||
Initobj,
|
||||
Constrained,
|
||||
Cpblk,
|
||||
Initblk,
|
||||
No,
|
||||
Rethrow,
|
||||
Sizeof,
|
||||
Refanytype,
|
||||
Readonly,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,671 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
using Mono.Cecil.PE;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
using RVA = System.UInt32;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
sealed class CodeReader : BinaryStreamReader {
|
||||
|
||||
readonly internal MetadataReader reader;
|
||||
|
||||
int start;
|
||||
|
||||
MethodDefinition method;
|
||||
MethodBody body;
|
||||
|
||||
int Offset {
|
||||
get { return Position - start; }
|
||||
}
|
||||
|
||||
public CodeReader (MetadataReader reader)
|
||||
: base (reader.image.Stream.value)
|
||||
{
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public int MoveTo (MethodDefinition method)
|
||||
{
|
||||
this.method = method;
|
||||
this.reader.context = method;
|
||||
var position = this.Position;
|
||||
this.Position = (int) reader.image.ResolveVirtualAddress ((uint) method.RVA);
|
||||
return position;
|
||||
}
|
||||
|
||||
public void MoveBackTo (int position)
|
||||
{
|
||||
this.reader.context = null;
|
||||
this.Position = position;
|
||||
}
|
||||
|
||||
public MethodBody ReadMethodBody (MethodDefinition method)
|
||||
{
|
||||
var position = MoveTo (method);
|
||||
this.body = new MethodBody (method);
|
||||
|
||||
ReadMethodBody ();
|
||||
|
||||
MoveBackTo (position);
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public int ReadCodeSize (MethodDefinition method)
|
||||
{
|
||||
var position = MoveTo (method);
|
||||
|
||||
var code_size = ReadCodeSize ();
|
||||
|
||||
MoveBackTo (position);
|
||||
return code_size;
|
||||
}
|
||||
|
||||
int ReadCodeSize ()
|
||||
{
|
||||
var flags = ReadByte ();
|
||||
switch (flags & 0x3) {
|
||||
case 0x2: // tiny
|
||||
return flags >> 2;
|
||||
case 0x3: // fat
|
||||
Advance (-1 + 2 + 2); // go back, 2 bytes flags, 2 bytes stack size
|
||||
return (int) ReadUInt32 ();
|
||||
default:
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadMethodBody ()
|
||||
{
|
||||
var flags = ReadByte ();
|
||||
switch (flags & 0x3) {
|
||||
case 0x2: // tiny
|
||||
body.code_size = flags >> 2;
|
||||
body.MaxStackSize = 8;
|
||||
ReadCode ();
|
||||
break;
|
||||
case 0x3: // fat
|
||||
Advance (-1);
|
||||
ReadFatMethod ();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
var symbol_reader = reader.module.symbol_reader;
|
||||
|
||||
if (symbol_reader != null && method.debug_info == null)
|
||||
method.debug_info = symbol_reader.Read (method);
|
||||
|
||||
if (method.debug_info != null)
|
||||
ReadDebugInfo ();
|
||||
}
|
||||
|
||||
void ReadFatMethod ()
|
||||
{
|
||||
var flags = ReadUInt16 ();
|
||||
body.max_stack_size = ReadUInt16 ();
|
||||
body.code_size = (int) ReadUInt32 ();
|
||||
body.local_var_token = new MetadataToken (ReadUInt32 ());
|
||||
body.init_locals = (flags & 0x10) != 0;
|
||||
|
||||
if (body.local_var_token.RID != 0)
|
||||
body.variables = ReadVariables (body.local_var_token);
|
||||
|
||||
ReadCode ();
|
||||
|
||||
if ((flags & 0x8) != 0)
|
||||
ReadSection ();
|
||||
}
|
||||
|
||||
public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
|
||||
{
|
||||
var position = reader.position;
|
||||
var variables = reader.ReadVariables (local_var_token);
|
||||
reader.position = position;
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
void ReadCode ()
|
||||
{
|
||||
start = Position;
|
||||
var code_size = body.code_size;
|
||||
|
||||
if (code_size < 0 || Length <= (uint) (code_size + Position))
|
||||
code_size = 0;
|
||||
|
||||
var end = start + code_size;
|
||||
var instructions = body.instructions = new InstructionCollection (method, (code_size + 1) / 2);
|
||||
|
||||
while (Position < end) {
|
||||
var offset = Position - start;
|
||||
var opcode = ReadOpCode ();
|
||||
var current = new Instruction (offset, opcode);
|
||||
|
||||
if (opcode.OperandType != OperandType.InlineNone)
|
||||
current.operand = ReadOperand (current);
|
||||
|
||||
instructions.Add (current);
|
||||
}
|
||||
|
||||
ResolveBranches (instructions);
|
||||
}
|
||||
|
||||
OpCode ReadOpCode ()
|
||||
{
|
||||
var il_opcode = ReadByte ();
|
||||
return il_opcode != 0xfe
|
||||
? OpCodes.OneByteOpCode [il_opcode]
|
||||
: OpCodes.TwoBytesOpCode [ReadByte ()];
|
||||
}
|
||||
|
||||
object ReadOperand (Instruction instruction)
|
||||
{
|
||||
switch (instruction.opcode.OperandType) {
|
||||
case OperandType.InlineSwitch:
|
||||
var length = ReadInt32 ();
|
||||
var base_offset = Offset + (4 * length);
|
||||
var branches = new int [length];
|
||||
for (int i = 0; i < length; i++)
|
||||
branches [i] = base_offset + ReadInt32 ();
|
||||
return branches;
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
return ReadSByte () + Offset;
|
||||
case OperandType.InlineBrTarget:
|
||||
return ReadInt32 () + Offset;
|
||||
case OperandType.ShortInlineI:
|
||||
if (instruction.opcode == OpCodes.Ldc_I4_S)
|
||||
return ReadSByte ();
|
||||
|
||||
return ReadByte ();
|
||||
case OperandType.InlineI:
|
||||
return ReadInt32 ();
|
||||
case OperandType.ShortInlineR:
|
||||
return ReadSingle ();
|
||||
case OperandType.InlineR:
|
||||
return ReadDouble ();
|
||||
case OperandType.InlineI8:
|
||||
return ReadInt64 ();
|
||||
case OperandType.ShortInlineVar:
|
||||
return GetVariable (ReadByte ());
|
||||
case OperandType.InlineVar:
|
||||
return GetVariable (ReadUInt16 ());
|
||||
case OperandType.ShortInlineArg:
|
||||
return GetParameter (ReadByte ());
|
||||
case OperandType.InlineArg:
|
||||
return GetParameter (ReadUInt16 ());
|
||||
case OperandType.InlineSig:
|
||||
return GetCallSite (ReadToken ());
|
||||
case OperandType.InlineString:
|
||||
return GetString (ReadToken ());
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineField:
|
||||
return reader.LookupToken (ReadToken ());
|
||||
default:
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public string GetString (MetadataToken token)
|
||||
{
|
||||
return reader.image.UserStringHeap.Read (token.RID);
|
||||
}
|
||||
|
||||
public ParameterDefinition GetParameter (int index)
|
||||
{
|
||||
return body.GetParameter (index);
|
||||
}
|
||||
|
||||
public VariableDefinition GetVariable (int index)
|
||||
{
|
||||
return body.GetVariable (index);
|
||||
}
|
||||
|
||||
public CallSite GetCallSite (MetadataToken token)
|
||||
{
|
||||
return reader.ReadCallSite (token);
|
||||
}
|
||||
|
||||
void ResolveBranches (Collection<Instruction> instructions)
|
||||
{
|
||||
var items = instructions.items;
|
||||
var size = instructions.size;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
var instruction = items [i];
|
||||
switch (instruction.opcode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
instruction.operand = GetInstruction ((int) instruction.operand);
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var offsets = (int []) instruction.operand;
|
||||
var branches = new Instruction [offsets.Length];
|
||||
for (int j = 0; j < offsets.Length; j++)
|
||||
branches [j] = GetInstruction (offsets [j]);
|
||||
|
||||
instruction.operand = branches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instruction GetInstruction (int offset)
|
||||
{
|
||||
return GetInstruction (body.Instructions, offset);
|
||||
}
|
||||
|
||||
static Instruction GetInstruction (Collection<Instruction> instructions, int offset)
|
||||
{
|
||||
var size = instructions.size;
|
||||
var items = instructions.items;
|
||||
if (offset < 0 || offset > items [size - 1].offset)
|
||||
return null;
|
||||
|
||||
int min = 0;
|
||||
int max = size - 1;
|
||||
while (min <= max) {
|
||||
int mid = min + ((max - min) / 2);
|
||||
var instruction = items [mid];
|
||||
var instruction_offset = instruction.offset;
|
||||
|
||||
if (offset == instruction_offset)
|
||||
return instruction;
|
||||
|
||||
if (offset < instruction_offset)
|
||||
max = mid - 1;
|
||||
else
|
||||
min = mid + 1;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void ReadSection ()
|
||||
{
|
||||
Align (4);
|
||||
|
||||
const byte fat_format = 0x40;
|
||||
const byte more_sects = 0x80;
|
||||
|
||||
var flags = ReadByte ();
|
||||
if ((flags & fat_format) == 0)
|
||||
ReadSmallSection ();
|
||||
else
|
||||
ReadFatSection ();
|
||||
|
||||
if ((flags & more_sects) != 0)
|
||||
ReadSection ();
|
||||
}
|
||||
|
||||
void ReadSmallSection ()
|
||||
{
|
||||
var count = ReadByte () / 12;
|
||||
Advance (2);
|
||||
|
||||
ReadExceptionHandlers (
|
||||
count,
|
||||
() => (int) ReadUInt16 (),
|
||||
() => (int) ReadByte ());
|
||||
}
|
||||
|
||||
void ReadFatSection ()
|
||||
{
|
||||
Advance (-1);
|
||||
var count = (ReadInt32 () >> 8) / 24;
|
||||
|
||||
ReadExceptionHandlers (
|
||||
count,
|
||||
ReadInt32,
|
||||
ReadInt32);
|
||||
}
|
||||
|
||||
// inline ?
|
||||
void ReadExceptionHandlers (int count, Func<int> read_entry, Func<int> read_length)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
var handler = new ExceptionHandler (
|
||||
(ExceptionHandlerType) (read_entry () & 0x7));
|
||||
|
||||
handler.TryStart = GetInstruction (read_entry ());
|
||||
handler.TryEnd = GetInstruction (handler.TryStart.Offset + read_length ());
|
||||
|
||||
handler.HandlerStart = GetInstruction (read_entry ());
|
||||
handler.HandlerEnd = GetInstruction (handler.HandlerStart.Offset + read_length ());
|
||||
|
||||
ReadExceptionHandlerSpecific (handler);
|
||||
|
||||
this.body.ExceptionHandlers.Add (handler);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadExceptionHandlerSpecific (ExceptionHandler handler)
|
||||
{
|
||||
switch (handler.HandlerType) {
|
||||
case ExceptionHandlerType.Catch:
|
||||
handler.CatchType = (TypeReference) reader.LookupToken (ReadToken ());
|
||||
break;
|
||||
case ExceptionHandlerType.Filter:
|
||||
handler.FilterStart = GetInstruction (ReadInt32 ());
|
||||
break;
|
||||
default:
|
||||
Advance (4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public MetadataToken ReadToken ()
|
||||
{
|
||||
return new MetadataToken (ReadUInt32 ());
|
||||
}
|
||||
|
||||
void ReadDebugInfo ()
|
||||
{
|
||||
if (method.debug_info.sequence_points != null)
|
||||
ReadSequencePoints ();
|
||||
|
||||
if (method.debug_info.scope != null)
|
||||
ReadScope (method.debug_info.scope);
|
||||
|
||||
if (method.custom_infos != null)
|
||||
ReadCustomDebugInformations (method);
|
||||
}
|
||||
|
||||
void ReadCustomDebugInformations (MethodDefinition method)
|
||||
{
|
||||
var custom_infos = method.custom_infos;
|
||||
|
||||
for (int i = 0; i < custom_infos.Count; i++) {
|
||||
var state_machine_scope = custom_infos [i] as StateMachineScopeDebugInformation;
|
||||
if (state_machine_scope != null)
|
||||
ReadStateMachineScope (state_machine_scope);
|
||||
|
||||
var async_method = custom_infos [i] as AsyncMethodBodyDebugInformation;
|
||||
if (async_method != null)
|
||||
ReadAsyncMethodBody (async_method);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadAsyncMethodBody (AsyncMethodBodyDebugInformation async_method)
|
||||
{
|
||||
if (async_method.catch_handler.Offset > -1)
|
||||
async_method.catch_handler = new InstructionOffset (GetInstruction (async_method.catch_handler.Offset));
|
||||
|
||||
if (!async_method.yields.IsNullOrEmpty ())
|
||||
for (int i = 0; i < async_method.yields.Count; i++)
|
||||
async_method.yields [i] = new InstructionOffset (GetInstruction (async_method.yields [i].Offset));
|
||||
|
||||
if (!async_method.resumes.IsNullOrEmpty ())
|
||||
for (int i = 0; i < async_method.resumes.Count; i++)
|
||||
async_method.resumes [i] = new InstructionOffset (GetInstruction (async_method.resumes [i].Offset));
|
||||
}
|
||||
|
||||
void ReadStateMachineScope (StateMachineScopeDebugInformation state_machine_scope)
|
||||
{
|
||||
if (state_machine_scope.scopes.IsNullOrEmpty ())
|
||||
return;
|
||||
|
||||
foreach (var scope in state_machine_scope.scopes) {
|
||||
scope.start = new InstructionOffset (GetInstruction (scope.start.Offset));
|
||||
|
||||
var end_instruction = GetInstruction (scope.end.Offset);
|
||||
scope.end = end_instruction == null
|
||||
? new InstructionOffset ()
|
||||
: new InstructionOffset (end_instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadSequencePoints ()
|
||||
{
|
||||
var symbol = method.debug_info;
|
||||
|
||||
for (int i = 0; i < symbol.sequence_points.Count; i++) {
|
||||
var sequence_point = symbol.sequence_points [i];
|
||||
var instruction = GetInstruction (sequence_point.Offset);
|
||||
if (instruction != null)
|
||||
sequence_point.offset = new InstructionOffset (instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadScopes (Collection<ScopeDebugInformation> scopes)
|
||||
{
|
||||
for (int i = 0; i < scopes.Count; i++)
|
||||
ReadScope (scopes [i]);
|
||||
}
|
||||
|
||||
void ReadScope (ScopeDebugInformation scope)
|
||||
{
|
||||
var start_instruction = GetInstruction (scope.Start.Offset);
|
||||
if (start_instruction != null)
|
||||
scope.Start = new InstructionOffset (start_instruction);
|
||||
|
||||
var end_instruction = GetInstruction (scope.End.Offset);
|
||||
scope.End = end_instruction != null
|
||||
? new InstructionOffset (end_instruction)
|
||||
: new InstructionOffset ();
|
||||
|
||||
if (!scope.variables.IsNullOrEmpty ()) {
|
||||
for (int i = 0; i < scope.variables.Count; i++) {
|
||||
var variable_info = scope.variables [i];
|
||||
var variable = GetVariable (variable_info.Index);
|
||||
if (variable != null)
|
||||
variable_info.index = new VariableIndex (variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!scope.scopes.IsNullOrEmpty ())
|
||||
ReadScopes (scope.scopes);
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out int code_size, out MetadataToken local_var_token)
|
||||
{
|
||||
var position = MoveTo (method);
|
||||
|
||||
var buffer = new ByteBuffer ();
|
||||
|
||||
var flags = ReadByte ();
|
||||
|
||||
switch (flags & 0x3) {
|
||||
case 0x2: // tiny
|
||||
buffer.WriteByte (flags);
|
||||
local_var_token = MetadataToken.Zero;
|
||||
code_size = flags >> 2;
|
||||
PatchRawCode (buffer, code_size, writer);
|
||||
break;
|
||||
case 0x3: // fat
|
||||
Advance (-1);
|
||||
PatchRawFatMethod (buffer, writer, out code_size, out local_var_token);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
MoveBackTo (position);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void PatchRawFatMethod (ByteBuffer buffer, CodeWriter writer, out int code_size, out MetadataToken local_var_token)
|
||||
{
|
||||
var flags = ReadUInt16 ();
|
||||
buffer.WriteUInt16 (flags);
|
||||
buffer.WriteUInt16 (ReadUInt16 ());
|
||||
code_size = ReadInt32 ();
|
||||
buffer.WriteInt32 (code_size);
|
||||
local_var_token = ReadToken ();
|
||||
|
||||
if (local_var_token.RID > 0) {
|
||||
var variables = ReadVariables (local_var_token);
|
||||
buffer.WriteUInt32 (variables != null
|
||||
? writer.GetStandAloneSignature (variables).ToUInt32 ()
|
||||
: 0);
|
||||
} else
|
||||
buffer.WriteUInt32 (0);
|
||||
|
||||
PatchRawCode (buffer, code_size, writer);
|
||||
|
||||
if ((flags & 0x8) != 0)
|
||||
PatchRawSection (buffer, writer.metadata);
|
||||
}
|
||||
|
||||
void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer)
|
||||
{
|
||||
var metadata = writer.metadata;
|
||||
buffer.WriteBytes (ReadBytes (code_size));
|
||||
var end = buffer.position;
|
||||
buffer.position -= code_size;
|
||||
|
||||
while (buffer.position < end) {
|
||||
OpCode opcode;
|
||||
var il_opcode = buffer.ReadByte ();
|
||||
if (il_opcode != 0xfe) {
|
||||
opcode = OpCodes.OneByteOpCode [il_opcode];
|
||||
} else {
|
||||
var il_opcode2 = buffer.ReadByte ();
|
||||
opcode = OpCodes.TwoBytesOpCode [il_opcode2];
|
||||
}
|
||||
|
||||
switch (opcode.OperandType) {
|
||||
case OperandType.ShortInlineI:
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.ShortInlineVar:
|
||||
case OperandType.ShortInlineArg:
|
||||
buffer.position += 1;
|
||||
break;
|
||||
case OperandType.InlineVar:
|
||||
case OperandType.InlineArg:
|
||||
buffer.position += 2;
|
||||
break;
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.ShortInlineR:
|
||||
case OperandType.InlineI:
|
||||
buffer.position += 4;
|
||||
break;
|
||||
case OperandType.InlineI8:
|
||||
case OperandType.InlineR:
|
||||
buffer.position += 8;
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var length = buffer.ReadInt32 ();
|
||||
buffer.position += length * 4;
|
||||
break;
|
||||
case OperandType.InlineString:
|
||||
var @string = GetString (new MetadataToken (buffer.ReadUInt32 ()));
|
||||
buffer.position -= 4;
|
||||
buffer.WriteUInt32 (
|
||||
new MetadataToken (
|
||||
TokenType.String,
|
||||
metadata.user_string_heap.GetStringIndex (@string)).ToUInt32 ());
|
||||
break;
|
||||
case OperandType.InlineSig:
|
||||
var call_site = GetCallSite (new MetadataToken (buffer.ReadUInt32 ()));
|
||||
buffer.position -= 4;
|
||||
buffer.WriteUInt32 (writer.GetStandAloneSignature (call_site).ToUInt32 ());
|
||||
break;
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineField:
|
||||
var provider = reader.LookupToken (new MetadataToken (buffer.ReadUInt32 ()));
|
||||
buffer.position -= 4;
|
||||
buffer.WriteUInt32 (metadata.LookupToken (provider).ToUInt32 ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata)
|
||||
{
|
||||
var position = Position;
|
||||
Align (4);
|
||||
buffer.WriteBytes (Position - position);
|
||||
|
||||
const byte fat_format = 0x40;
|
||||
const byte more_sects = 0x80;
|
||||
|
||||
var flags = ReadByte ();
|
||||
if ((flags & fat_format) == 0) {
|
||||
buffer.WriteByte (flags);
|
||||
PatchRawSmallSection (buffer, metadata);
|
||||
} else
|
||||
PatchRawFatSection (buffer, metadata);
|
||||
|
||||
if ((flags & more_sects) != 0)
|
||||
PatchRawSection (buffer, metadata);
|
||||
}
|
||||
|
||||
void PatchRawSmallSection (ByteBuffer buffer, MetadataBuilder metadata)
|
||||
{
|
||||
var length = ReadByte ();
|
||||
buffer.WriteByte (length);
|
||||
Advance (2);
|
||||
|
||||
buffer.WriteUInt16 (0);
|
||||
|
||||
var count = length / 12;
|
||||
|
||||
PatchRawExceptionHandlers (buffer, metadata, count, false);
|
||||
}
|
||||
|
||||
void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata)
|
||||
{
|
||||
Advance (-1);
|
||||
var length = ReadInt32 ();
|
||||
buffer.WriteInt32 (length);
|
||||
|
||||
var count = (length >> 8) / 24;
|
||||
|
||||
PatchRawExceptionHandlers (buffer, metadata, count, true);
|
||||
}
|
||||
|
||||
void PatchRawExceptionHandlers (ByteBuffer buffer, MetadataBuilder metadata, int count, bool fat_entry)
|
||||
{
|
||||
const int fat_entry_size = 16;
|
||||
const int small_entry_size = 6;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ExceptionHandlerType handler_type;
|
||||
if (fat_entry) {
|
||||
var type = ReadUInt32 ();
|
||||
handler_type = (ExceptionHandlerType) (type & 0x7);
|
||||
buffer.WriteUInt32 (type);
|
||||
} else {
|
||||
var type = ReadUInt16 ();
|
||||
handler_type = (ExceptionHandlerType) (type & 0x7);
|
||||
buffer.WriteUInt16 (type);
|
||||
}
|
||||
|
||||
buffer.WriteBytes (ReadBytes (fat_entry ? fat_entry_size : small_entry_size));
|
||||
|
||||
switch (handler_type) {
|
||||
case ExceptionHandlerType.Catch:
|
||||
var exception = reader.LookupToken (ReadToken ());
|
||||
buffer.WriteUInt32 (metadata.LookupToken (exception).ToUInt32 ());
|
||||
break;
|
||||
default:
|
||||
buffer.WriteUInt32 (ReadUInt32 ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,659 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
using Mono.Cecil.Metadata;
|
||||
using Mono.Cecil.PE;
|
||||
|
||||
using RVA = System.UInt32;
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
sealed class CodeWriter : ByteBuffer {
|
||||
|
||||
readonly RVA code_base;
|
||||
internal readonly MetadataBuilder metadata;
|
||||
readonly Dictionary<uint, MetadataToken> standalone_signatures;
|
||||
readonly Dictionary<ByteBuffer, RVA> tiny_method_bodies;
|
||||
|
||||
MethodBody body;
|
||||
|
||||
public CodeWriter (MetadataBuilder metadata)
|
||||
: base (0)
|
||||
{
|
||||
this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader);
|
||||
this.metadata = metadata;
|
||||
this.standalone_signatures = new Dictionary<uint, MetadataToken> ();
|
||||
this.tiny_method_bodies = new Dictionary<ByteBuffer, RVA> (new ByteBufferEqualityComparer ());
|
||||
}
|
||||
|
||||
public RVA WriteMethodBody (MethodDefinition method)
|
||||
{
|
||||
RVA rva;
|
||||
|
||||
if (IsUnresolved (method)) {
|
||||
if (method.rva == 0)
|
||||
return 0;
|
||||
|
||||
rva = WriteUnresolvedMethodBody (method);
|
||||
} else {
|
||||
if (IsEmptyMethodBody (method.Body))
|
||||
return 0;
|
||||
|
||||
rva = WriteResolvedMethodBody (method);
|
||||
}
|
||||
|
||||
return rva;
|
||||
}
|
||||
|
||||
static bool IsEmptyMethodBody (MethodBody body)
|
||||
{
|
||||
return body.instructions.IsNullOrEmpty ()
|
||||
&& body.variables.IsNullOrEmpty ();
|
||||
}
|
||||
|
||||
static bool IsUnresolved (MethodDefinition method)
|
||||
{
|
||||
return method.HasBody && method.HasImage && method.body == null;
|
||||
}
|
||||
|
||||
RVA WriteUnresolvedMethodBody (MethodDefinition method)
|
||||
{
|
||||
var code_reader = metadata.module.reader.code;
|
||||
|
||||
int code_size;
|
||||
MetadataToken local_var_token;
|
||||
var raw_body = code_reader.PatchRawMethodBody (method, this, out code_size, out local_var_token);
|
||||
var fat_header = (raw_body.buffer [0] & 0x3) == 0x3;
|
||||
if (fat_header)
|
||||
Align (4);
|
||||
|
||||
var rva = BeginMethod ();
|
||||
|
||||
if (fat_header || !GetOrMapTinyMethodBody (raw_body, ref rva)) {
|
||||
WriteBytes (raw_body);
|
||||
}
|
||||
|
||||
if (method.debug_info == null)
|
||||
return rva;
|
||||
|
||||
var symbol_writer = metadata.symbol_writer;
|
||||
if (symbol_writer != null) {
|
||||
method.debug_info.code_size = code_size;
|
||||
method.debug_info.local_var_token = local_var_token;
|
||||
symbol_writer.Write (method.debug_info);
|
||||
}
|
||||
|
||||
return rva;
|
||||
}
|
||||
|
||||
RVA WriteResolvedMethodBody(MethodDefinition method)
|
||||
{
|
||||
RVA rva;
|
||||
|
||||
body = method.Body;
|
||||
ComputeHeader ();
|
||||
if (RequiresFatHeader ()) {
|
||||
Align (4);
|
||||
rva = BeginMethod ();
|
||||
WriteFatHeader ();
|
||||
WriteInstructions ();
|
||||
|
||||
if (body.HasExceptionHandlers)
|
||||
WriteExceptionHandlers ();
|
||||
} else {
|
||||
rva = BeginMethod ();
|
||||
WriteByte ((byte) (0x2 | (body.CodeSize << 2))); // tiny
|
||||
WriteInstructions ();
|
||||
|
||||
var start_position = (int) (rva - code_base);
|
||||
var body_size = position - start_position;
|
||||
var body_bytes = new byte [body_size];
|
||||
|
||||
Array.Copy (buffer, start_position, body_bytes, 0, body_size);
|
||||
|
||||
if (GetOrMapTinyMethodBody (new ByteBuffer (body_bytes), ref rva))
|
||||
position = start_position;
|
||||
}
|
||||
|
||||
var symbol_writer = metadata.symbol_writer;
|
||||
if (symbol_writer != null && method.debug_info != null) {
|
||||
method.debug_info.code_size = body.CodeSize;
|
||||
method.debug_info.local_var_token = body.local_var_token;
|
||||
symbol_writer.Write (method.debug_info);
|
||||
}
|
||||
|
||||
return rva;
|
||||
}
|
||||
|
||||
bool GetOrMapTinyMethodBody (ByteBuffer body, ref RVA rva)
|
||||
{
|
||||
RVA existing_rva;
|
||||
if (tiny_method_bodies.TryGetValue (body, out existing_rva)) {
|
||||
rva = existing_rva;
|
||||
return true;
|
||||
}
|
||||
|
||||
tiny_method_bodies.Add (body, rva);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WriteFatHeader ()
|
||||
{
|
||||
var body = this.body;
|
||||
byte flags = 0x3; // fat
|
||||
if (body.InitLocals)
|
||||
flags |= 0x10; // init locals
|
||||
if (body.HasExceptionHandlers)
|
||||
flags |= 0x8; // more sections
|
||||
|
||||
WriteByte (flags);
|
||||
WriteByte (0x30);
|
||||
WriteInt16 ((short) body.max_stack_size);
|
||||
WriteInt32 (body.code_size);
|
||||
body.local_var_token = body.HasVariables
|
||||
? GetStandAloneSignature (body.Variables)
|
||||
: MetadataToken.Zero;
|
||||
WriteMetadataToken (body.local_var_token);
|
||||
}
|
||||
|
||||
void WriteInstructions ()
|
||||
{
|
||||
var instructions = body.Instructions;
|
||||
var items = instructions.items;
|
||||
var size = instructions.size;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
var instruction = items [i];
|
||||
WriteOpCode (instruction.opcode);
|
||||
WriteOperand (instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteOpCode (OpCode opcode)
|
||||
{
|
||||
if (opcode.Size == 1) {
|
||||
WriteByte (opcode.Op2);
|
||||
} else {
|
||||
WriteByte (opcode.Op1);
|
||||
WriteByte (opcode.Op2);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteOperand (Instruction instruction)
|
||||
{
|
||||
var opcode = instruction.opcode;
|
||||
var operand_type = opcode.OperandType;
|
||||
if (operand_type == OperandType.InlineNone)
|
||||
return;
|
||||
|
||||
var operand = instruction.operand;
|
||||
if (operand == null && !(operand_type == OperandType.InlineBrTarget || operand_type == OperandType.ShortInlineBrTarget)) {
|
||||
throw new ArgumentException ();
|
||||
}
|
||||
|
||||
switch (operand_type) {
|
||||
case OperandType.InlineSwitch: {
|
||||
var targets = (Instruction []) operand;
|
||||
WriteInt32 (targets.Length);
|
||||
var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1));
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
WriteInt32 (GetTargetOffset (targets [i]) - diff);
|
||||
break;
|
||||
}
|
||||
case OperandType.ShortInlineBrTarget: {
|
||||
var target = (Instruction) operand;
|
||||
var offset = target != null ? GetTargetOffset (target) : body.code_size;
|
||||
WriteSByte ((sbyte) (offset - (instruction.Offset + opcode.Size + 1)));
|
||||
break;
|
||||
}
|
||||
case OperandType.InlineBrTarget: {
|
||||
var target = (Instruction) operand;
|
||||
var offset = target != null ? GetTargetOffset (target) : body.code_size;
|
||||
WriteInt32 (offset - (instruction.Offset + opcode.Size + 4));
|
||||
break;
|
||||
}
|
||||
case OperandType.ShortInlineVar:
|
||||
WriteByte ((byte) GetVariableIndex ((VariableDefinition) operand));
|
||||
break;
|
||||
case OperandType.ShortInlineArg:
|
||||
WriteByte ((byte) GetParameterIndex ((ParameterDefinition) operand));
|
||||
break;
|
||||
case OperandType.InlineVar:
|
||||
WriteInt16 ((short) GetVariableIndex ((VariableDefinition) operand));
|
||||
break;
|
||||
case OperandType.InlineArg:
|
||||
WriteInt16 ((short) GetParameterIndex ((ParameterDefinition) operand));
|
||||
break;
|
||||
case OperandType.InlineSig:
|
||||
WriteMetadataToken (GetStandAloneSignature ((CallSite) operand));
|
||||
break;
|
||||
case OperandType.ShortInlineI:
|
||||
if (opcode == OpCodes.Ldc_I4_S)
|
||||
WriteSByte ((sbyte) operand);
|
||||
else
|
||||
WriteByte ((byte) operand);
|
||||
break;
|
||||
case OperandType.InlineI:
|
||||
WriteInt32 ((int) operand);
|
||||
break;
|
||||
case OperandType.InlineI8:
|
||||
WriteInt64 ((long) operand);
|
||||
break;
|
||||
case OperandType.ShortInlineR:
|
||||
WriteSingle ((float) operand);
|
||||
break;
|
||||
case OperandType.InlineR:
|
||||
WriteDouble ((double) operand);
|
||||
break;
|
||||
case OperandType.InlineString:
|
||||
WriteMetadataToken (
|
||||
new MetadataToken (
|
||||
TokenType.String,
|
||||
GetUserStringIndex ((string) operand)));
|
||||
break;
|
||||
case OperandType.InlineType:
|
||||
case OperandType.InlineField:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineTok:
|
||||
WriteMetadataToken (metadata.LookupToken ((IMetadataTokenProvider) operand));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException ();
|
||||
}
|
||||
}
|
||||
|
||||
int GetTargetOffset (Instruction instruction)
|
||||
{
|
||||
if (instruction == null) {
|
||||
var last = body.instructions [body.instructions.size - 1];
|
||||
return last.offset + last.GetSize ();
|
||||
}
|
||||
|
||||
return instruction.offset;
|
||||
}
|
||||
|
||||
uint GetUserStringIndex (string @string)
|
||||
{
|
||||
if (@string == null)
|
||||
return 0;
|
||||
|
||||
return metadata.user_string_heap.GetStringIndex (@string);
|
||||
}
|
||||
|
||||
static int GetVariableIndex (VariableDefinition variable)
|
||||
{
|
||||
return variable.Index;
|
||||
}
|
||||
|
||||
int GetParameterIndex (ParameterDefinition parameter)
|
||||
{
|
||||
if (body.method.HasThis) {
|
||||
if (parameter == body.this_parameter)
|
||||
return 0;
|
||||
|
||||
return parameter.Index + 1;
|
||||
}
|
||||
|
||||
return parameter.Index;
|
||||
}
|
||||
|
||||
bool RequiresFatHeader ()
|
||||
{
|
||||
var body = this.body;
|
||||
return body.CodeSize >= 64
|
||||
|| body.InitLocals
|
||||
|| body.HasVariables
|
||||
|| body.HasExceptionHandlers
|
||||
|| body.MaxStackSize > 8;
|
||||
}
|
||||
|
||||
void ComputeHeader ()
|
||||
{
|
||||
int offset = 0;
|
||||
var instructions = body.instructions;
|
||||
var items = instructions.items;
|
||||
var count = instructions.size;
|
||||
var stack_size = 0;
|
||||
var max_stack = 0;
|
||||
Dictionary<Instruction, int> stack_sizes = null;
|
||||
|
||||
if (body.HasExceptionHandlers)
|
||||
ComputeExceptionHandlerStackSize (ref stack_sizes);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
var instruction = items [i];
|
||||
instruction.offset = offset;
|
||||
offset += instruction.GetSize ();
|
||||
|
||||
ComputeStackSize (instruction, ref stack_sizes, ref stack_size, ref max_stack);
|
||||
}
|
||||
|
||||
body.code_size = offset;
|
||||
body.max_stack_size = max_stack;
|
||||
}
|
||||
|
||||
void ComputeExceptionHandlerStackSize (ref Dictionary<Instruction, int> stack_sizes)
|
||||
{
|
||||
var exception_handlers = body.ExceptionHandlers;
|
||||
|
||||
for (int i = 0; i < exception_handlers.Count; i++) {
|
||||
var exception_handler = exception_handlers [i];
|
||||
|
||||
switch (exception_handler.HandlerType) {
|
||||
case ExceptionHandlerType.Catch:
|
||||
AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes);
|
||||
break;
|
||||
case ExceptionHandlerType.Filter:
|
||||
AddExceptionStackSize (exception_handler.FilterStart, ref stack_sizes);
|
||||
AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AddExceptionStackSize (Instruction handler_start, ref Dictionary<Instruction, int> stack_sizes)
|
||||
{
|
||||
if (handler_start == null)
|
||||
return;
|
||||
|
||||
if (stack_sizes == null)
|
||||
stack_sizes = new Dictionary<Instruction, int> ();
|
||||
|
||||
stack_sizes [handler_start] = 1;
|
||||
}
|
||||
|
||||
static void ComputeStackSize (Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, ref int stack_size, ref int max_stack)
|
||||
{
|
||||
int computed_size;
|
||||
if (stack_sizes != null && stack_sizes.TryGetValue (instruction, out computed_size))
|
||||
stack_size = computed_size;
|
||||
|
||||
max_stack = System.Math.Max (max_stack, stack_size);
|
||||
ComputeStackDelta (instruction, ref stack_size);
|
||||
max_stack = System.Math.Max (max_stack, stack_size);
|
||||
|
||||
CopyBranchStackSize (instruction, ref stack_sizes, stack_size);
|
||||
ComputeStackSize (instruction, ref stack_size);
|
||||
}
|
||||
|
||||
static void CopyBranchStackSize (Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, int stack_size)
|
||||
{
|
||||
if (stack_size == 0)
|
||||
return;
|
||||
|
||||
switch (instruction.opcode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
CopyBranchStackSize (ref stack_sizes, (Instruction) instruction.operand, stack_size);
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var targets = (Instruction []) instruction.operand;
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
CopyBranchStackSize (ref stack_sizes, targets [i], stack_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyBranchStackSize (ref Dictionary<Instruction, int> stack_sizes, Instruction target, int stack_size)
|
||||
{
|
||||
if (stack_sizes == null)
|
||||
stack_sizes = new Dictionary<Instruction, int> ();
|
||||
|
||||
int branch_stack_size = stack_size;
|
||||
|
||||
int computed_size;
|
||||
if (stack_sizes.TryGetValue (target, out computed_size))
|
||||
branch_stack_size = System.Math.Max (branch_stack_size, computed_size);
|
||||
|
||||
stack_sizes [target] = branch_stack_size;
|
||||
}
|
||||
|
||||
static void ComputeStackSize (Instruction instruction, ref int stack_size)
|
||||
{
|
||||
switch (instruction.opcode.FlowControl) {
|
||||
case FlowControl.Branch:
|
||||
case FlowControl.Break:
|
||||
case FlowControl.Throw:
|
||||
case FlowControl.Return:
|
||||
stack_size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputeStackDelta (Instruction instruction, ref int stack_size)
|
||||
{
|
||||
switch (instruction.opcode.FlowControl) {
|
||||
case FlowControl.Call: {
|
||||
var method = (IMethodSignature) instruction.operand;
|
||||
// pop 'this' argument
|
||||
if (method.HasImplicitThis() && instruction.opcode.Code != Code.Newobj)
|
||||
stack_size--;
|
||||
// pop normal arguments
|
||||
if (method.HasParameters)
|
||||
stack_size -= method.Parameters.Count;
|
||||
// pop function pointer
|
||||
if (instruction.opcode.Code == Code.Calli)
|
||||
stack_size--;
|
||||
// push return value
|
||||
if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj)
|
||||
stack_size++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ComputePopDelta (instruction.opcode.StackBehaviourPop, ref stack_size);
|
||||
ComputePushDelta (instruction.opcode.StackBehaviourPush, ref stack_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputePopDelta (StackBehaviour pop_behavior, ref int stack_size)
|
||||
{
|
||||
switch (pop_behavior) {
|
||||
case StackBehaviour.Popi:
|
||||
case StackBehaviour.Popref:
|
||||
case StackBehaviour.Pop1:
|
||||
stack_size--;
|
||||
break;
|
||||
case StackBehaviour.Pop1_pop1:
|
||||
case StackBehaviour.Popi_pop1:
|
||||
case StackBehaviour.Popi_popi:
|
||||
case StackBehaviour.Popi_popi8:
|
||||
case StackBehaviour.Popi_popr4:
|
||||
case StackBehaviour.Popi_popr8:
|
||||
case StackBehaviour.Popref_pop1:
|
||||
case StackBehaviour.Popref_popi:
|
||||
stack_size -= 2;
|
||||
break;
|
||||
case StackBehaviour.Popi_popi_popi:
|
||||
case StackBehaviour.Popref_popi_popi:
|
||||
case StackBehaviour.Popref_popi_popi8:
|
||||
case StackBehaviour.Popref_popi_popr4:
|
||||
case StackBehaviour.Popref_popi_popr8:
|
||||
case StackBehaviour.Popref_popi_popref:
|
||||
stack_size -= 3;
|
||||
break;
|
||||
case StackBehaviour.PopAll:
|
||||
stack_size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputePushDelta (StackBehaviour push_behaviour, ref int stack_size)
|
||||
{
|
||||
switch (push_behaviour) {
|
||||
case StackBehaviour.Push1:
|
||||
case StackBehaviour.Pushi:
|
||||
case StackBehaviour.Pushi8:
|
||||
case StackBehaviour.Pushr4:
|
||||
case StackBehaviour.Pushr8:
|
||||
case StackBehaviour.Pushref:
|
||||
stack_size++;
|
||||
break;
|
||||
case StackBehaviour.Push1_push1:
|
||||
stack_size += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteExceptionHandlers ()
|
||||
{
|
||||
Align (4);
|
||||
|
||||
var handlers = body.ExceptionHandlers;
|
||||
|
||||
if (handlers.Count < 0x15 && !RequiresFatSection (handlers))
|
||||
WriteSmallSection (handlers);
|
||||
else
|
||||
WriteFatSection (handlers);
|
||||
}
|
||||
|
||||
static bool RequiresFatSection (Collection<ExceptionHandler> handlers)
|
||||
{
|
||||
for (int i = 0; i < handlers.Count; i++) {
|
||||
var handler = handlers [i];
|
||||
|
||||
if (IsFatRange (handler.TryStart, handler.TryEnd))
|
||||
return true;
|
||||
|
||||
if (IsFatRange (handler.HandlerStart, handler.HandlerEnd))
|
||||
return true;
|
||||
|
||||
if (handler.HandlerType == ExceptionHandlerType.Filter
|
||||
&& IsFatRange (handler.FilterStart, handler.HandlerStart))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsFatRange (Instruction start, Instruction end)
|
||||
{
|
||||
if (start == null)
|
||||
throw new ArgumentException ();
|
||||
|
||||
if (end == null)
|
||||
return true;
|
||||
|
||||
return end.Offset - start.Offset > 255 || start.Offset > 65535;
|
||||
}
|
||||
|
||||
void WriteSmallSection (Collection<ExceptionHandler> handlers)
|
||||
{
|
||||
const byte eh_table = 0x1;
|
||||
|
||||
WriteByte (eh_table);
|
||||
WriteByte ((byte) (handlers.Count * 12 + 4));
|
||||
WriteBytes (2);
|
||||
|
||||
WriteExceptionHandlers (
|
||||
handlers,
|
||||
i => WriteUInt16 ((ushort) i),
|
||||
i => WriteByte ((byte) i));
|
||||
}
|
||||
|
||||
void WriteFatSection (Collection<ExceptionHandler> handlers)
|
||||
{
|
||||
const byte eh_table = 0x1;
|
||||
const byte fat_format = 0x40;
|
||||
|
||||
WriteByte (eh_table | fat_format);
|
||||
|
||||
int size = handlers.Count * 24 + 4;
|
||||
WriteByte ((byte) (size & 0xff));
|
||||
WriteByte ((byte) ((size >> 8) & 0xff));
|
||||
WriteByte ((byte) ((size >> 16) & 0xff));
|
||||
|
||||
WriteExceptionHandlers (handlers, WriteInt32, WriteInt32);
|
||||
}
|
||||
|
||||
void WriteExceptionHandlers (Collection<ExceptionHandler> handlers, Action<int> write_entry, Action<int> write_length)
|
||||
{
|
||||
for (int i = 0; i < handlers.Count; i++) {
|
||||
var handler = handlers [i];
|
||||
|
||||
write_entry ((int) handler.HandlerType);
|
||||
|
||||
write_entry (handler.TryStart.Offset);
|
||||
write_length (GetTargetOffset (handler.TryEnd) - handler.TryStart.Offset);
|
||||
|
||||
write_entry (handler.HandlerStart.Offset);
|
||||
write_length (GetTargetOffset (handler.HandlerEnd) - handler.HandlerStart.Offset);
|
||||
|
||||
WriteExceptionHandlerSpecific (handler);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteExceptionHandlerSpecific (ExceptionHandler handler)
|
||||
{
|
||||
switch (handler.HandlerType) {
|
||||
case ExceptionHandlerType.Catch:
|
||||
WriteMetadataToken (metadata.LookupToken (handler.CatchType));
|
||||
break;
|
||||
case ExceptionHandlerType.Filter:
|
||||
WriteInt32 (handler.FilterStart.Offset);
|
||||
break;
|
||||
default:
|
||||
WriteInt32 (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public MetadataToken GetStandAloneSignature (Collection<VariableDefinition> variables)
|
||||
{
|
||||
var signature = metadata.GetLocalVariableBlobIndex (variables);
|
||||
|
||||
return GetStandAloneSignatureToken (signature);
|
||||
}
|
||||
|
||||
public MetadataToken GetStandAloneSignature (CallSite call_site)
|
||||
{
|
||||
var signature = metadata.GetCallSiteBlobIndex (call_site);
|
||||
var token = GetStandAloneSignatureToken (signature);
|
||||
call_site.MetadataToken = token;
|
||||
return token;
|
||||
}
|
||||
|
||||
MetadataToken GetStandAloneSignatureToken (uint signature)
|
||||
{
|
||||
MetadataToken token;
|
||||
if (standalone_signatures.TryGetValue (signature, out token))
|
||||
return token;
|
||||
|
||||
token = new MetadataToken (TokenType.Signature, metadata.AddStandAloneSignature (signature));
|
||||
standalone_signatures.Add (signature, token);
|
||||
return token;
|
||||
}
|
||||
|
||||
RVA BeginMethod ()
|
||||
{
|
||||
return (RVA)(code_base + position);
|
||||
}
|
||||
|
||||
void WriteMetadataToken (MetadataToken token)
|
||||
{
|
||||
WriteUInt32 (token.ToUInt32 ());
|
||||
}
|
||||
|
||||
void Align (int align)
|
||||
{
|
||||
align--;
|
||||
WriteBytes (((position + align) & ~align) - position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,123 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public enum DocumentType {
|
||||
Other,
|
||||
Text,
|
||||
}
|
||||
|
||||
public enum DocumentHashAlgorithm {
|
||||
None,
|
||||
MD5,
|
||||
SHA1,
|
||||
SHA256,
|
||||
}
|
||||
|
||||
public enum DocumentLanguage {
|
||||
Other,
|
||||
C,
|
||||
Cpp,
|
||||
CSharp,
|
||||
Basic,
|
||||
Java,
|
||||
Cobol,
|
||||
Pascal,
|
||||
Cil,
|
||||
JScript,
|
||||
Smc,
|
||||
MCpp,
|
||||
FSharp,
|
||||
}
|
||||
|
||||
public enum DocumentLanguageVendor {
|
||||
Other,
|
||||
Microsoft,
|
||||
}
|
||||
|
||||
public sealed class Document : DebugInformation {
|
||||
|
||||
string url;
|
||||
|
||||
Guid type;
|
||||
Guid hash_algorithm;
|
||||
Guid language;
|
||||
Guid language_vendor;
|
||||
|
||||
byte [] hash;
|
||||
byte [] embedded_source;
|
||||
|
||||
public string Url {
|
||||
get { return url; }
|
||||
set { url = value; }
|
||||
}
|
||||
|
||||
public DocumentType Type {
|
||||
get { return type.ToType (); }
|
||||
set { type = value.ToGuid (); }
|
||||
}
|
||||
|
||||
public Guid TypeGuid {
|
||||
get { return type; }
|
||||
set { type = value; }
|
||||
}
|
||||
|
||||
public DocumentHashAlgorithm HashAlgorithm {
|
||||
get { return hash_algorithm.ToHashAlgorithm (); }
|
||||
set { hash_algorithm = value.ToGuid (); }
|
||||
}
|
||||
|
||||
public Guid HashAlgorithmGuid {
|
||||
get { return hash_algorithm; }
|
||||
set { hash_algorithm = value; }
|
||||
}
|
||||
|
||||
public DocumentLanguage Language {
|
||||
get { return language.ToLanguage (); }
|
||||
set { language = value.ToGuid (); }
|
||||
}
|
||||
|
||||
public Guid LanguageGuid {
|
||||
get { return language; }
|
||||
set { language = value; }
|
||||
}
|
||||
|
||||
public DocumentLanguageVendor LanguageVendor {
|
||||
get { return language_vendor.ToVendor (); }
|
||||
set { language_vendor = value.ToGuid (); }
|
||||
}
|
||||
|
||||
public Guid LanguageVendorGuid {
|
||||
get { return language_vendor; }
|
||||
set { language_vendor = value; }
|
||||
}
|
||||
|
||||
public byte [] Hash {
|
||||
get { return hash; }
|
||||
set { hash = value; }
|
||||
}
|
||||
|
||||
public byte[] EmbeddedSource {
|
||||
get { return embedded_source; }
|
||||
set { embedded_source = value; }
|
||||
}
|
||||
|
||||
public Document (string url)
|
||||
{
|
||||
this.url = url;
|
||||
this.hash = Empty<byte>.Array;
|
||||
this.embedded_source = Empty<byte>.Array;
|
||||
this.token = new MetadataToken (TokenType.Document);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public enum ExceptionHandlerType {
|
||||
Catch = 0,
|
||||
Filter = 1,
|
||||
Finally = 2,
|
||||
Fault = 4,
|
||||
}
|
||||
|
||||
public sealed class ExceptionHandler {
|
||||
|
||||
Instruction try_start;
|
||||
Instruction try_end;
|
||||
Instruction filter_start;
|
||||
Instruction handler_start;
|
||||
Instruction handler_end;
|
||||
|
||||
TypeReference catch_type;
|
||||
ExceptionHandlerType handler_type;
|
||||
|
||||
public Instruction TryStart {
|
||||
get { return try_start; }
|
||||
set { try_start = value; }
|
||||
}
|
||||
|
||||
public Instruction TryEnd {
|
||||
get { return try_end; }
|
||||
set { try_end = value; }
|
||||
}
|
||||
|
||||
public Instruction FilterStart {
|
||||
get { return filter_start; }
|
||||
set { filter_start = value; }
|
||||
}
|
||||
|
||||
public Instruction HandlerStart {
|
||||
get { return handler_start; }
|
||||
set { handler_start = value; }
|
||||
}
|
||||
|
||||
public Instruction HandlerEnd {
|
||||
get { return handler_end; }
|
||||
set { handler_end = value; }
|
||||
}
|
||||
|
||||
public TypeReference CatchType {
|
||||
get { return catch_type; }
|
||||
set { catch_type = value; }
|
||||
}
|
||||
|
||||
public ExceptionHandlerType HandlerType {
|
||||
get { return handler_type; }
|
||||
set { handler_type = value; }
|
||||
}
|
||||
|
||||
public ExceptionHandler (ExceptionHandlerType handlerType)
|
||||
{
|
||||
this.handler_type = handlerType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class ILProcessor {
|
||||
|
||||
readonly MethodBody body;
|
||||
readonly Collection<Instruction> instructions;
|
||||
|
||||
public MethodBody Body {
|
||||
get { return body; }
|
||||
}
|
||||
|
||||
internal ILProcessor (MethodBody body)
|
||||
{
|
||||
this.body = body;
|
||||
this.instructions = body.Instructions;
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode)
|
||||
{
|
||||
return Instruction.Create (opcode);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, TypeReference type)
|
||||
{
|
||||
return Instruction.Create (opcode, type);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, CallSite site)
|
||||
{
|
||||
return Instruction.Create (opcode, site);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, MethodReference method)
|
||||
{
|
||||
return Instruction.Create (opcode, method);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, FieldReference field)
|
||||
{
|
||||
return Instruction.Create (opcode, field);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, string value)
|
||||
{
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, sbyte value)
|
||||
{
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, byte value)
|
||||
{
|
||||
if (opcode.OperandType == OperandType.ShortInlineVar)
|
||||
return Instruction.Create (opcode, body.Variables [value]);
|
||||
|
||||
if (opcode.OperandType == OperandType.ShortInlineArg)
|
||||
return Instruction.Create (opcode, body.GetParameter (value));
|
||||
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, int value)
|
||||
{
|
||||
if (opcode.OperandType == OperandType.InlineVar)
|
||||
return Instruction.Create (opcode, body.Variables [value]);
|
||||
|
||||
if (opcode.OperandType == OperandType.InlineArg)
|
||||
return Instruction.Create (opcode, body.GetParameter (value));
|
||||
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, long value)
|
||||
{
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, float value)
|
||||
{
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, double value)
|
||||
{
|
||||
return Instruction.Create (opcode, value);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, Instruction target)
|
||||
{
|
||||
return Instruction.Create (opcode, target);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, Instruction [] targets)
|
||||
{
|
||||
return Instruction.Create (opcode, targets);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, VariableDefinition variable)
|
||||
{
|
||||
return Instruction.Create (opcode, variable);
|
||||
}
|
||||
|
||||
public Instruction Create (OpCode opcode, ParameterDefinition parameter)
|
||||
{
|
||||
return Instruction.Create (opcode, parameter);
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode)
|
||||
{
|
||||
Append (Create (opcode));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, TypeReference type)
|
||||
{
|
||||
Append (Create (opcode, type));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, MethodReference method)
|
||||
{
|
||||
Append (Create (opcode, method));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, CallSite site)
|
||||
{
|
||||
Append (Create (opcode, site));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, FieldReference field)
|
||||
{
|
||||
Append (Create (opcode, field));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, string value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, byte value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, sbyte value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, int value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, long value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, float value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, double value)
|
||||
{
|
||||
Append (Create (opcode, value));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, Instruction target)
|
||||
{
|
||||
Append (Create (opcode, target));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, Instruction [] targets)
|
||||
{
|
||||
Append (Create (opcode, targets));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, VariableDefinition variable)
|
||||
{
|
||||
Append (Create (opcode, variable));
|
||||
}
|
||||
|
||||
public void Emit (OpCode opcode, ParameterDefinition parameter)
|
||||
{
|
||||
Append (Create (opcode, parameter));
|
||||
}
|
||||
|
||||
public void InsertBefore (Instruction target, Instruction instruction)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException ("target");
|
||||
if (instruction == null)
|
||||
throw new ArgumentNullException ("instruction");
|
||||
|
||||
var index = instructions.IndexOf (target);
|
||||
if (index == -1)
|
||||
throw new ArgumentOutOfRangeException ("target");
|
||||
|
||||
instructions.Insert (index, instruction);
|
||||
}
|
||||
|
||||
public void InsertAfter (Instruction target, Instruction instruction)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException ("target");
|
||||
if (instruction == null)
|
||||
throw new ArgumentNullException ("instruction");
|
||||
|
||||
var index = instructions.IndexOf (target);
|
||||
if (index == -1)
|
||||
throw new ArgumentOutOfRangeException ("target");
|
||||
|
||||
instructions.Insert (index + 1, instruction);
|
||||
}
|
||||
|
||||
public void Append (Instruction instruction)
|
||||
{
|
||||
if (instruction == null)
|
||||
throw new ArgumentNullException ("instruction");
|
||||
|
||||
instructions.Add (instruction);
|
||||
}
|
||||
|
||||
public void Replace (Instruction target, Instruction instruction)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException ("target");
|
||||
if (instruction == null)
|
||||
throw new ArgumentNullException ("instruction");
|
||||
|
||||
InsertAfter (target, instruction);
|
||||
Remove (target);
|
||||
}
|
||||
|
||||
public void Remove (Instruction instruction)
|
||||
{
|
||||
if (instruction == null)
|
||||
throw new ArgumentNullException ("instruction");
|
||||
|
||||
if (!instructions.Remove (instruction))
|
||||
throw new ArgumentOutOfRangeException ("instruction");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class Instruction {
|
||||
|
||||
internal int offset;
|
||||
internal OpCode opcode;
|
||||
internal object operand;
|
||||
|
||||
internal Instruction previous;
|
||||
internal Instruction next;
|
||||
|
||||
public int Offset {
|
||||
get { return offset; }
|
||||
set { offset = value; }
|
||||
}
|
||||
|
||||
public OpCode OpCode {
|
||||
get { return opcode; }
|
||||
set { opcode = value; }
|
||||
}
|
||||
|
||||
public object Operand {
|
||||
get { return operand; }
|
||||
set { operand = value; }
|
||||
}
|
||||
|
||||
public Instruction Previous {
|
||||
get { return previous; }
|
||||
set { previous = value; }
|
||||
}
|
||||
|
||||
public Instruction Next {
|
||||
get { return next; }
|
||||
set { next = value; }
|
||||
}
|
||||
|
||||
internal Instruction (int offset, OpCode opCode)
|
||||
{
|
||||
this.offset = offset;
|
||||
this.opcode = opCode;
|
||||
}
|
||||
|
||||
internal Instruction (OpCode opcode, object operand)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
public int GetSize ()
|
||||
{
|
||||
int size = opcode.Size;
|
||||
|
||||
switch (opcode.OperandType) {
|
||||
case OperandType.InlineSwitch:
|
||||
return size + (1 + ((Instruction []) operand).Length) * 4;
|
||||
case OperandType.InlineI8:
|
||||
case OperandType.InlineR:
|
||||
return size + 8;
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.InlineField:
|
||||
case OperandType.InlineI:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineString:
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.ShortInlineR:
|
||||
case OperandType.InlineSig:
|
||||
return size + 4;
|
||||
case OperandType.InlineArg:
|
||||
case OperandType.InlineVar:
|
||||
return size + 2;
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.ShortInlineI:
|
||||
case OperandType.ShortInlineArg:
|
||||
case OperandType.ShortInlineVar:
|
||||
return size + 1;
|
||||
default:
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var instruction = new StringBuilder ();
|
||||
|
||||
AppendLabel (instruction, this);
|
||||
instruction.Append (':');
|
||||
instruction.Append (' ');
|
||||
instruction.Append (opcode.Name);
|
||||
|
||||
if (operand == null)
|
||||
return instruction.ToString ();
|
||||
|
||||
instruction.Append (' ');
|
||||
|
||||
switch (opcode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
AppendLabel (instruction, (Instruction) operand);
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var labels = (Instruction []) operand;
|
||||
for (int i = 0; i < labels.Length; i++) {
|
||||
if (i > 0)
|
||||
instruction.Append (',');
|
||||
|
||||
AppendLabel (instruction, labels [i]);
|
||||
}
|
||||
break;
|
||||
case OperandType.InlineString:
|
||||
instruction.Append ('\"');
|
||||
instruction.Append (operand);
|
||||
instruction.Append ('\"');
|
||||
break;
|
||||
default:
|
||||
instruction.Append (operand);
|
||||
break;
|
||||
}
|
||||
|
||||
return instruction.ToString ();
|
||||
}
|
||||
|
||||
static void AppendLabel (StringBuilder builder, Instruction instruction)
|
||||
{
|
||||
builder.Append ("IL_");
|
||||
builder.Append (instruction.offset.ToString ("x4"));
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.InlineNone)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, null);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, TypeReference type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException ("type");
|
||||
if (opcode.OperandType != OperandType.InlineType &&
|
||||
opcode.OperandType != OperandType.InlineTok)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, type);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, CallSite site)
|
||||
{
|
||||
if (site == null)
|
||||
throw new ArgumentNullException ("site");
|
||||
if (opcode.Code != Code.Calli)
|
||||
throw new ArgumentException ("code");
|
||||
|
||||
return new Instruction (opcode, site);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, MethodReference method)
|
||||
{
|
||||
if (method == null)
|
||||
throw new ArgumentNullException ("method");
|
||||
if (opcode.OperandType != OperandType.InlineMethod &&
|
||||
opcode.OperandType != OperandType.InlineTok)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, method);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, FieldReference field)
|
||||
{
|
||||
if (field == null)
|
||||
throw new ArgumentNullException ("field");
|
||||
if (opcode.OperandType != OperandType.InlineField &&
|
||||
opcode.OperandType != OperandType.InlineTok)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, field);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, string value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
if (opcode.OperandType != OperandType.InlineString)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, sbyte value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.ShortInlineI &&
|
||||
opcode != OpCodes.Ldc_I4_S)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, byte value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.ShortInlineI ||
|
||||
opcode == OpCodes.Ldc_I4_S)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, int value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.InlineI)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, long value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.InlineI8)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, float value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.ShortInlineR)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, double value)
|
||||
{
|
||||
if (opcode.OperandType != OperandType.InlineR)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, value);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, Instruction target)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException ("target");
|
||||
if (opcode.OperandType != OperandType.InlineBrTarget &&
|
||||
opcode.OperandType != OperandType.ShortInlineBrTarget)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, target);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, Instruction [] targets)
|
||||
{
|
||||
if (targets == null)
|
||||
throw new ArgumentNullException ("targets");
|
||||
if (opcode.OperandType != OperandType.InlineSwitch)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, targets);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, VariableDefinition variable)
|
||||
{
|
||||
if (variable == null)
|
||||
throw new ArgumentNullException ("variable");
|
||||
if (opcode.OperandType != OperandType.ShortInlineVar &&
|
||||
opcode.OperandType != OperandType.InlineVar)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, variable);
|
||||
}
|
||||
|
||||
public static Instruction Create (OpCode opcode, ParameterDefinition parameter)
|
||||
{
|
||||
if (parameter == null)
|
||||
throw new ArgumentNullException ("parameter");
|
||||
if (opcode.OperandType != OperandType.ShortInlineArg &&
|
||||
opcode.OperandType != OperandType.InlineArg)
|
||||
throw new ArgumentException ("opcode");
|
||||
|
||||
return new Instruction (opcode, parameter);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class MethodBody {
|
||||
|
||||
readonly internal MethodDefinition method;
|
||||
|
||||
internal ParameterDefinition this_parameter;
|
||||
internal int max_stack_size;
|
||||
internal int code_size;
|
||||
internal bool init_locals;
|
||||
internal MetadataToken local_var_token;
|
||||
|
||||
internal Collection<Instruction> instructions;
|
||||
internal Collection<ExceptionHandler> exceptions;
|
||||
internal Collection<VariableDefinition> variables;
|
||||
|
||||
public MethodDefinition Method {
|
||||
get { return method; }
|
||||
}
|
||||
|
||||
public int MaxStackSize {
|
||||
get { return max_stack_size; }
|
||||
set { max_stack_size = value; }
|
||||
}
|
||||
|
||||
public int CodeSize {
|
||||
get { return code_size; }
|
||||
}
|
||||
|
||||
public bool InitLocals {
|
||||
get { return init_locals; }
|
||||
set { init_locals = value; }
|
||||
}
|
||||
|
||||
public MetadataToken LocalVarToken {
|
||||
get { return local_var_token; }
|
||||
set { local_var_token = value; }
|
||||
}
|
||||
|
||||
public Collection<Instruction> Instructions {
|
||||
get { return instructions ?? (instructions = new InstructionCollection (method)); }
|
||||
}
|
||||
|
||||
public bool HasExceptionHandlers {
|
||||
get { return !exceptions.IsNullOrEmpty (); }
|
||||
}
|
||||
|
||||
public Collection<ExceptionHandler> ExceptionHandlers {
|
||||
get { return exceptions ?? (exceptions = new Collection<ExceptionHandler> ()); }
|
||||
}
|
||||
|
||||
public bool HasVariables {
|
||||
get { return !variables.IsNullOrEmpty (); }
|
||||
}
|
||||
|
||||
public Collection<VariableDefinition> Variables {
|
||||
get { return variables ?? (variables = new VariableDefinitionCollection ()); }
|
||||
}
|
||||
|
||||
public ParameterDefinition ThisParameter {
|
||||
get {
|
||||
if (method == null || method.DeclaringType == null)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
if (!method.HasThis)
|
||||
return null;
|
||||
|
||||
if (this_parameter == null)
|
||||
Interlocked.CompareExchange (ref this_parameter, CreateThisParameter (method), null);
|
||||
|
||||
return this_parameter;
|
||||
}
|
||||
}
|
||||
|
||||
static ParameterDefinition CreateThisParameter (MethodDefinition method)
|
||||
{
|
||||
var parameter_type = method.DeclaringType as TypeReference;
|
||||
|
||||
if (parameter_type.HasGenericParameters) {
|
||||
var instance = new GenericInstanceType (parameter_type);
|
||||
for (int i = 0; i < parameter_type.GenericParameters.Count; i++)
|
||||
instance.GenericArguments.Add (parameter_type.GenericParameters [i]);
|
||||
|
||||
parameter_type = instance;
|
||||
|
||||
}
|
||||
|
||||
if (parameter_type.IsValueType || parameter_type.IsPrimitive)
|
||||
parameter_type = new ByReferenceType (parameter_type);
|
||||
|
||||
return new ParameterDefinition (parameter_type, method);
|
||||
}
|
||||
|
||||
public MethodBody (MethodDefinition method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public ILProcessor GetILProcessor ()
|
||||
{
|
||||
return new ILProcessor (this);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class VariableDefinitionCollection : Collection<VariableDefinition> {
|
||||
|
||||
internal VariableDefinitionCollection ()
|
||||
{
|
||||
}
|
||||
|
||||
internal VariableDefinitionCollection (int capacity)
|
||||
: base (capacity)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnAdd (VariableDefinition item, int index)
|
||||
{
|
||||
item.index = index;
|
||||
}
|
||||
|
||||
protected override void OnInsert (VariableDefinition item, int index)
|
||||
{
|
||||
item.index = index;
|
||||
|
||||
for (int i = index; i < size; i++)
|
||||
items [i].index = i + 1;
|
||||
}
|
||||
|
||||
protected override void OnSet (VariableDefinition item, int index)
|
||||
{
|
||||
item.index = index;
|
||||
}
|
||||
|
||||
protected override void OnRemove (VariableDefinition item, int index)
|
||||
{
|
||||
item.index = -1;
|
||||
|
||||
for (int i = index + 1; i < size; i++)
|
||||
items [i].index = i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
class InstructionCollection : Collection<Instruction> {
|
||||
|
||||
readonly MethodDefinition method;
|
||||
|
||||
internal InstructionCollection (MethodDefinition method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
internal InstructionCollection (MethodDefinition method, int capacity)
|
||||
: base (capacity)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
protected override void OnAdd (Instruction item, int index)
|
||||
{
|
||||
if (index == 0)
|
||||
return;
|
||||
|
||||
var previous = items [index - 1];
|
||||
previous.next = item;
|
||||
item.previous = previous;
|
||||
}
|
||||
|
||||
protected override void OnInsert (Instruction item, int index)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
var current = items [index];
|
||||
if (current == null) {
|
||||
var last = items [index - 1];
|
||||
last.next = item;
|
||||
item.previous = last;
|
||||
return;
|
||||
}
|
||||
|
||||
var previous = current.previous;
|
||||
if (previous != null) {
|
||||
previous.next = item;
|
||||
item.previous = previous;
|
||||
}
|
||||
|
||||
current.previous = item;
|
||||
item.next = current;
|
||||
}
|
||||
|
||||
protected override void OnSet (Instruction item, int index)
|
||||
{
|
||||
var current = items [index];
|
||||
|
||||
item.previous = current.previous;
|
||||
item.next = current.next;
|
||||
|
||||
current.previous = null;
|
||||
current.next = null;
|
||||
}
|
||||
|
||||
protected override void OnRemove (Instruction item, int index)
|
||||
{
|
||||
var previous = item.previous;
|
||||
if (previous != null)
|
||||
previous.next = item.next;
|
||||
|
||||
var next = item.next;
|
||||
if (next != null)
|
||||
next.previous = item.previous;
|
||||
|
||||
RemoveSequencePoint (item);
|
||||
|
||||
item.previous = null;
|
||||
item.next = null;
|
||||
}
|
||||
|
||||
void RemoveSequencePoint (Instruction instruction)
|
||||
{
|
||||
var debug_info = method.debug_info;
|
||||
if (debug_info == null || !debug_info.HasSequencePoints)
|
||||
return;
|
||||
|
||||
var sequence_points = debug_info.sequence_points;
|
||||
for (int i = 0; i < sequence_points.Count; i++) {
|
||||
if (sequence_points [i].Offset == instruction.offset) {
|
||||
sequence_points.RemoveAt (i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,439 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public enum FlowControl {
|
||||
Branch,
|
||||
Break,
|
||||
Call,
|
||||
Cond_Branch,
|
||||
Meta,
|
||||
Next,
|
||||
Phi,
|
||||
Return,
|
||||
Throw,
|
||||
}
|
||||
|
||||
public enum OpCodeType {
|
||||
Annotation,
|
||||
Macro,
|
||||
Nternal,
|
||||
Objmodel,
|
||||
Prefix,
|
||||
Primitive,
|
||||
}
|
||||
|
||||
public enum OperandType {
|
||||
InlineBrTarget,
|
||||
InlineField,
|
||||
InlineI,
|
||||
InlineI8,
|
||||
InlineMethod,
|
||||
InlineNone,
|
||||
InlinePhi,
|
||||
InlineR,
|
||||
InlineSig,
|
||||
InlineString,
|
||||
InlineSwitch,
|
||||
InlineTok,
|
||||
InlineType,
|
||||
InlineVar,
|
||||
InlineArg,
|
||||
ShortInlineBrTarget,
|
||||
ShortInlineI,
|
||||
ShortInlineR,
|
||||
ShortInlineVar,
|
||||
ShortInlineArg,
|
||||
}
|
||||
|
||||
public enum StackBehaviour {
|
||||
Pop0,
|
||||
Pop1,
|
||||
Pop1_pop1,
|
||||
Popi,
|
||||
Popi_pop1,
|
||||
Popi_popi,
|
||||
Popi_popi8,
|
||||
Popi_popi_popi,
|
||||
Popi_popr4,
|
||||
Popi_popr8,
|
||||
Popref,
|
||||
Popref_pop1,
|
||||
Popref_popi,
|
||||
Popref_popi_popi,
|
||||
Popref_popi_popi8,
|
||||
Popref_popi_popr4,
|
||||
Popref_popi_popr8,
|
||||
Popref_popi_popref,
|
||||
PopAll,
|
||||
Push0,
|
||||
Push1,
|
||||
Push1_push1,
|
||||
Pushi,
|
||||
Pushi8,
|
||||
Pushr4,
|
||||
Pushr8,
|
||||
Pushref,
|
||||
Varpop,
|
||||
Varpush,
|
||||
}
|
||||
|
||||
public struct OpCode : IEquatable<OpCode> {
|
||||
|
||||
readonly byte op1;
|
||||
readonly byte op2;
|
||||
readonly byte code;
|
||||
readonly byte flow_control;
|
||||
readonly byte opcode_type;
|
||||
readonly byte operand_type;
|
||||
readonly byte stack_behavior_pop;
|
||||
readonly byte stack_behavior_push;
|
||||
|
||||
public string Name {
|
||||
get { return OpCodeNames.names [(int) Code]; }
|
||||
}
|
||||
|
||||
public int Size {
|
||||
get { return op1 == 0xff ? 1 : 2; }
|
||||
}
|
||||
|
||||
public byte Op1 {
|
||||
get { return op1; }
|
||||
}
|
||||
|
||||
public byte Op2 {
|
||||
get { return op2; }
|
||||
}
|
||||
|
||||
public short Value {
|
||||
get { return op1 == 0xff ? op2 : (short) ((op1 << 8) | op2); }
|
||||
}
|
||||
|
||||
public Code Code {
|
||||
get { return (Code) code; }
|
||||
}
|
||||
|
||||
public FlowControl FlowControl {
|
||||
get { return (FlowControl) flow_control; }
|
||||
}
|
||||
|
||||
public OpCodeType OpCodeType {
|
||||
get { return (OpCodeType) opcode_type; }
|
||||
}
|
||||
|
||||
public OperandType OperandType {
|
||||
get { return (OperandType) operand_type; }
|
||||
}
|
||||
|
||||
public StackBehaviour StackBehaviourPop {
|
||||
get { return (StackBehaviour) stack_behavior_pop; }
|
||||
}
|
||||
|
||||
public StackBehaviour StackBehaviourPush {
|
||||
get { return (StackBehaviour) stack_behavior_push; }
|
||||
}
|
||||
|
||||
internal OpCode (int x, int y)
|
||||
{
|
||||
this.op1 = (byte) ((x >> 0) & 0xff);
|
||||
this.op2 = (byte) ((x >> 8) & 0xff);
|
||||
this.code = (byte) ((x >> 16) & 0xff);
|
||||
this.flow_control = (byte) ((x >> 24) & 0xff);
|
||||
|
||||
this.opcode_type = (byte) ((y >> 0) & 0xff);
|
||||
this.operand_type = (byte) ((y >> 8) & 0xff);
|
||||
this.stack_behavior_pop = (byte) ((y >> 16) & 0xff);
|
||||
this.stack_behavior_push = (byte) ((y >> 24) & 0xff);
|
||||
|
||||
if (op1 == 0xff)
|
||||
OpCodes.OneByteOpCode [op2] = this;
|
||||
else
|
||||
OpCodes.TwoBytesOpCode [op2] = this;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (!(obj is OpCode))
|
||||
return false;
|
||||
|
||||
var opcode = (OpCode) obj;
|
||||
return op1 == opcode.op1 && op2 == opcode.op2;
|
||||
}
|
||||
|
||||
public bool Equals (OpCode opcode)
|
||||
{
|
||||
return op1 == opcode.op1 && op2 == opcode.op2;
|
||||
}
|
||||
|
||||
public static bool operator == (OpCode one, OpCode other)
|
||||
{
|
||||
return one.op1 == other.op1 && one.op2 == other.op2;
|
||||
}
|
||||
|
||||
public static bool operator != (OpCode one, OpCode other)
|
||||
{
|
||||
return one.op1 != other.op1 || one.op2 != other.op2;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
static class OpCodeNames {
|
||||
|
||||
internal static readonly string [] names;
|
||||
|
||||
static OpCodeNames ()
|
||||
{
|
||||
var table = new byte [] {
|
||||
3, 110, 111, 112,
|
||||
5, 98, 114, 101, 97, 107,
|
||||
7, 108, 100, 97, 114, 103, 46, 48,
|
||||
7, 108, 100, 97, 114, 103, 46, 49,
|
||||
7, 108, 100, 97, 114, 103, 46, 50,
|
||||
7, 108, 100, 97, 114, 103, 46, 51,
|
||||
7, 108, 100, 108, 111, 99, 46, 48,
|
||||
7, 108, 100, 108, 111, 99, 46, 49,
|
||||
7, 108, 100, 108, 111, 99, 46, 50,
|
||||
7, 108, 100, 108, 111, 99, 46, 51,
|
||||
7, 115, 116, 108, 111, 99, 46, 48,
|
||||
7, 115, 116, 108, 111, 99, 46, 49,
|
||||
7, 115, 116, 108, 111, 99, 46, 50,
|
||||
7, 115, 116, 108, 111, 99, 46, 51,
|
||||
7, 108, 100, 97, 114, 103, 46, 115,
|
||||
8, 108, 100, 97, 114, 103, 97, 46, 115,
|
||||
7, 115, 116, 97, 114, 103, 46, 115,
|
||||
7, 108, 100, 108, 111, 99, 46, 115,
|
||||
8, 108, 100, 108, 111, 99, 97, 46, 115,
|
||||
7, 115, 116, 108, 111, 99, 46, 115,
|
||||
6, 108, 100, 110, 117, 108, 108,
|
||||
9, 108, 100, 99, 46, 105, 52, 46, 109, 49,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 48,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 49,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 50,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 51,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 52,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 53,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 54,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 55,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 56,
|
||||
8, 108, 100, 99, 46, 105, 52, 46, 115,
|
||||
6, 108, 100, 99, 46, 105, 52,
|
||||
6, 108, 100, 99, 46, 105, 56,
|
||||
6, 108, 100, 99, 46, 114, 52,
|
||||
6, 108, 100, 99, 46, 114, 56,
|
||||
3, 100, 117, 112,
|
||||
3, 112, 111, 112,
|
||||
3, 106, 109, 112,
|
||||
4, 99, 97, 108, 108,
|
||||
5, 99, 97, 108, 108, 105,
|
||||
3, 114, 101, 116,
|
||||
4, 98, 114, 46, 115,
|
||||
9, 98, 114, 102, 97, 108, 115, 101, 46, 115,
|
||||
8, 98, 114, 116, 114, 117, 101, 46, 115,
|
||||
5, 98, 101, 113, 46, 115,
|
||||
5, 98, 103, 101, 46, 115,
|
||||
5, 98, 103, 116, 46, 115,
|
||||
5, 98, 108, 101, 46, 115,
|
||||
5, 98, 108, 116, 46, 115,
|
||||
8, 98, 110, 101, 46, 117, 110, 46, 115,
|
||||
8, 98, 103, 101, 46, 117, 110, 46, 115,
|
||||
8, 98, 103, 116, 46, 117, 110, 46, 115,
|
||||
8, 98, 108, 101, 46, 117, 110, 46, 115,
|
||||
8, 98, 108, 116, 46, 117, 110, 46, 115,
|
||||
2, 98, 114,
|
||||
7, 98, 114, 102, 97, 108, 115, 101,
|
||||
6, 98, 114, 116, 114, 117, 101,
|
||||
3, 98, 101, 113,
|
||||
3, 98, 103, 101,
|
||||
3, 98, 103, 116,
|
||||
3, 98, 108, 101,
|
||||
3, 98, 108, 116,
|
||||
6, 98, 110, 101, 46, 117, 110,
|
||||
6, 98, 103, 101, 46, 117, 110,
|
||||
6, 98, 103, 116, 46, 117, 110,
|
||||
6, 98, 108, 101, 46, 117, 110,
|
||||
6, 98, 108, 116, 46, 117, 110,
|
||||
6, 115, 119, 105, 116, 99, 104,
|
||||
8, 108, 100, 105, 110, 100, 46, 105, 49,
|
||||
8, 108, 100, 105, 110, 100, 46, 117, 49,
|
||||
8, 108, 100, 105, 110, 100, 46, 105, 50,
|
||||
8, 108, 100, 105, 110, 100, 46, 117, 50,
|
||||
8, 108, 100, 105, 110, 100, 46, 105, 52,
|
||||
8, 108, 100, 105, 110, 100, 46, 117, 52,
|
||||
8, 108, 100, 105, 110, 100, 46, 105, 56,
|
||||
7, 108, 100, 105, 110, 100, 46, 105,
|
||||
8, 108, 100, 105, 110, 100, 46, 114, 52,
|
||||
8, 108, 100, 105, 110, 100, 46, 114, 56,
|
||||
9, 108, 100, 105, 110, 100, 46, 114, 101, 102,
|
||||
9, 115, 116, 105, 110, 100, 46, 114, 101, 102,
|
||||
8, 115, 116, 105, 110, 100, 46, 105, 49,
|
||||
8, 115, 116, 105, 110, 100, 46, 105, 50,
|
||||
8, 115, 116, 105, 110, 100, 46, 105, 52,
|
||||
8, 115, 116, 105, 110, 100, 46, 105, 56,
|
||||
8, 115, 116, 105, 110, 100, 46, 114, 52,
|
||||
8, 115, 116, 105, 110, 100, 46, 114, 56,
|
||||
3, 97, 100, 100,
|
||||
3, 115, 117, 98,
|
||||
3, 109, 117, 108,
|
||||
3, 100, 105, 118,
|
||||
6, 100, 105, 118, 46, 117, 110,
|
||||
3, 114, 101, 109,
|
||||
6, 114, 101, 109, 46, 117, 110,
|
||||
3, 97, 110, 100,
|
||||
2, 111, 114,
|
||||
3, 120, 111, 114,
|
||||
3, 115, 104, 108,
|
||||
3, 115, 104, 114,
|
||||
6, 115, 104, 114, 46, 117, 110,
|
||||
3, 110, 101, 103,
|
||||
3, 110, 111, 116,
|
||||
7, 99, 111, 110, 118, 46, 105, 49,
|
||||
7, 99, 111, 110, 118, 46, 105, 50,
|
||||
7, 99, 111, 110, 118, 46, 105, 52,
|
||||
7, 99, 111, 110, 118, 46, 105, 56,
|
||||
7, 99, 111, 110, 118, 46, 114, 52,
|
||||
7, 99, 111, 110, 118, 46, 114, 56,
|
||||
7, 99, 111, 110, 118, 46, 117, 52,
|
||||
7, 99, 111, 110, 118, 46, 117, 56,
|
||||
8, 99, 97, 108, 108, 118, 105, 114, 116,
|
||||
5, 99, 112, 111, 98, 106,
|
||||
5, 108, 100, 111, 98, 106,
|
||||
5, 108, 100, 115, 116, 114,
|
||||
6, 110, 101, 119, 111, 98, 106,
|
||||
9, 99, 97, 115, 116, 99, 108, 97, 115, 115,
|
||||
6, 105, 115, 105, 110, 115, 116,
|
||||
9, 99, 111, 110, 118, 46, 114, 46, 117, 110,
|
||||
5, 117, 110, 98, 111, 120,
|
||||
5, 116, 104, 114, 111, 119,
|
||||
5, 108, 100, 102, 108, 100,
|
||||
6, 108, 100, 102, 108, 100, 97,
|
||||
5, 115, 116, 102, 108, 100,
|
||||
6, 108, 100, 115, 102, 108, 100,
|
||||
7, 108, 100, 115, 102, 108, 100, 97,
|
||||
6, 115, 116, 115, 102, 108, 100,
|
||||
5, 115, 116, 111, 98, 106,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 46, 117, 110,
|
||||
14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 46, 117, 110,
|
||||
13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 46, 117, 110,
|
||||
13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 46, 117, 110,
|
||||
3, 98, 111, 120,
|
||||
6, 110, 101, 119, 97, 114, 114,
|
||||
5, 108, 100, 108, 101, 110,
|
||||
7, 108, 100, 101, 108, 101, 109, 97,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 105, 49,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 117, 49,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 105, 50,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 117, 50,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 105, 52,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 117, 52,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 105, 56,
|
||||
8, 108, 100, 101, 108, 101, 109, 46, 105,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 114, 52,
|
||||
9, 108, 100, 101, 108, 101, 109, 46, 114, 56,
|
||||
10, 108, 100, 101, 108, 101, 109, 46, 114, 101, 102,
|
||||
8, 115, 116, 101, 108, 101, 109, 46, 105,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 105, 49,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 105, 50,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 105, 52,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 105, 56,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 114, 52,
|
||||
9, 115, 116, 101, 108, 101, 109, 46, 114, 56,
|
||||
10, 115, 116, 101, 108, 101, 109, 46, 114, 101, 102,
|
||||
10, 108, 100, 101, 108, 101, 109, 46, 97, 110, 121,
|
||||
10, 115, 116, 101, 108, 101, 109, 46, 97, 110, 121,
|
||||
9, 117, 110, 98, 111, 120, 46, 97, 110, 121,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56,
|
||||
11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56,
|
||||
9, 114, 101, 102, 97, 110, 121, 118, 97, 108,
|
||||
8, 99, 107, 102, 105, 110, 105, 116, 101,
|
||||
8, 109, 107, 114, 101, 102, 97, 110, 121,
|
||||
7, 108, 100, 116, 111, 107, 101, 110,
|
||||
7, 99, 111, 110, 118, 46, 117, 50,
|
||||
7, 99, 111, 110, 118, 46, 117, 49,
|
||||
6, 99, 111, 110, 118, 46, 105,
|
||||
10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105,
|
||||
10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117,
|
||||
7, 97, 100, 100, 46, 111, 118, 102,
|
||||
10, 97, 100, 100, 46, 111, 118, 102, 46, 117, 110,
|
||||
7, 109, 117, 108, 46, 111, 118, 102,
|
||||
10, 109, 117, 108, 46, 111, 118, 102, 46, 117, 110,
|
||||
7, 115, 117, 98, 46, 111, 118, 102,
|
||||
10, 115, 117, 98, 46, 111, 118, 102, 46, 117, 110,
|
||||
10, 101, 110, 100, 102, 105, 110, 97, 108, 108, 121,
|
||||
5, 108, 101, 97, 118, 101,
|
||||
7, 108, 101, 97, 118, 101, 46, 115,
|
||||
7, 115, 116, 105, 110, 100, 46, 105,
|
||||
6, 99, 111, 110, 118, 46, 117,
|
||||
7, 97, 114, 103, 108, 105, 115, 116,
|
||||
3, 99, 101, 113,
|
||||
3, 99, 103, 116,
|
||||
6, 99, 103, 116, 46, 117, 110,
|
||||
3, 99, 108, 116,
|
||||
6, 99, 108, 116, 46, 117, 110,
|
||||
5, 108, 100, 102, 116, 110,
|
||||
9, 108, 100, 118, 105, 114, 116, 102, 116, 110,
|
||||
5, 108, 100, 97, 114, 103,
|
||||
6, 108, 100, 97, 114, 103, 97,
|
||||
5, 115, 116, 97, 114, 103,
|
||||
5, 108, 100, 108, 111, 99,
|
||||
6, 108, 100, 108, 111, 99, 97,
|
||||
5, 115, 116, 108, 111, 99,
|
||||
8, 108, 111, 99, 97, 108, 108, 111, 99,
|
||||
9, 101, 110, 100, 102, 105, 108, 116, 101, 114,
|
||||
10, 117, 110, 97, 108, 105, 103, 110, 101, 100, 46,
|
||||
9, 118, 111, 108, 97, 116, 105, 108, 101, 46,
|
||||
5, 116, 97, 105, 108, 46,
|
||||
7, 105, 110, 105, 116, 111, 98, 106,
|
||||
12, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 46,
|
||||
5, 99, 112, 98, 108, 107,
|
||||
7, 105, 110, 105, 116, 98, 108, 107,
|
||||
3, 110, 111, 46,
|
||||
7, 114, 101, 116, 104, 114, 111, 119,
|
||||
6, 115, 105, 122, 101, 111, 102,
|
||||
10, 114, 101, 102, 97, 110, 121, 116, 121, 112, 101,
|
||||
9, 114, 101, 97, 100, 111, 110, 108, 121, 46,
|
||||
};
|
||||
|
||||
names = new string [219];
|
||||
|
||||
for (int i = 0, p = 0; i < names.Length; i++) {
|
||||
var buffer = new char [table [p++]];
|
||||
|
||||
for (int j = 0; j < buffer.Length; j++)
|
||||
buffer [j] = (char) table [p++];
|
||||
|
||||
names [i] = new string (buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,894 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public static class OpCodes {
|
||||
|
||||
internal static readonly OpCode [] OneByteOpCode = new OpCode [0xe0 + 1];
|
||||
internal static readonly OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1];
|
||||
|
||||
public static readonly OpCode Nop = new OpCode (
|
||||
0xff << 0 | 0x00 << 8 | (byte) Code.Nop << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Break = new OpCode (
|
||||
0xff << 0 | 0x01 << 8 | (byte) Code.Break << 16 | (byte) FlowControl.Break << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldarg_0 = new OpCode (
|
||||
0xff << 0 | 0x02 << 8 | (byte) Code.Ldarg_0 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldarg_1 = new OpCode (
|
||||
0xff << 0 | 0x03 << 8 | (byte) Code.Ldarg_1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldarg_2 = new OpCode (
|
||||
0xff << 0 | 0x04 << 8 | (byte) Code.Ldarg_2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldarg_3 = new OpCode (
|
||||
0xff << 0 | 0x05 << 8 | (byte) Code.Ldarg_3 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc_0 = new OpCode (
|
||||
0xff << 0 | 0x06 << 8 | (byte) Code.Ldloc_0 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc_1 = new OpCode (
|
||||
0xff << 0 | 0x07 << 8 | (byte) Code.Ldloc_1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc_2 = new OpCode (
|
||||
0xff << 0 | 0x08 << 8 | (byte) Code.Ldloc_2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc_3 = new OpCode (
|
||||
0xff << 0 | 0x09 << 8 | (byte) Code.Ldloc_3 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Stloc_0 = new OpCode (
|
||||
0xff << 0 | 0x0a << 8 | (byte) Code.Stloc_0 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stloc_1 = new OpCode (
|
||||
0xff << 0 | 0x0b << 8 | (byte) Code.Stloc_1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stloc_2 = new OpCode (
|
||||
0xff << 0 | 0x0c << 8 | (byte) Code.Stloc_2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stloc_3 = new OpCode (
|
||||
0xff << 0 | 0x0d << 8 | (byte) Code.Stloc_3 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldarg_S = new OpCode (
|
||||
0xff << 0 | 0x0e << 8 | (byte) Code.Ldarg_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldarga_S = new OpCode (
|
||||
0xff << 0 | 0x0f << 8 | (byte) Code.Ldarga_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Starg_S = new OpCode (
|
||||
0xff << 0 | 0x10 << 8 | (byte) Code.Starg_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc_S = new OpCode (
|
||||
0xff << 0 | 0x11 << 8 | (byte) Code.Ldloc_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloca_S = new OpCode (
|
||||
0xff << 0 | 0x12 << 8 | (byte) Code.Ldloca_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Stloc_S = new OpCode (
|
||||
0xff << 0 | 0x13 << 8 | (byte) Code.Stloc_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldnull = new OpCode (
|
||||
0xff << 0 | 0x14 << 8 | (byte) Code.Ldnull << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_M1 = new OpCode (
|
||||
0xff << 0 | 0x15 << 8 | (byte) Code.Ldc_I4_M1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_0 = new OpCode (
|
||||
0xff << 0 | 0x16 << 8 | (byte) Code.Ldc_I4_0 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_1 = new OpCode (
|
||||
0xff << 0 | 0x17 << 8 | (byte) Code.Ldc_I4_1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_2 = new OpCode (
|
||||
0xff << 0 | 0x18 << 8 | (byte) Code.Ldc_I4_2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_3 = new OpCode (
|
||||
0xff << 0 | 0x19 << 8 | (byte) Code.Ldc_I4_3 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_4 = new OpCode (
|
||||
0xff << 0 | 0x1a << 8 | (byte) Code.Ldc_I4_4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_5 = new OpCode (
|
||||
0xff << 0 | 0x1b << 8 | (byte) Code.Ldc_I4_5 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_6 = new OpCode (
|
||||
0xff << 0 | 0x1c << 8 | (byte) Code.Ldc_I4_6 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_7 = new OpCode (
|
||||
0xff << 0 | 0x1d << 8 | (byte) Code.Ldc_I4_7 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_8 = new OpCode (
|
||||
0xff << 0 | 0x1e << 8 | (byte) Code.Ldc_I4_8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4_S = new OpCode (
|
||||
0xff << 0 | 0x1f << 8 | (byte) Code.Ldc_I4_S << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I4 = new OpCode (
|
||||
0xff << 0 | 0x20 << 8 | (byte) Code.Ldc_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldc_I8 = new OpCode (
|
||||
0xff << 0 | 0x21 << 8 | (byte) Code.Ldc_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI8 << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Ldc_R4 = new OpCode (
|
||||
0xff << 0 | 0x22 << 8 | (byte) Code.Ldc_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.ShortInlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr4 << 24);
|
||||
|
||||
public static readonly OpCode Ldc_R8 = new OpCode (
|
||||
0xff << 0 | 0x23 << 8 | (byte) Code.Ldc_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Dup = new OpCode (
|
||||
0xff << 0 | 0x25 << 8 | (byte) Code.Dup << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1_push1 << 24);
|
||||
|
||||
public static readonly OpCode Pop = new OpCode (
|
||||
0xff << 0 | 0x26 << 8 | (byte) Code.Pop << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Jmp = new OpCode (
|
||||
0xff << 0 | 0x27 << 8 | (byte) Code.Jmp << 16 | (byte) FlowControl.Call << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Call = new OpCode (
|
||||
0xff << 0 | 0x28 << 8 | (byte) Code.Call << 16 | (byte) FlowControl.Call << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24);
|
||||
|
||||
public static readonly OpCode Calli = new OpCode (
|
||||
0xff << 0 | 0x29 << 8 | (byte) Code.Calli << 16 | (byte) FlowControl.Call << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSig << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24);
|
||||
|
||||
public static readonly OpCode Ret = new OpCode (
|
||||
0xff << 0 | 0x2a << 8 | (byte) Code.Ret << 16 | (byte) FlowControl.Return << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Br_S = new OpCode (
|
||||
0xff << 0 | 0x2b << 8 | (byte) Code.Br_S << 16 | (byte) FlowControl.Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Brfalse_S = new OpCode (
|
||||
0xff << 0 | 0x2c << 8 | (byte) Code.Brfalse_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Brtrue_S = new OpCode (
|
||||
0xff << 0 | 0x2d << 8 | (byte) Code.Brtrue_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Beq_S = new OpCode (
|
||||
0xff << 0 | 0x2e << 8 | (byte) Code.Beq_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bge_S = new OpCode (
|
||||
0xff << 0 | 0x2f << 8 | (byte) Code.Bge_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bgt_S = new OpCode (
|
||||
0xff << 0 | 0x30 << 8 | (byte) Code.Bgt_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ble_S = new OpCode (
|
||||
0xff << 0 | 0x31 << 8 | (byte) Code.Ble_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Blt_S = new OpCode (
|
||||
0xff << 0 | 0x32 << 8 | (byte) Code.Blt_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bne_Un_S = new OpCode (
|
||||
0xff << 0 | 0x33 << 8 | (byte) Code.Bne_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bge_Un_S = new OpCode (
|
||||
0xff << 0 | 0x34 << 8 | (byte) Code.Bge_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bgt_Un_S = new OpCode (
|
||||
0xff << 0 | 0x35 << 8 | (byte) Code.Bgt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ble_Un_S = new OpCode (
|
||||
0xff << 0 | 0x36 << 8 | (byte) Code.Ble_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Blt_Un_S = new OpCode (
|
||||
0xff << 0 | 0x37 << 8 | (byte) Code.Blt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Br = new OpCode (
|
||||
0xff << 0 | 0x38 << 8 | (byte) Code.Br << 16 | (byte) FlowControl.Branch << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Brfalse = new OpCode (
|
||||
0xff << 0 | 0x39 << 8 | (byte) Code.Brfalse << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Brtrue = new OpCode (
|
||||
0xff << 0 | 0x3a << 8 | (byte) Code.Brtrue << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Beq = new OpCode (
|
||||
0xff << 0 | 0x3b << 8 | (byte) Code.Beq << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bge = new OpCode (
|
||||
0xff << 0 | 0x3c << 8 | (byte) Code.Bge << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bgt = new OpCode (
|
||||
0xff << 0 | 0x3d << 8 | (byte) Code.Bgt << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ble = new OpCode (
|
||||
0xff << 0 | 0x3e << 8 | (byte) Code.Ble << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Blt = new OpCode (
|
||||
0xff << 0 | 0x3f << 8 | (byte) Code.Blt << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bne_Un = new OpCode (
|
||||
0xff << 0 | 0x40 << 8 | (byte) Code.Bne_Un << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bge_Un = new OpCode (
|
||||
0xff << 0 | 0x41 << 8 | (byte) Code.Bge_Un << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Bgt_Un = new OpCode (
|
||||
0xff << 0 | 0x42 << 8 | (byte) Code.Bgt_Un << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ble_Un = new OpCode (
|
||||
0xff << 0 | 0x43 << 8 | (byte) Code.Ble_Un << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Blt_Un = new OpCode (
|
||||
0xff << 0 | 0x44 << 8 | (byte) Code.Blt_Un << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Switch = new OpCode (
|
||||
0xff << 0 | 0x45 << 8 | (byte) Code.Switch << 16 | (byte) FlowControl.Cond_Branch << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSwitch << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldind_I1 = new OpCode (
|
||||
0xff << 0 | 0x46 << 8 | (byte) Code.Ldind_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_U1 = new OpCode (
|
||||
0xff << 0 | 0x47 << 8 | (byte) Code.Ldind_U1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_I2 = new OpCode (
|
||||
0xff << 0 | 0x48 << 8 | (byte) Code.Ldind_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_U2 = new OpCode (
|
||||
0xff << 0 | 0x49 << 8 | (byte) Code.Ldind_U2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_I4 = new OpCode (
|
||||
0xff << 0 | 0x4a << 8 | (byte) Code.Ldind_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_U4 = new OpCode (
|
||||
0xff << 0 | 0x4b << 8 | (byte) Code.Ldind_U4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_I8 = new OpCode (
|
||||
0xff << 0 | 0x4c << 8 | (byte) Code.Ldind_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Ldind_I = new OpCode (
|
||||
0xff << 0 | 0x4d << 8 | (byte) Code.Ldind_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldind_R4 = new OpCode (
|
||||
0xff << 0 | 0x4e << 8 | (byte) Code.Ldind_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr4 << 24);
|
||||
|
||||
public static readonly OpCode Ldind_R8 = new OpCode (
|
||||
0xff << 0 | 0x4f << 8 | (byte) Code.Ldind_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Ldind_Ref = new OpCode (
|
||||
0xff << 0 | 0x50 << 8 | (byte) Code.Ldind_Ref << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Stind_Ref = new OpCode (
|
||||
0xff << 0 | 0x51 << 8 | (byte) Code.Stind_Ref << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_I1 = new OpCode (
|
||||
0xff << 0 | 0x52 << 8 | (byte) Code.Stind_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_I2 = new OpCode (
|
||||
0xff << 0 | 0x53 << 8 | (byte) Code.Stind_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_I4 = new OpCode (
|
||||
0xff << 0 | 0x54 << 8 | (byte) Code.Stind_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_I8 = new OpCode (
|
||||
0xff << 0 | 0x55 << 8 | (byte) Code.Stind_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_R4 = new OpCode (
|
||||
0xff << 0 | 0x56 << 8 | (byte) Code.Stind_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_R8 = new OpCode (
|
||||
0xff << 0 | 0x57 << 8 | (byte) Code.Stind_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Add = new OpCode (
|
||||
0xff << 0 | 0x58 << 8 | (byte) Code.Add << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Sub = new OpCode (
|
||||
0xff << 0 | 0x59 << 8 | (byte) Code.Sub << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Mul = new OpCode (
|
||||
0xff << 0 | 0x5a << 8 | (byte) Code.Mul << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Div = new OpCode (
|
||||
0xff << 0 | 0x5b << 8 | (byte) Code.Div << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Div_Un = new OpCode (
|
||||
0xff << 0 | 0x5c << 8 | (byte) Code.Div_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Rem = new OpCode (
|
||||
0xff << 0 | 0x5d << 8 | (byte) Code.Rem << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Rem_Un = new OpCode (
|
||||
0xff << 0 | 0x5e << 8 | (byte) Code.Rem_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode And = new OpCode (
|
||||
0xff << 0 | 0x5f << 8 | (byte) Code.And << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Or = new OpCode (
|
||||
0xff << 0 | 0x60 << 8 | (byte) Code.Or << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Xor = new OpCode (
|
||||
0xff << 0 | 0x61 << 8 | (byte) Code.Xor << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Shl = new OpCode (
|
||||
0xff << 0 | 0x62 << 8 | (byte) Code.Shl << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Shr = new OpCode (
|
||||
0xff << 0 | 0x63 << 8 | (byte) Code.Shr << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Shr_Un = new OpCode (
|
||||
0xff << 0 | 0x64 << 8 | (byte) Code.Shr_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Neg = new OpCode (
|
||||
0xff << 0 | 0x65 << 8 | (byte) Code.Neg << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Not = new OpCode (
|
||||
0xff << 0 | 0x66 << 8 | (byte) Code.Not << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Conv_I1 = new OpCode (
|
||||
0xff << 0 | 0x67 << 8 | (byte) Code.Conv_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_I2 = new OpCode (
|
||||
0xff << 0 | 0x68 << 8 | (byte) Code.Conv_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_I4 = new OpCode (
|
||||
0xff << 0 | 0x69 << 8 | (byte) Code.Conv_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_I8 = new OpCode (
|
||||
0xff << 0 | 0x6a << 8 | (byte) Code.Conv_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Conv_R4 = new OpCode (
|
||||
0xff << 0 | 0x6b << 8 | (byte) Code.Conv_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr4 << 24);
|
||||
|
||||
public static readonly OpCode Conv_R8 = new OpCode (
|
||||
0xff << 0 | 0x6c << 8 | (byte) Code.Conv_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Conv_U4 = new OpCode (
|
||||
0xff << 0 | 0x6d << 8 | (byte) Code.Conv_U4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_U8 = new OpCode (
|
||||
0xff << 0 | 0x6e << 8 | (byte) Code.Conv_U8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Callvirt = new OpCode (
|
||||
0xff << 0 | 0x6f << 8 | (byte) Code.Callvirt << 16 | (byte) FlowControl.Call << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24);
|
||||
|
||||
public static readonly OpCode Cpobj = new OpCode (
|
||||
0xff << 0 | 0x70 << 8 | (byte) Code.Cpobj << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldobj = new OpCode (
|
||||
0xff << 0 | 0x71 << 8 | (byte) Code.Ldobj << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldstr = new OpCode (
|
||||
0xff << 0 | 0x72 << 8 | (byte) Code.Ldstr << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineString << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Newobj = new OpCode (
|
||||
0xff << 0 | 0x73 << 8 | (byte) Code.Newobj << 16 | (byte) FlowControl.Call << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Castclass = new OpCode (
|
||||
0xff << 0 | 0x74 << 8 | (byte) Code.Castclass << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Isinst = new OpCode (
|
||||
0xff << 0 | 0x75 << 8 | (byte) Code.Isinst << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_R_Un = new OpCode (
|
||||
0xff << 0 | 0x76 << 8 | (byte) Code.Conv_R_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Unbox = new OpCode (
|
||||
0xff << 0 | 0x79 << 8 | (byte) Code.Unbox << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Throw = new OpCode (
|
||||
0xff << 0 | 0x7a << 8 | (byte) Code.Throw << 16 | (byte) FlowControl.Throw << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldfld = new OpCode (
|
||||
0xff << 0 | 0x7b << 8 | (byte) Code.Ldfld << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldflda = new OpCode (
|
||||
0xff << 0 | 0x7c << 8 | (byte) Code.Ldflda << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Stfld = new OpCode (
|
||||
0xff << 0 | 0x7d << 8 | (byte) Code.Stfld << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldsfld = new OpCode (
|
||||
0xff << 0 | 0x7e << 8 | (byte) Code.Ldsfld << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldsflda = new OpCode (
|
||||
0xff << 0 | 0x7f << 8 | (byte) Code.Ldsflda << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Stsfld = new OpCode (
|
||||
0xff << 0 | 0x80 << 8 | (byte) Code.Stsfld << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stobj = new OpCode (
|
||||
0xff << 0 | 0x81 << 8 | (byte) Code.Stobj << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I1_Un = new OpCode (
|
||||
0xff << 0 | 0x82 << 8 | (byte) Code.Conv_Ovf_I1_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I2_Un = new OpCode (
|
||||
0xff << 0 | 0x83 << 8 | (byte) Code.Conv_Ovf_I2_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I4_Un = new OpCode (
|
||||
0xff << 0 | 0x84 << 8 | (byte) Code.Conv_Ovf_I4_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I8_Un = new OpCode (
|
||||
0xff << 0 | 0x85 << 8 | (byte) Code.Conv_Ovf_I8_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U1_Un = new OpCode (
|
||||
0xff << 0 | 0x86 << 8 | (byte) Code.Conv_Ovf_U1_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U2_Un = new OpCode (
|
||||
0xff << 0 | 0x87 << 8 | (byte) Code.Conv_Ovf_U2_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U4_Un = new OpCode (
|
||||
0xff << 0 | 0x88 << 8 | (byte) Code.Conv_Ovf_U4_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U8_Un = new OpCode (
|
||||
0xff << 0 | 0x89 << 8 | (byte) Code.Conv_Ovf_U8_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I_Un = new OpCode (
|
||||
0xff << 0 | 0x8a << 8 | (byte) Code.Conv_Ovf_I_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U_Un = new OpCode (
|
||||
0xff << 0 | 0x8b << 8 | (byte) Code.Conv_Ovf_U_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Box = new OpCode (
|
||||
0xff << 0 | 0x8c << 8 | (byte) Code.Box << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Newarr = new OpCode (
|
||||
0xff << 0 | 0x8d << 8 | (byte) Code.Newarr << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Ldlen = new OpCode (
|
||||
0xff << 0 | 0x8e << 8 | (byte) Code.Ldlen << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelema = new OpCode (
|
||||
0xff << 0 | 0x8f << 8 | (byte) Code.Ldelema << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_I1 = new OpCode (
|
||||
0xff << 0 | 0x90 << 8 | (byte) Code.Ldelem_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_U1 = new OpCode (
|
||||
0xff << 0 | 0x91 << 8 | (byte) Code.Ldelem_U1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_I2 = new OpCode (
|
||||
0xff << 0 | 0x92 << 8 | (byte) Code.Ldelem_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_U2 = new OpCode (
|
||||
0xff << 0 | 0x93 << 8 | (byte) Code.Ldelem_U2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_I4 = new OpCode (
|
||||
0xff << 0 | 0x94 << 8 | (byte) Code.Ldelem_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_U4 = new OpCode (
|
||||
0xff << 0 | 0x95 << 8 | (byte) Code.Ldelem_U4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_I8 = new OpCode (
|
||||
0xff << 0 | 0x96 << 8 | (byte) Code.Ldelem_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_I = new OpCode (
|
||||
0xff << 0 | 0x97 << 8 | (byte) Code.Ldelem_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_R4 = new OpCode (
|
||||
0xff << 0 | 0x98 << 8 | (byte) Code.Ldelem_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr4 << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_R8 = new OpCode (
|
||||
0xff << 0 | 0x99 << 8 | (byte) Code.Ldelem_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_Ref = new OpCode (
|
||||
0xff << 0 | 0x9a << 8 | (byte) Code.Ldelem_Ref << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushref << 24);
|
||||
|
||||
public static readonly OpCode Stelem_I = new OpCode (
|
||||
0xff << 0 | 0x9b << 8 | (byte) Code.Stelem_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_I1 = new OpCode (
|
||||
0xff << 0 | 0x9c << 8 | (byte) Code.Stelem_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_I2 = new OpCode (
|
||||
0xff << 0 | 0x9d << 8 | (byte) Code.Stelem_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_I4 = new OpCode (
|
||||
0xff << 0 | 0x9e << 8 | (byte) Code.Stelem_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_I8 = new OpCode (
|
||||
0xff << 0 | 0x9f << 8 | (byte) Code.Stelem_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_R4 = new OpCode (
|
||||
0xff << 0 | 0xa0 << 8 | (byte) Code.Stelem_R4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_R8 = new OpCode (
|
||||
0xff << 0 | 0xa1 << 8 | (byte) Code.Stelem_R8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_Ref = new OpCode (
|
||||
0xff << 0 | 0xa2 << 8 | (byte) Code.Stelem_Ref << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldelem_Any = new OpCode (
|
||||
0xff << 0 | 0xa3 << 8 | (byte) Code.Ldelem_Any << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Stelem_Any = new OpCode (
|
||||
0xff << 0 | 0xa4 << 8 | (byte) Code.Stelem_Any << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Unbox_Any = new OpCode (
|
||||
0xff << 0 | 0xa5 << 8 | (byte) Code.Unbox_Any << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I1 = new OpCode (
|
||||
0xff << 0 | 0xb3 << 8 | (byte) Code.Conv_Ovf_I1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U1 = new OpCode (
|
||||
0xff << 0 | 0xb4 << 8 | (byte) Code.Conv_Ovf_U1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I2 = new OpCode (
|
||||
0xff << 0 | 0xb5 << 8 | (byte) Code.Conv_Ovf_I2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U2 = new OpCode (
|
||||
0xff << 0 | 0xb6 << 8 | (byte) Code.Conv_Ovf_U2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I4 = new OpCode (
|
||||
0xff << 0 | 0xb7 << 8 | (byte) Code.Conv_Ovf_I4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U4 = new OpCode (
|
||||
0xff << 0 | 0xb8 << 8 | (byte) Code.Conv_Ovf_U4 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I8 = new OpCode (
|
||||
0xff << 0 | 0xb9 << 8 | (byte) Code.Conv_Ovf_I8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U8 = new OpCode (
|
||||
0xff << 0 | 0xba << 8 | (byte) Code.Conv_Ovf_U8 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24);
|
||||
|
||||
public static readonly OpCode Refanyval = new OpCode (
|
||||
0xff << 0 | 0xc2 << 8 | (byte) Code.Refanyval << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ckfinite = new OpCode (
|
||||
0xff << 0 | 0xc3 << 8 | (byte) Code.Ckfinite << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24);
|
||||
|
||||
public static readonly OpCode Mkrefany = new OpCode (
|
||||
0xff << 0 | 0xc6 << 8 | (byte) Code.Mkrefany << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldtoken = new OpCode (
|
||||
0xff << 0 | 0xd0 << 8 | (byte) Code.Ldtoken << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineTok << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_U2 = new OpCode (
|
||||
0xff << 0 | 0xd1 << 8 | (byte) Code.Conv_U2 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_U1 = new OpCode (
|
||||
0xff << 0 | 0xd2 << 8 | (byte) Code.Conv_U1 << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_I = new OpCode (
|
||||
0xff << 0 | 0xd3 << 8 | (byte) Code.Conv_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_I = new OpCode (
|
||||
0xff << 0 | 0xd4 << 8 | (byte) Code.Conv_Ovf_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Conv_Ovf_U = new OpCode (
|
||||
0xff << 0 | 0xd5 << 8 | (byte) Code.Conv_Ovf_U << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Add_Ovf = new OpCode (
|
||||
0xff << 0 | 0xd6 << 8 | (byte) Code.Add_Ovf << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Add_Ovf_Un = new OpCode (
|
||||
0xff << 0 | 0xd7 << 8 | (byte) Code.Add_Ovf_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Mul_Ovf = new OpCode (
|
||||
0xff << 0 | 0xd8 << 8 | (byte) Code.Mul_Ovf << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Mul_Ovf_Un = new OpCode (
|
||||
0xff << 0 | 0xd9 << 8 | (byte) Code.Mul_Ovf_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Sub_Ovf = new OpCode (
|
||||
0xff << 0 | 0xda << 8 | (byte) Code.Sub_Ovf << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Sub_Ovf_Un = new OpCode (
|
||||
0xff << 0 | 0xdb << 8 | (byte) Code.Sub_Ovf_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Endfinally = new OpCode (
|
||||
0xff << 0 | 0xdc << 8 | (byte) Code.Endfinally << 16 | (byte) FlowControl.Return << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Leave = new OpCode (
|
||||
0xff << 0 | 0xdd << 8 | (byte) Code.Leave << 16 | (byte) FlowControl.Branch << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Leave_S = new OpCode (
|
||||
0xff << 0 | 0xde << 8 | (byte) Code.Leave_S << 16 | (byte) FlowControl.Branch << 24,
|
||||
(byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Stind_I = new OpCode (
|
||||
0xff << 0 | 0xdf << 8 | (byte) Code.Stind_I << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Conv_U = new OpCode (
|
||||
0xff << 0 | 0xe0 << 8 | (byte) Code.Conv_U << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Arglist = new OpCode (
|
||||
0xfe << 0 | 0x00 << 8 | (byte) Code.Arglist << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ceq = new OpCode (
|
||||
0xfe << 0 | 0x01 << 8 | (byte) Code.Ceq << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Cgt = new OpCode (
|
||||
0xfe << 0 | 0x02 << 8 | (byte) Code.Cgt << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Cgt_Un = new OpCode (
|
||||
0xfe << 0 | 0x03 << 8 | (byte) Code.Cgt_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Clt = new OpCode (
|
||||
0xfe << 0 | 0x04 << 8 | (byte) Code.Clt << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Clt_Un = new OpCode (
|
||||
0xfe << 0 | 0x05 << 8 | (byte) Code.Clt_Un << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldftn = new OpCode (
|
||||
0xfe << 0 | 0x06 << 8 | (byte) Code.Ldftn << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldvirtftn = new OpCode (
|
||||
0xfe << 0 | 0x07 << 8 | (byte) Code.Ldvirtftn << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Ldarg = new OpCode (
|
||||
0xfe << 0 | 0x09 << 8 | (byte) Code.Ldarg << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldarga = new OpCode (
|
||||
0xfe << 0 | 0x0a << 8 | (byte) Code.Ldarga << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Starg = new OpCode (
|
||||
0xfe << 0 | 0x0b << 8 | (byte) Code.Starg << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Ldloc = new OpCode (
|
||||
0xfe << 0 | 0x0c << 8 | (byte) Code.Ldloc << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24);
|
||||
|
||||
public static readonly OpCode Ldloca = new OpCode (
|
||||
0xfe << 0 | 0x0d << 8 | (byte) Code.Ldloca << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Stloc = new OpCode (
|
||||
0xfe << 0 | 0x0e << 8 | (byte) Code.Stloc << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Localloc = new OpCode (
|
||||
0xfe << 0 | 0x0f << 8 | (byte) Code.Localloc << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Endfilter = new OpCode (
|
||||
0xfe << 0 | 0x11 << 8 | (byte) Code.Endfilter << 16 | (byte) FlowControl.Return << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Unaligned = new OpCode (
|
||||
0xfe << 0 | 0x12 << 8 | (byte) Code.Unaligned << 16 | (byte) FlowControl.Meta << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Volatile = new OpCode (
|
||||
0xfe << 0 | 0x13 << 8 | (byte) Code.Volatile << 16 | (byte) FlowControl.Meta << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Tail = new OpCode (
|
||||
0xfe << 0 | 0x14 << 8 | (byte) Code.Tail << 16 | (byte) FlowControl.Meta << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Initobj = new OpCode (
|
||||
0xfe << 0 | 0x15 << 8 | (byte) Code.Initobj << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Constrained = new OpCode (
|
||||
0xfe << 0 | 0x16 << 8 | (byte) Code.Constrained << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Cpblk = new OpCode (
|
||||
0xfe << 0 | 0x17 << 8 | (byte) Code.Cpblk << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Initblk = new OpCode (
|
||||
0xfe << 0 | 0x18 << 8 | (byte) Code.Initblk << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode No = new OpCode (
|
||||
0xfe << 0 | 0x19 << 8 | (byte) Code.No << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Rethrow = new OpCode (
|
||||
0xfe << 0 | 0x1a << 8 | (byte) Code.Rethrow << 16 | (byte) FlowControl.Throw << 24,
|
||||
(byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
|
||||
public static readonly OpCode Sizeof = new OpCode (
|
||||
0xfe << 0 | 0x1c << 8 | (byte) Code.Sizeof << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Refanytype = new OpCode (
|
||||
0xfe << 0 | 0x1d << 8 | (byte) Code.Refanytype << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24);
|
||||
|
||||
public static readonly OpCode Readonly = new OpCode (
|
||||
0xfe << 0 | 0x1e << 8 | (byte) Code.Readonly << 16 | (byte) FlowControl.Next << 24,
|
||||
(byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,590 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
using Mono.Cecil.Metadata;
|
||||
using Mono.Cecil.PE;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class PortablePdbReaderProvider : ISymbolReaderProvider {
|
||||
|
||||
public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
Mixin.CheckFileName (fileName);
|
||||
|
||||
var file = File.OpenRead (Mixin.GetPdbFileName (fileName));
|
||||
return GetSymbolReader (module, Disposable.Owned (file as Stream), file.Name);
|
||||
}
|
||||
|
||||
public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
Mixin.CheckStream (symbolStream);
|
||||
|
||||
return GetSymbolReader (module, Disposable.NotOwned (symbolStream), symbolStream.GetFileName ());
|
||||
}
|
||||
|
||||
ISymbolReader GetSymbolReader (ModuleDefinition module, Disposable<Stream> symbolStream, string fileName)
|
||||
{
|
||||
return new PortablePdbReader (ImageReader.ReadPortablePdb (symbolStream, fileName), module);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PortablePdbReader : ISymbolReader {
|
||||
|
||||
readonly Image image;
|
||||
readonly ModuleDefinition module;
|
||||
readonly MetadataReader reader;
|
||||
readonly MetadataReader debug_reader;
|
||||
|
||||
bool IsEmbedded { get { return reader.image == debug_reader.image; } }
|
||||
|
||||
internal PortablePdbReader (Image image, ModuleDefinition module)
|
||||
{
|
||||
this.image = image;
|
||||
this.module = module;
|
||||
this.reader = module.reader;
|
||||
this.debug_reader = new MetadataReader (image, module, this.reader);
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
public ISymbolWriterProvider GetWriterProvider ()
|
||||
{
|
||||
return new PortablePdbWriterProvider ();
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool ProcessDebugHeader (ImageDebugHeader header)
|
||||
{
|
||||
if (image == module.Image)
|
||||
return true;
|
||||
|
||||
var entry = header.GetCodeViewEntry ();
|
||||
if (entry == null)
|
||||
return false;
|
||||
|
||||
var data = entry.Data;
|
||||
|
||||
if (data.Length < 24)
|
||||
return false;
|
||||
|
||||
var magic = ReadInt32 (data, 0);
|
||||
if (magic != 0x53445352)
|
||||
return false;
|
||||
|
||||
var buffer = new byte [16];
|
||||
Buffer.BlockCopy (data, 4, buffer, 0, 16);
|
||||
|
||||
var module_guid = new Guid (buffer);
|
||||
|
||||
Buffer.BlockCopy (image.PdbHeap.Id, 0, buffer, 0, 16);
|
||||
|
||||
var pdb_guid = new Guid (buffer);
|
||||
|
||||
if (module_guid != pdb_guid)
|
||||
return false;
|
||||
|
||||
ReadModule ();
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ReadInt32 (byte [] bytes, int start)
|
||||
{
|
||||
return (bytes [start]
|
||||
| (bytes [start + 1] << 8)
|
||||
| (bytes [start + 2] << 16)
|
||||
| (bytes [start + 3] << 24));
|
||||
}
|
||||
|
||||
void ReadModule ()
|
||||
{
|
||||
module.custom_infos = debug_reader.GetCustomDebugInformation (module);
|
||||
}
|
||||
|
||||
public MethodDebugInformation Read (MethodDefinition method)
|
||||
{
|
||||
var info = new MethodDebugInformation (method);
|
||||
ReadSequencePoints (info);
|
||||
ReadScope (info);
|
||||
ReadStateMachineKickOffMethod (info);
|
||||
ReadCustomDebugInformations (info);
|
||||
return info;
|
||||
}
|
||||
|
||||
void ReadSequencePoints (MethodDebugInformation method_info)
|
||||
{
|
||||
method_info.sequence_points = debug_reader.ReadSequencePoints (method_info.method);
|
||||
}
|
||||
|
||||
void ReadScope (MethodDebugInformation method_info)
|
||||
{
|
||||
method_info.scope = debug_reader.ReadScope (method_info.method);
|
||||
}
|
||||
|
||||
void ReadStateMachineKickOffMethod (MethodDebugInformation method_info)
|
||||
{
|
||||
method_info.kickoff_method = debug_reader.ReadStateMachineKickoffMethod (method_info.method);
|
||||
}
|
||||
|
||||
void ReadCustomDebugInformations (MethodDebugInformation info)
|
||||
{
|
||||
info.method.custom_infos = debug_reader.GetCustomDebugInformation (info.method);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (IsEmbedded)
|
||||
return;
|
||||
|
||||
image.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EmbeddedPortablePdbReaderProvider : ISymbolReaderProvider {
|
||||
|
||||
public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
|
||||
var header = module.GetDebugHeader ();
|
||||
var entry = header.GetEmbeddedPortablePdbEntry ();
|
||||
if (entry == null)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
return new EmbeddedPortablePdbReader (
|
||||
(PortablePdbReader) new PortablePdbReaderProvider ().GetSymbolReader (module, GetPortablePdbStream (entry)));
|
||||
}
|
||||
|
||||
static Stream GetPortablePdbStream (ImageDebugHeaderEntry entry)
|
||||
{
|
||||
var compressed_stream = new MemoryStream (entry.Data);
|
||||
var reader = new BinaryStreamReader (compressed_stream);
|
||||
reader.ReadInt32 (); // signature
|
||||
var length = reader.ReadInt32 ();
|
||||
var decompressed_stream = new MemoryStream (length);
|
||||
|
||||
using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true))
|
||||
deflate_stream.CopyTo (decompressed_stream);
|
||||
|
||||
return decompressed_stream;
|
||||
}
|
||||
|
||||
public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EmbeddedPortablePdbReader : ISymbolReader
|
||||
{
|
||||
private readonly PortablePdbReader reader;
|
||||
|
||||
internal EmbeddedPortablePdbReader (PortablePdbReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException ();
|
||||
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
#if !READ_ONLY
|
||||
public ISymbolWriterProvider GetWriterProvider ()
|
||||
{
|
||||
return new EmbeddedPortablePdbWriterProvider ();
|
||||
}
|
||||
#endif
|
||||
public bool ProcessDebugHeader (ImageDebugHeader header)
|
||||
{
|
||||
return reader.ProcessDebugHeader (header);
|
||||
}
|
||||
|
||||
public MethodDebugInformation Read (MethodDefinition method)
|
||||
{
|
||||
return reader.Read (method);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
reader.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
public sealed class PortablePdbWriterProvider : ISymbolWriterProvider
|
||||
{
|
||||
public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
Mixin.CheckFileName (fileName);
|
||||
|
||||
var file = File.OpenWrite (Mixin.GetPdbFileName (fileName));
|
||||
return GetSymbolWriter (module, Disposable.Owned (file as Stream));
|
||||
}
|
||||
|
||||
public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
Mixin.CheckStream (symbolStream);
|
||||
|
||||
return GetSymbolWriter (module, Disposable.NotOwned (symbolStream));
|
||||
}
|
||||
|
||||
ISymbolWriter GetSymbolWriter (ModuleDefinition module, Disposable<Stream> stream)
|
||||
{
|
||||
var metadata = new MetadataBuilder (module, this);
|
||||
var writer = ImageWriter.CreateDebugWriter (module, metadata, stream);
|
||||
|
||||
return new PortablePdbWriter (metadata, module, writer);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PortablePdbWriter : ISymbolWriter {
|
||||
|
||||
readonly MetadataBuilder pdb_metadata;
|
||||
readonly ModuleDefinition module;
|
||||
readonly ImageWriter writer;
|
||||
|
||||
MetadataBuilder module_metadata;
|
||||
|
||||
bool IsEmbedded { get { return writer == null; } }
|
||||
|
||||
internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module)
|
||||
{
|
||||
this.pdb_metadata = pdb_metadata;
|
||||
this.module = module;
|
||||
|
||||
this.module_metadata = module.metadata_builder;
|
||||
|
||||
if (module_metadata != pdb_metadata)
|
||||
this.pdb_metadata.metadata_builder = this.module_metadata;
|
||||
|
||||
pdb_metadata.AddCustomDebugInformations (module);
|
||||
}
|
||||
|
||||
internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module, ImageWriter writer)
|
||||
: this (pdb_metadata, module)
|
||||
{
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public ISymbolReaderProvider GetReaderProvider ()
|
||||
{
|
||||
return new PortablePdbReaderProvider ();
|
||||
}
|
||||
|
||||
public ImageDebugHeader GetDebugHeader ()
|
||||
{
|
||||
if (IsEmbedded)
|
||||
return new ImageDebugHeader ();
|
||||
|
||||
var directory = new ImageDebugDirectory () {
|
||||
MajorVersion = 256,
|
||||
MinorVersion = 20557,
|
||||
Type = ImageDebugType.CodeView,
|
||||
TimeDateStamp = (int) module.timestamp,
|
||||
};
|
||||
|
||||
var buffer = new ByteBuffer ();
|
||||
// RSDS
|
||||
buffer.WriteUInt32 (0x53445352);
|
||||
// Module ID
|
||||
buffer.WriteBytes (module.Mvid.ToByteArray ());
|
||||
// PDB Age
|
||||
buffer.WriteUInt32 (1);
|
||||
// PDB Path
|
||||
buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (writer.BaseStream.GetFileName ()));
|
||||
buffer.WriteByte (0);
|
||||
|
||||
var data = new byte [buffer.length];
|
||||
Buffer.BlockCopy (buffer.buffer, 0, data, 0, buffer.length);
|
||||
directory.SizeOfData = data.Length;
|
||||
|
||||
return new ImageDebugHeader (new ImageDebugHeaderEntry (directory, data));
|
||||
}
|
||||
|
||||
public void Write (MethodDebugInformation info)
|
||||
{
|
||||
CheckMethodDebugInformationTable ();
|
||||
|
||||
pdb_metadata.AddMethodDebugInformation (info);
|
||||
}
|
||||
|
||||
void CheckMethodDebugInformationTable ()
|
||||
{
|
||||
var mdi = pdb_metadata.table_heap.GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation);
|
||||
if (mdi.length > 0)
|
||||
return;
|
||||
|
||||
// The MethodDebugInformation table has the same length as the Method table
|
||||
mdi.rows = new Row<uint, uint> [module_metadata.method_rid - 1];
|
||||
mdi.length = mdi.rows.Length;
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (IsEmbedded)
|
||||
return;
|
||||
|
||||
WritePdbFile ();
|
||||
}
|
||||
|
||||
void WritePdbFile ()
|
||||
{
|
||||
WritePdbHeap ();
|
||||
|
||||
WriteTableHeap ();
|
||||
|
||||
writer.BuildMetadataTextMap ();
|
||||
writer.WriteMetadataHeader ();
|
||||
writer.WriteMetadata ();
|
||||
|
||||
writer.Flush ();
|
||||
writer.stream.Dispose ();
|
||||
}
|
||||
|
||||
void WritePdbHeap ()
|
||||
{
|
||||
var pdb_heap = pdb_metadata.pdb_heap;
|
||||
|
||||
pdb_heap.WriteBytes (module.Mvid.ToByteArray ());
|
||||
pdb_heap.WriteUInt32 (module_metadata.timestamp);
|
||||
|
||||
pdb_heap.WriteUInt32 (module_metadata.entry_point.ToUInt32 ());
|
||||
|
||||
var table_heap = module_metadata.table_heap;
|
||||
var tables = table_heap.tables;
|
||||
|
||||
ulong valid = 0;
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
if (tables [i] == null || tables [i].Length == 0)
|
||||
continue;
|
||||
|
||||
valid |= (1UL << i);
|
||||
}
|
||||
|
||||
pdb_heap.WriteUInt64 (valid);
|
||||
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
if (tables [i] == null || tables [i].Length == 0)
|
||||
continue;
|
||||
|
||||
pdb_heap.WriteUInt32 ((uint) tables [i].Length);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTableHeap ()
|
||||
{
|
||||
pdb_metadata.table_heap.string_offsets = pdb_metadata.string_heap.WriteStrings ();
|
||||
pdb_metadata.table_heap.ComputeTableInformations ();
|
||||
pdb_metadata.table_heap.WriteTableHeap ();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EmbeddedPortablePdbWriterProvider : ISymbolWriterProvider {
|
||||
|
||||
public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
Mixin.CheckFileName (fileName);
|
||||
|
||||
var stream = new MemoryStream ();
|
||||
var pdb_writer = (PortablePdbWriter) new PortablePdbWriterProvider ().GetSymbolWriter (module, stream);
|
||||
return new EmbeddedPortablePdbWriter (stream, pdb_writer);
|
||||
}
|
||||
|
||||
public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EmbeddedPortablePdbWriter : ISymbolWriter {
|
||||
|
||||
readonly Stream stream;
|
||||
readonly PortablePdbWriter writer;
|
||||
|
||||
internal EmbeddedPortablePdbWriter (Stream stream, PortablePdbWriter writer)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public ISymbolReaderProvider GetReaderProvider ()
|
||||
{
|
||||
return new EmbeddedPortablePdbReaderProvider ();
|
||||
}
|
||||
|
||||
public ImageDebugHeader GetDebugHeader ()
|
||||
{
|
||||
writer.Dispose ();
|
||||
|
||||
var directory = new ImageDebugDirectory {
|
||||
Type = ImageDebugType.EmbeddedPortablePdb,
|
||||
MajorVersion = 0x0100,
|
||||
MinorVersion = 0x0100,
|
||||
};
|
||||
|
||||
var data = new MemoryStream ();
|
||||
|
||||
var w = new BinaryStreamWriter (data);
|
||||
w.WriteByte (0x4d);
|
||||
w.WriteByte (0x50);
|
||||
w.WriteByte (0x44);
|
||||
w.WriteByte (0x42);
|
||||
|
||||
w.WriteInt32 ((int) stream.Length);
|
||||
|
||||
stream.Position = 0;
|
||||
|
||||
using (var compress_stream = new DeflateStream (data, CompressionMode.Compress, leaveOpen: true))
|
||||
stream.CopyTo (compress_stream);
|
||||
|
||||
directory.SizeOfData = (int) data.Length;
|
||||
|
||||
return new ImageDebugHeader (new [] {
|
||||
writer.GetDebugHeader ().Entries [0],
|
||||
new ImageDebugHeaderEntry (directory, data.ToArray ())
|
||||
});
|
||||
}
|
||||
|
||||
public void Write (MethodDebugInformation info)
|
||||
{
|
||||
writer.Write (info);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static class PdbGuidMapping {
|
||||
|
||||
static readonly Dictionary<Guid, DocumentLanguage> guid_language = new Dictionary<Guid, DocumentLanguage> ();
|
||||
static readonly Dictionary<DocumentLanguage, Guid> language_guid = new Dictionary<DocumentLanguage, Guid> ();
|
||||
|
||||
static PdbGuidMapping ()
|
||||
{
|
||||
AddMapping (DocumentLanguage.C, new Guid ("63a08714-fc37-11d2-904c-00c04fa302a1"));
|
||||
AddMapping (DocumentLanguage.Cpp, new Guid ("3a12d0b7-c26c-11d0-b442-00a0244a1dd2"));
|
||||
AddMapping (DocumentLanguage.CSharp, new Guid ("3f5162f8-07c6-11d3-9053-00c04fa302a1"));
|
||||
AddMapping (DocumentLanguage.Basic, new Guid ("3a12d0b8-c26c-11d0-b442-00a0244a1dd2"));
|
||||
AddMapping (DocumentLanguage.Java, new Guid ("3a12d0b4-c26c-11d0-b442-00a0244a1dd2"));
|
||||
AddMapping (DocumentLanguage.Cobol, new Guid ("af046cd1-d0e1-11d2-977c-00a0c9b4d50c"));
|
||||
AddMapping (DocumentLanguage.Pascal, new Guid ("af046cd2-d0e1-11d2-977c-00a0c9b4d50c"));
|
||||
AddMapping (DocumentLanguage.Cil, new Guid ("af046cd3-d0e1-11d2-977c-00a0c9b4d50c"));
|
||||
AddMapping (DocumentLanguage.JScript, new Guid ("3a12d0b6-c26c-11d0-b442-00a0244a1dd2"));
|
||||
AddMapping (DocumentLanguage.Smc, new Guid ("0d9b9f7b-6611-11d3-bd2a-0000f80849bd"));
|
||||
AddMapping (DocumentLanguage.MCpp, new Guid ("4b35fde8-07c6-11d3-9053-00c04fa302a1"));
|
||||
AddMapping (DocumentLanguage.FSharp, new Guid ("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3"));
|
||||
}
|
||||
|
||||
static void AddMapping (DocumentLanguage language, Guid guid)
|
||||
{
|
||||
guid_language.Add (guid, language);
|
||||
language_guid.Add (language, guid);
|
||||
}
|
||||
|
||||
static readonly Guid type_text = new Guid ("5a869d0b-6611-11d3-bd2a-0000f80849bd");
|
||||
|
||||
public static DocumentType ToType (this Guid guid)
|
||||
{
|
||||
if (guid == type_text)
|
||||
return DocumentType.Text;
|
||||
|
||||
return DocumentType.Other;
|
||||
}
|
||||
|
||||
public static Guid ToGuid (this DocumentType type)
|
||||
{
|
||||
if (type == DocumentType.Text)
|
||||
return type_text;
|
||||
|
||||
return new Guid ();
|
||||
}
|
||||
|
||||
static readonly Guid hash_md5 = new Guid ("406ea660-64cf-4c82-b6f0-42d48172a799");
|
||||
static readonly Guid hash_sha1 = new Guid ("ff1816ec-aa5e-4d10-87f7-6f4963833460");
|
||||
static readonly Guid hash_sha256 = new Guid ("8829d00f-11b8-4213-878b-770e8597ac16");
|
||||
|
||||
public static DocumentHashAlgorithm ToHashAlgorithm (this Guid guid)
|
||||
{
|
||||
if (guid == hash_md5)
|
||||
return DocumentHashAlgorithm.MD5;
|
||||
|
||||
if (guid == hash_sha1)
|
||||
return DocumentHashAlgorithm.SHA1;
|
||||
|
||||
if (guid == hash_sha256)
|
||||
return DocumentHashAlgorithm.SHA256;
|
||||
|
||||
return DocumentHashAlgorithm.None;
|
||||
}
|
||||
|
||||
public static Guid ToGuid (this DocumentHashAlgorithm hash_algo)
|
||||
{
|
||||
if (hash_algo == DocumentHashAlgorithm.MD5)
|
||||
return hash_md5;
|
||||
|
||||
if (hash_algo == DocumentHashAlgorithm.SHA1)
|
||||
return hash_sha1;
|
||||
|
||||
if (hash_algo == DocumentHashAlgorithm.SHA256)
|
||||
return hash_sha256;
|
||||
|
||||
return new Guid ();
|
||||
}
|
||||
|
||||
public static DocumentLanguage ToLanguage (this Guid guid)
|
||||
{
|
||||
DocumentLanguage language;
|
||||
if (!guid_language.TryGetValue (guid, out language))
|
||||
return DocumentLanguage.Other;
|
||||
|
||||
return language;
|
||||
}
|
||||
|
||||
public static Guid ToGuid (this DocumentLanguage language)
|
||||
{
|
||||
Guid guid;
|
||||
if (!language_guid.TryGetValue (language, out guid))
|
||||
return new Guid ();
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
static readonly Guid vendor_ms = new Guid ("994b45c4-e6e9-11d2-903f-00c04fa302a1");
|
||||
|
||||
public static DocumentLanguageVendor ToVendor (this Guid guid)
|
||||
{
|
||||
if (guid == vendor_ms)
|
||||
return DocumentLanguageVendor.Microsoft;
|
||||
|
||||
return DocumentLanguageVendor.Other;
|
||||
}
|
||||
|
||||
public static Guid ToGuid (this DocumentLanguageVendor vendor)
|
||||
{
|
||||
if (vendor == DocumentLanguageVendor.Microsoft)
|
||||
return vendor_ms;
|
||||
|
||||
return new Guid ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class SequencePoint {
|
||||
|
||||
internal InstructionOffset offset;
|
||||
Document document;
|
||||
|
||||
int start_line;
|
||||
int start_column;
|
||||
int end_line;
|
||||
int end_column;
|
||||
|
||||
public int Offset {
|
||||
get { return offset.Offset; }
|
||||
}
|
||||
|
||||
public int StartLine {
|
||||
get { return start_line; }
|
||||
set { start_line = value; }
|
||||
}
|
||||
|
||||
public int StartColumn {
|
||||
get { return start_column; }
|
||||
set { start_column = value; }
|
||||
}
|
||||
|
||||
public int EndLine {
|
||||
get { return end_line; }
|
||||
set { end_line = value; }
|
||||
}
|
||||
|
||||
public int EndColumn {
|
||||
get { return end_column; }
|
||||
set { end_column = value; }
|
||||
}
|
||||
|
||||
public bool IsHidden {
|
||||
get { return start_line == 0xfeefee && start_line == end_line; }
|
||||
}
|
||||
|
||||
public Document Document {
|
||||
get { return document; }
|
||||
set { document = value; }
|
||||
}
|
||||
|
||||
internal SequencePoint (int offset, Document document)
|
||||
{
|
||||
if (document == null)
|
||||
throw new ArgumentNullException ("document");
|
||||
|
||||
this.offset = new InstructionOffset (offset);
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public SequencePoint (Instruction instruction, Document document)
|
||||
{
|
||||
if (document == null)
|
||||
throw new ArgumentNullException ("document");
|
||||
|
||||
this.offset = new InstructionOffset (instruction);
|
||||
this.document = document;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public sealed class VariableDefinition : VariableReference {
|
||||
|
||||
public bool IsPinned {
|
||||
get { return variable_type.IsPinned; }
|
||||
}
|
||||
|
||||
public VariableDefinition (TypeReference variableType)
|
||||
: base (variableType)
|
||||
{
|
||||
}
|
||||
|
||||
public override VariableDefinition Resolve ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Cil {
|
||||
|
||||
public abstract class VariableReference {
|
||||
|
||||
internal int index = -1;
|
||||
protected TypeReference variable_type;
|
||||
|
||||
public TypeReference VariableType {
|
||||
get { return variable_type; }
|
||||
set { variable_type = value; }
|
||||
}
|
||||
|
||||
public int Index {
|
||||
get { return index; }
|
||||
}
|
||||
|
||||
internal VariableReference (TypeReference variable_type)
|
||||
{
|
||||
this.variable_type = variable_type;
|
||||
}
|
||||
|
||||
public abstract VariableDefinition Resolve ();
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
if (index >= 0)
|
||||
return "V_" + index;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
static class Consts
|
||||
{
|
||||
public const string AssemblyName = "Mono.Cecil";
|
||||
public const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf";
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public struct CustomAttributeArgument {
|
||||
|
||||
readonly TypeReference type;
|
||||
readonly object value;
|
||||
|
||||
public TypeReference Type {
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public object Value {
|
||||
get { return value; }
|
||||
}
|
||||
|
||||
public CustomAttributeArgument (TypeReference type, object value)
|
||||
{
|
||||
Mixin.CheckType (type);
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct CustomAttributeNamedArgument {
|
||||
|
||||
readonly string name;
|
||||
readonly CustomAttributeArgument argument;
|
||||
|
||||
public string Name {
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public CustomAttributeArgument Argument {
|
||||
get { return argument; }
|
||||
}
|
||||
|
||||
public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
this.name = name;
|
||||
this.argument = argument;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICustomAttribute {
|
||||
|
||||
TypeReference AttributeType { get; }
|
||||
|
||||
bool HasFields { get; }
|
||||
bool HasProperties { get; }
|
||||
bool HasConstructorArguments { get; }
|
||||
Collection<CustomAttributeNamedArgument> Fields { get; }
|
||||
Collection<CustomAttributeNamedArgument> Properties { get; }
|
||||
Collection<CustomAttributeArgument> ConstructorArguments { get; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay ("{AttributeType}")]
|
||||
public sealed class CustomAttribute : ICustomAttribute {
|
||||
|
||||
internal CustomAttributeValueProjection projection;
|
||||
readonly internal uint signature;
|
||||
internal bool resolved;
|
||||
MethodReference constructor;
|
||||
byte [] blob;
|
||||
internal Collection<CustomAttributeArgument> arguments;
|
||||
internal Collection<CustomAttributeNamedArgument> fields;
|
||||
internal Collection<CustomAttributeNamedArgument> properties;
|
||||
|
||||
public MethodReference Constructor {
|
||||
get { return constructor; }
|
||||
set { constructor = value; }
|
||||
}
|
||||
|
||||
public TypeReference AttributeType {
|
||||
get { return constructor.DeclaringType; }
|
||||
}
|
||||
|
||||
public bool IsResolved {
|
||||
get { return resolved; }
|
||||
}
|
||||
|
||||
public bool HasConstructorArguments {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return !arguments.IsNullOrEmpty ();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttributeArgument> ConstructorArguments {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return arguments ?? (arguments = new Collection<CustomAttributeArgument> ());
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFields {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return !fields.IsNullOrEmpty ();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttributeNamedArgument> Fields {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return fields ?? (fields = new Collection<CustomAttributeNamedArgument> ());
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasProperties {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return !properties.IsNullOrEmpty ();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttributeNamedArgument> Properties {
|
||||
get {
|
||||
Resolve ();
|
||||
|
||||
return properties ?? (properties = new Collection<CustomAttributeNamedArgument> ());
|
||||
}
|
||||
}
|
||||
|
||||
internal bool HasImage {
|
||||
get { return constructor != null && constructor.HasImage; }
|
||||
}
|
||||
|
||||
internal ModuleDefinition Module {
|
||||
get { return constructor.Module; }
|
||||
}
|
||||
|
||||
internal CustomAttribute (uint signature, MethodReference constructor)
|
||||
{
|
||||
this.signature = signature;
|
||||
this.constructor = constructor;
|
||||
this.resolved = false;
|
||||
}
|
||||
|
||||
public CustomAttribute (MethodReference constructor)
|
||||
{
|
||||
this.constructor = constructor;
|
||||
this.resolved = true;
|
||||
}
|
||||
|
||||
public CustomAttribute (MethodReference constructor, byte [] blob)
|
||||
{
|
||||
this.constructor = constructor;
|
||||
this.resolved = false;
|
||||
this.blob = blob;
|
||||
}
|
||||
|
||||
public byte [] GetBlob ()
|
||||
{
|
||||
if (blob != null)
|
||||
return blob;
|
||||
|
||||
if (!HasImage)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature));
|
||||
}
|
||||
|
||||
void Resolve ()
|
||||
{
|
||||
if (resolved || !HasImage)
|
||||
return;
|
||||
|
||||
Module.Read (this, (attribute, reader) => {
|
||||
try {
|
||||
reader.ReadCustomAttributeSignature (attribute);
|
||||
resolved = true;
|
||||
} catch (ResolutionException) {
|
||||
if (arguments != null)
|
||||
arguments.Clear ();
|
||||
if (fields != null)
|
||||
fields.Clear ();
|
||||
if (properties != null)
|
||||
properties.Clear ();
|
||||
|
||||
resolved = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public class DefaultAssemblyResolver : BaseAssemblyResolver {
|
||||
|
||||
readonly IDictionary<string, AssemblyDefinition> cache;
|
||||
|
||||
public DefaultAssemblyResolver ()
|
||||
{
|
||||
cache = new Dictionary<string, AssemblyDefinition> (StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
public override AssemblyDefinition Resolve (AssemblyNameReference name)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
|
||||
AssemblyDefinition assembly;
|
||||
if (cache.TryGetValue (name.FullName, out assembly))
|
||||
return assembly;
|
||||
|
||||
assembly = base.Resolve (name);
|
||||
cache [name.FullName] = assembly;
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
protected void RegisterAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
if (assembly == null)
|
||||
throw new ArgumentNullException ("assembly");
|
||||
|
||||
var name = assembly.Name.FullName;
|
||||
if (cache.ContainsKey (name))
|
||||
return;
|
||||
|
||||
cache [name] = assembly;
|
||||
}
|
||||
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
foreach (var assembly in cache.Values)
|
||||
assembly.Dispose ();
|
||||
|
||||
cache.Clear ();
|
||||
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class EmbeddedResource : Resource {
|
||||
|
||||
readonly MetadataReader reader;
|
||||
|
||||
uint? offset;
|
||||
byte [] data;
|
||||
Stream stream;
|
||||
|
||||
public override ResourceType ResourceType {
|
||||
get { return ResourceType.Embedded; }
|
||||
}
|
||||
|
||||
public EmbeddedResource (string name, ManifestResourceAttributes attributes, byte [] data) :
|
||||
base (name, attributes)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public EmbeddedResource (string name, ManifestResourceAttributes attributes, Stream stream) :
|
||||
base (name, attributes)
|
||||
{
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
internal EmbeddedResource (string name, ManifestResourceAttributes attributes, uint offset, MetadataReader reader)
|
||||
: base (name, attributes)
|
||||
{
|
||||
this.offset = offset;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public Stream GetResourceStream ()
|
||||
{
|
||||
if (stream != null)
|
||||
return stream;
|
||||
|
||||
if (data != null)
|
||||
return new MemoryStream (data);
|
||||
|
||||
if (offset.HasValue)
|
||||
return new MemoryStream (reader.GetManagedResource (offset.Value));
|
||||
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
public byte [] GetResourceData ()
|
||||
{
|
||||
if (stream != null)
|
||||
return ReadStream (stream);
|
||||
|
||||
if (data != null)
|
||||
return data;
|
||||
|
||||
if (offset.HasValue)
|
||||
return reader.GetManagedResource (offset.Value);
|
||||
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
static byte [] ReadStream (Stream stream)
|
||||
{
|
||||
int read;
|
||||
|
||||
if (stream.CanSeek) {
|
||||
var length = (int) stream.Length;
|
||||
var data = new byte [length];
|
||||
int offset = 0;
|
||||
|
||||
while ((read = stream.Read (data, offset, length - offset)) > 0)
|
||||
offset += read;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
var buffer = new byte [1024 * 8];
|
||||
var memory = new MemoryStream ();
|
||||
while ((read = stream.Read (buffer, 0, buffer.Length)) > 0)
|
||||
memory.Write (buffer, 0, read);
|
||||
|
||||
return memory.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
[Flags]
|
||||
public enum EventAttributes : ushort {
|
||||
None = 0x0000,
|
||||
SpecialName = 0x0200, // Event is special
|
||||
RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class EventDefinition : EventReference, IMemberDefinition {
|
||||
|
||||
ushort attributes;
|
||||
|
||||
Collection<CustomAttribute> custom_attributes;
|
||||
|
||||
internal MethodDefinition add_method;
|
||||
internal MethodDefinition invoke_method;
|
||||
internal MethodDefinition remove_method;
|
||||
internal Collection<MethodDefinition> other_methods;
|
||||
|
||||
public EventAttributes Attributes {
|
||||
get { return (EventAttributes) attributes; }
|
||||
set { attributes = (ushort) value; }
|
||||
}
|
||||
|
||||
public MethodDefinition AddMethod {
|
||||
get {
|
||||
if (add_method != null)
|
||||
return add_method;
|
||||
|
||||
InitializeMethods ();
|
||||
return add_method;
|
||||
}
|
||||
set { add_method = value; }
|
||||
}
|
||||
|
||||
public MethodDefinition InvokeMethod {
|
||||
get {
|
||||
if (invoke_method != null)
|
||||
return invoke_method;
|
||||
|
||||
InitializeMethods ();
|
||||
return invoke_method;
|
||||
}
|
||||
set { invoke_method = value; }
|
||||
}
|
||||
|
||||
public MethodDefinition RemoveMethod {
|
||||
get {
|
||||
if (remove_method != null)
|
||||
return remove_method;
|
||||
|
||||
InitializeMethods ();
|
||||
return remove_method;
|
||||
}
|
||||
set { remove_method = value; }
|
||||
}
|
||||
|
||||
public bool HasOtherMethods {
|
||||
get {
|
||||
if (other_methods != null)
|
||||
return other_methods.Count > 0;
|
||||
|
||||
InitializeMethods ();
|
||||
return !other_methods.IsNullOrEmpty ();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MethodDefinition> OtherMethods {
|
||||
get {
|
||||
if (other_methods != null)
|
||||
return other_methods;
|
||||
|
||||
InitializeMethods ();
|
||||
|
||||
if (other_methods != null)
|
||||
return other_methods;
|
||||
|
||||
return other_methods = new Collection<MethodDefinition> ();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCustomAttributes {
|
||||
get {
|
||||
if (custom_attributes != null)
|
||||
return custom_attributes.Count > 0;
|
||||
|
||||
return this.GetHasCustomAttributes (Module);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttribute> CustomAttributes {
|
||||
get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); }
|
||||
}
|
||||
|
||||
#region EventAttributes
|
||||
|
||||
public bool IsSpecialName {
|
||||
get { return attributes.GetAttributes ((ushort) EventAttributes.SpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) EventAttributes.SpecialName, value); }
|
||||
}
|
||||
|
||||
public bool IsRuntimeSpecialName {
|
||||
get { return attributes.GetAttributes ((ushort) EventAttributes.RTSpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) EventAttributes.RTSpecialName, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public new TypeDefinition DeclaringType {
|
||||
get { return (TypeDefinition) base.DeclaringType; }
|
||||
set { base.DeclaringType = value; }
|
||||
}
|
||||
|
||||
public override bool IsDefinition {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public EventDefinition (string name, EventAttributes attributes, TypeReference eventType)
|
||||
: base (name, eventType)
|
||||
{
|
||||
this.attributes = (ushort) attributes;
|
||||
this.token = new MetadataToken (TokenType.Event);
|
||||
}
|
||||
|
||||
void InitializeMethods ()
|
||||
{
|
||||
var module = this.Module;
|
||||
if (module == null)
|
||||
return;
|
||||
|
||||
lock (module.SyncRoot) {
|
||||
if (add_method != null
|
||||
|| invoke_method != null
|
||||
|| remove_method != null)
|
||||
return;
|
||||
|
||||
if (!module.HasImage ())
|
||||
return;
|
||||
|
||||
module.Read (this, (@event, reader) => reader.ReadMethods (@event));
|
||||
}
|
||||
}
|
||||
|
||||
public override EventDefinition Resolve ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public abstract class EventReference : MemberReference {
|
||||
|
||||
TypeReference event_type;
|
||||
|
||||
public TypeReference EventType {
|
||||
get { return event_type; }
|
||||
set { event_type = value; }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get { return event_type.FullName + " " + MemberFullName (); }
|
||||
}
|
||||
|
||||
protected EventReference (string name, TypeReference eventType)
|
||||
: base (name)
|
||||
{
|
||||
Mixin.CheckType (eventType, Mixin.Argument.eventType);
|
||||
event_type = eventType;
|
||||
}
|
||||
|
||||
protected override IMemberDefinition ResolveDefinition ()
|
||||
{
|
||||
return this.Resolve ();
|
||||
}
|
||||
|
||||
public new abstract EventDefinition Resolve ();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class ExportedType : IMetadataTokenProvider {
|
||||
|
||||
string @namespace;
|
||||
string name;
|
||||
uint attributes;
|
||||
IMetadataScope scope;
|
||||
ModuleDefinition module;
|
||||
int identifier;
|
||||
ExportedType declaring_type;
|
||||
internal MetadataToken token;
|
||||
|
||||
public string Namespace {
|
||||
get { return @namespace; }
|
||||
set { @namespace = value; }
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
|
||||
public TypeAttributes Attributes {
|
||||
get { return (TypeAttributes) attributes; }
|
||||
set { attributes = (uint) value; }
|
||||
}
|
||||
|
||||
public IMetadataScope Scope {
|
||||
get {
|
||||
if (declaring_type != null)
|
||||
return declaring_type.Scope;
|
||||
|
||||
return scope;
|
||||
}
|
||||
set {
|
||||
if (declaring_type != null) {
|
||||
declaring_type.Scope = value;
|
||||
return;
|
||||
}
|
||||
|
||||
scope = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ExportedType DeclaringType {
|
||||
get { return declaring_type; }
|
||||
set { declaring_type = value; }
|
||||
}
|
||||
|
||||
public MetadataToken MetadataToken {
|
||||
get { return token; }
|
||||
set { token = value; }
|
||||
}
|
||||
|
||||
public int Identifier {
|
||||
get { return identifier; }
|
||||
set { identifier = value; }
|
||||
}
|
||||
|
||||
#region TypeAttributes
|
||||
|
||||
public bool IsNotPublic {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); }
|
||||
}
|
||||
|
||||
public bool IsPublic {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedPublic {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedPrivate {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedFamily {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedFamilyAndAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); }
|
||||
}
|
||||
|
||||
public bool IsNestedFamilyOrAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); }
|
||||
}
|
||||
|
||||
public bool IsAutoLayout {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); }
|
||||
}
|
||||
|
||||
public bool IsSequentialLayout {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); }
|
||||
}
|
||||
|
||||
public bool IsExplicitLayout {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); }
|
||||
}
|
||||
|
||||
public bool IsClass {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); }
|
||||
}
|
||||
|
||||
public bool IsInterface {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); }
|
||||
}
|
||||
|
||||
public bool IsAbstract {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.Abstract); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Abstract, value); }
|
||||
}
|
||||
|
||||
public bool IsSealed {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.Sealed); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Sealed, value); }
|
||||
}
|
||||
|
||||
public bool IsSpecialName {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.SpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.SpecialName, value); }
|
||||
}
|
||||
|
||||
public bool IsImport {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.Import); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Import, value); }
|
||||
}
|
||||
|
||||
public bool IsSerializable {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.Serializable); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Serializable, value); }
|
||||
}
|
||||
|
||||
public bool IsAnsiClass {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); }
|
||||
}
|
||||
|
||||
public bool IsUnicodeClass {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); }
|
||||
}
|
||||
|
||||
public bool IsAutoClass {
|
||||
get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); }
|
||||
}
|
||||
|
||||
public bool IsBeforeFieldInit {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.BeforeFieldInit); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.BeforeFieldInit, value); }
|
||||
}
|
||||
|
||||
public bool IsRuntimeSpecialName {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.RTSpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.RTSpecialName, value); }
|
||||
}
|
||||
|
||||
public bool HasSecurity {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.HasSecurity); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.HasSecurity, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public bool IsForwarder {
|
||||
get { return attributes.GetAttributes ((uint) TypeAttributes.Forwarder); }
|
||||
set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Forwarder, value); }
|
||||
}
|
||||
|
||||
public string FullName {
|
||||
get {
|
||||
var fullname = string.IsNullOrEmpty (@namespace)
|
||||
? name
|
||||
: @namespace + '.' + name;
|
||||
|
||||
if (declaring_type != null)
|
||||
return declaring_type.FullName + "/" + fullname;
|
||||
|
||||
return fullname;
|
||||
}
|
||||
}
|
||||
|
||||
public ExportedType (string @namespace, string name, ModuleDefinition module, IMetadataScope scope)
|
||||
{
|
||||
this.@namespace = @namespace;
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return FullName;
|
||||
}
|
||||
|
||||
public TypeDefinition Resolve ()
|
||||
{
|
||||
return module.Resolve (CreateReference ());
|
||||
}
|
||||
|
||||
internal TypeReference CreateReference ()
|
||||
{
|
||||
return new TypeReference (@namespace, name, module, scope) {
|
||||
DeclaringType = declaring_type != null ? declaring_type.CreateReference () : null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
[Flags]
|
||||
public enum FieldAttributes : ushort {
|
||||
FieldAccessMask = 0x0007,
|
||||
CompilerControlled = 0x0000, // Member not referenceable
|
||||
Private = 0x0001, // Accessible only by the parent type
|
||||
FamANDAssem = 0x0002, // Accessible by sub-types only in this assembly
|
||||
Assembly = 0x0003, // Accessible by anyone in the Assembly
|
||||
Family = 0x0004, // Accessible only by type and sub-types
|
||||
FamORAssem = 0x0005, // Accessible by sub-types anywhere, plus anyone in the assembly
|
||||
Public = 0x0006, // Accessible by anyone who has visibility to this scope field contract attributes
|
||||
|
||||
Static = 0x0010, // Defined on type, else per instance
|
||||
InitOnly = 0x0020, // Field may only be initialized, not written after init
|
||||
Literal = 0x0040, // Value is compile time constant
|
||||
NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted
|
||||
SpecialName = 0x0200, // Field is special
|
||||
|
||||
// Interop Attributes
|
||||
PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke
|
||||
|
||||
// Additional flags
|
||||
RTSpecialName = 0x0400, // CLI provides 'special' behavior, depending upon the name of the field
|
||||
HasFieldMarshal = 0x1000, // Field has marshalling information
|
||||
HasDefault = 0x8000, // Field has default
|
||||
HasFieldRVA = 0x0100 // Field has RVA
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class FieldDefinition : FieldReference, IMemberDefinition, IConstantProvider, IMarshalInfoProvider {
|
||||
|
||||
ushort attributes;
|
||||
Collection<CustomAttribute> custom_attributes;
|
||||
|
||||
int offset = Mixin.NotResolvedMarker;
|
||||
|
||||
internal int rva = Mixin.NotResolvedMarker;
|
||||
byte [] initial_value;
|
||||
|
||||
object constant = Mixin.NotResolved;
|
||||
|
||||
MarshalInfo marshal_info;
|
||||
|
||||
void ResolveLayout ()
|
||||
{
|
||||
if (offset != Mixin.NotResolvedMarker)
|
||||
return;
|
||||
|
||||
if (!HasImage) {
|
||||
offset = Mixin.NoDataMarker;
|
||||
return;
|
||||
}
|
||||
|
||||
offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field));
|
||||
}
|
||||
|
||||
public bool HasLayoutInfo {
|
||||
get {
|
||||
if (offset >= 0)
|
||||
return true;
|
||||
|
||||
ResolveLayout ();
|
||||
|
||||
return offset >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int Offset {
|
||||
get {
|
||||
if (offset >= 0)
|
||||
return offset;
|
||||
|
||||
ResolveLayout ();
|
||||
|
||||
return offset >= 0 ? offset : -1;
|
||||
}
|
||||
set { offset = value; }
|
||||
}
|
||||
|
||||
internal new FieldDefinitionProjection WindowsRuntimeProjection {
|
||||
get { return (FieldDefinitionProjection) projection; }
|
||||
set { projection = value; }
|
||||
}
|
||||
|
||||
void ResolveRVA ()
|
||||
{
|
||||
if (rva != Mixin.NotResolvedMarker)
|
||||
return;
|
||||
|
||||
if (!HasImage)
|
||||
return;
|
||||
|
||||
rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field));
|
||||
}
|
||||
|
||||
public int RVA {
|
||||
get {
|
||||
if (rva > 0)
|
||||
return rva;
|
||||
|
||||
ResolveRVA ();
|
||||
|
||||
return rva > 0 ? rva : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public byte [] InitialValue {
|
||||
get {
|
||||
if (initial_value != null)
|
||||
return initial_value;
|
||||
|
||||
ResolveRVA ();
|
||||
|
||||
if (initial_value == null)
|
||||
initial_value = Empty<byte>.Array;
|
||||
|
||||
return initial_value;
|
||||
}
|
||||
set {
|
||||
initial_value = value;
|
||||
rva = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public FieldAttributes Attributes {
|
||||
get { return (FieldAttributes) attributes; }
|
||||
set {
|
||||
if (IsWindowsRuntimeProjection && (ushort) value != attributes)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
attributes = (ushort) value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasConstant {
|
||||
get {
|
||||
this.ResolveConstant (ref constant, Module);
|
||||
|
||||
return constant != Mixin.NoValue;
|
||||
}
|
||||
set { if (!value) constant = Mixin.NoValue; }
|
||||
}
|
||||
|
||||
public object Constant {
|
||||
get { return HasConstant ? constant : null; }
|
||||
set { constant = value; }
|
||||
}
|
||||
|
||||
public bool HasCustomAttributes {
|
||||
get {
|
||||
if (custom_attributes != null)
|
||||
return custom_attributes.Count > 0;
|
||||
|
||||
return this.GetHasCustomAttributes (Module);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttribute> CustomAttributes {
|
||||
get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); }
|
||||
}
|
||||
|
||||
public bool HasMarshalInfo {
|
||||
get {
|
||||
if (marshal_info != null)
|
||||
return true;
|
||||
|
||||
return this.GetHasMarshalInfo (Module);
|
||||
}
|
||||
}
|
||||
|
||||
public MarshalInfo MarshalInfo {
|
||||
get { return marshal_info ?? (this.GetMarshalInfo (ref marshal_info, Module)); }
|
||||
set { marshal_info = value; }
|
||||
}
|
||||
|
||||
#region FieldAttributes
|
||||
|
||||
public bool IsCompilerControlled {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled, value); }
|
||||
}
|
||||
|
||||
public bool IsPrivate {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private, value); }
|
||||
}
|
||||
|
||||
public bool IsFamilyAndAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem, value); }
|
||||
}
|
||||
|
||||
public bool IsAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly, value); }
|
||||
}
|
||||
|
||||
public bool IsFamily {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family, value); }
|
||||
}
|
||||
|
||||
public bool IsFamilyOrAssembly {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem, value); }
|
||||
}
|
||||
|
||||
public bool IsPublic {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public, value); }
|
||||
}
|
||||
|
||||
public bool IsStatic {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.Static); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.Static, value); }
|
||||
}
|
||||
|
||||
public bool IsInitOnly {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.InitOnly); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.InitOnly, value); }
|
||||
}
|
||||
|
||||
public bool IsLiteral {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.Literal); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.Literal, value); }
|
||||
}
|
||||
|
||||
public bool IsNotSerialized {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.NotSerialized); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.NotSerialized, value); }
|
||||
}
|
||||
|
||||
public bool IsSpecialName {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.SpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.SpecialName, value); }
|
||||
}
|
||||
|
||||
public bool IsPInvokeImpl {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.PInvokeImpl); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.PInvokeImpl, value); }
|
||||
}
|
||||
|
||||
public bool IsRuntimeSpecialName {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.RTSpecialName); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.RTSpecialName, value); }
|
||||
}
|
||||
|
||||
public bool HasDefault {
|
||||
get { return attributes.GetAttributes ((ushort) FieldAttributes.HasDefault); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.HasDefault, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool IsDefinition {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public new TypeDefinition DeclaringType {
|
||||
get { return (TypeDefinition) base.DeclaringType; }
|
||||
set { base.DeclaringType = value; }
|
||||
}
|
||||
|
||||
public FieldDefinition (string name, FieldAttributes attributes, TypeReference fieldType)
|
||||
: base (name, fieldType)
|
||||
{
|
||||
this.attributes = (ushort) attributes;
|
||||
}
|
||||
|
||||
public override FieldDefinition Resolve ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public const int NotResolvedMarker = -2;
|
||||
public const int NoDataMarker = -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public class FieldReference : MemberReference {
|
||||
|
||||
TypeReference field_type;
|
||||
|
||||
public TypeReference FieldType {
|
||||
get { return field_type; }
|
||||
set { field_type = value; }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get { return field_type.FullName + " " + MemberFullName (); }
|
||||
}
|
||||
|
||||
public override bool ContainsGenericParameter {
|
||||
get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; }
|
||||
}
|
||||
|
||||
internal FieldReference ()
|
||||
{
|
||||
this.token = new MetadataToken (TokenType.MemberRef);
|
||||
}
|
||||
|
||||
public FieldReference (string name, TypeReference fieldType)
|
||||
: base (name)
|
||||
{
|
||||
Mixin.CheckType (fieldType, Mixin.Argument.fieldType);
|
||||
|
||||
this.field_type = fieldType;
|
||||
this.token = new MetadataToken (TokenType.MemberRef);
|
||||
}
|
||||
|
||||
public FieldReference (string name, TypeReference fieldType, TypeReference declaringType)
|
||||
: this (name, fieldType)
|
||||
{
|
||||
Mixin.CheckType (declaringType, Mixin.Argument.declaringType);
|
||||
|
||||
this.DeclaringType = declaringType;
|
||||
}
|
||||
|
||||
protected override IMemberDefinition ResolveDefinition ()
|
||||
{
|
||||
return this.Resolve ();
|
||||
}
|
||||
|
||||
public new virtual FieldDefinition Resolve ()
|
||||
{
|
||||
var module = this.Module;
|
||||
if (module == null)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
return module.Resolve (this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
enum FileAttributes : uint {
|
||||
ContainsMetaData = 0x0000, // This is not a resource file
|
||||
ContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Mono.Collections.Generic;
|
||||
using MD = Mono.Cecil.Metadata;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class FunctionPointerType : TypeSpecification, IMethodSignature {
|
||||
|
||||
readonly MethodReference function;
|
||||
|
||||
public bool HasThis {
|
||||
get { return function.HasThis; }
|
||||
set { function.HasThis = value; }
|
||||
}
|
||||
|
||||
public bool ExplicitThis {
|
||||
get { return function.ExplicitThis; }
|
||||
set { function.ExplicitThis = value; }
|
||||
}
|
||||
|
||||
public MethodCallingConvention CallingConvention {
|
||||
get { return function.CallingConvention; }
|
||||
set { function.CallingConvention = value; }
|
||||
}
|
||||
|
||||
public bool HasParameters {
|
||||
get { return function.HasParameters; }
|
||||
}
|
||||
|
||||
public Collection<ParameterDefinition> Parameters {
|
||||
get { return function.Parameters; }
|
||||
}
|
||||
|
||||
public TypeReference ReturnType {
|
||||
get { return function.MethodReturnType.ReturnType; }
|
||||
set { function.MethodReturnType.ReturnType = value; }
|
||||
}
|
||||
|
||||
public MethodReturnType MethodReturnType {
|
||||
get { return function.MethodReturnType; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return function.Name; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override string Namespace {
|
||||
get { return string.Empty; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override ModuleDefinition Module {
|
||||
get { return ReturnType.Module; }
|
||||
}
|
||||
|
||||
public override IMetadataScope Scope {
|
||||
get { return function.ReturnType.Scope; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override bool IsFunctionPointer {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool ContainsGenericParameter {
|
||||
get { return function.ContainsGenericParameter; }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get {
|
||||
var signature = new StringBuilder ();
|
||||
signature.Append (function.Name);
|
||||
signature.Append (" ");
|
||||
signature.Append (function.ReturnType.FullName);
|
||||
signature.Append (" *");
|
||||
this.MethodSignatureFullName (signature);
|
||||
return signature.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public FunctionPointerType ()
|
||||
: base (null)
|
||||
{
|
||||
this.function = new MethodReference ();
|
||||
this.function.Name = "method";
|
||||
this.etype = MD.ElementType.FnPtr;
|
||||
}
|
||||
|
||||
public override TypeDefinition Resolve ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override TypeReference GetElementType ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class GenericInstanceMethod : MethodSpecification, IGenericInstance, IGenericContext {
|
||||
|
||||
Collection<TypeReference> arguments;
|
||||
|
||||
public bool HasGenericArguments {
|
||||
get { return !arguments.IsNullOrEmpty (); }
|
||||
}
|
||||
|
||||
public Collection<TypeReference> GenericArguments {
|
||||
get { return arguments ?? (arguments = new Collection<TypeReference> ()); }
|
||||
}
|
||||
|
||||
public override bool IsGenericInstance {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
IGenericParameterProvider IGenericContext.Method {
|
||||
get { return ElementMethod; }
|
||||
}
|
||||
|
||||
IGenericParameterProvider IGenericContext.Type {
|
||||
get { return ElementMethod.DeclaringType; }
|
||||
}
|
||||
|
||||
public override bool ContainsGenericParameter {
|
||||
get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get {
|
||||
var signature = new StringBuilder ();
|
||||
var method = this.ElementMethod;
|
||||
signature.Append (method.ReturnType.FullName)
|
||||
.Append (" ")
|
||||
.Append (method.DeclaringType.FullName)
|
||||
.Append ("::")
|
||||
.Append (method.Name);
|
||||
this.GenericInstanceFullName (signature);
|
||||
this.MethodSignatureFullName (signature);
|
||||
return signature.ToString ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public GenericInstanceMethod (MethodReference method)
|
||||
: base (method)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
using MD = Mono.Cecil.Metadata;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext {
|
||||
|
||||
Collection<TypeReference> arguments;
|
||||
|
||||
public bool HasGenericArguments {
|
||||
get { return !arguments.IsNullOrEmpty (); }
|
||||
}
|
||||
|
||||
public Collection<TypeReference> GenericArguments {
|
||||
get { return arguments ?? (arguments = new Collection<TypeReference> ()); }
|
||||
}
|
||||
|
||||
public override TypeReference DeclaringType {
|
||||
get { return ElementType.DeclaringType; }
|
||||
set { throw new NotSupportedException (); }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get {
|
||||
var name = new StringBuilder ();
|
||||
name.Append (base.FullName);
|
||||
this.GenericInstanceFullName (name);
|
||||
return name.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsGenericInstance {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool ContainsGenericParameter {
|
||||
get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; }
|
||||
}
|
||||
|
||||
IGenericParameterProvider IGenericContext.Type {
|
||||
get { return ElementType; }
|
||||
}
|
||||
|
||||
public GenericInstanceType (TypeReference type)
|
||||
: base (type)
|
||||
{
|
||||
base.IsValueType = type.IsValueType;
|
||||
this.etype = MD.ElementType.GenericInst;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
using Mono.Cecil.Metadata;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class GenericParameter : TypeReference, ICustomAttributeProvider {
|
||||
|
||||
internal int position;
|
||||
internal GenericParameterType type;
|
||||
internal IGenericParameterProvider owner;
|
||||
|
||||
ushort attributes;
|
||||
Collection<TypeReference> constraints;
|
||||
Collection<CustomAttribute> custom_attributes;
|
||||
|
||||
public GenericParameterAttributes Attributes {
|
||||
get { return (GenericParameterAttributes) attributes; }
|
||||
set { attributes = (ushort) value; }
|
||||
}
|
||||
|
||||
public int Position {
|
||||
get { return position; }
|
||||
}
|
||||
|
||||
public GenericParameterType Type {
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public IGenericParameterProvider Owner {
|
||||
get { return owner; }
|
||||
}
|
||||
|
||||
public bool HasConstraints {
|
||||
get {
|
||||
if (constraints != null)
|
||||
return constraints.Count > 0;
|
||||
|
||||
return HasImage && Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter));
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<TypeReference> Constraints {
|
||||
get {
|
||||
if (constraints != null)
|
||||
return constraints;
|
||||
|
||||
if (HasImage)
|
||||
return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter));
|
||||
|
||||
return constraints = new Collection<TypeReference> ();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCustomAttributes {
|
||||
get {
|
||||
if (custom_attributes != null)
|
||||
return custom_attributes.Count > 0;
|
||||
|
||||
return this.GetHasCustomAttributes (Module);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CustomAttribute> CustomAttributes {
|
||||
get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); }
|
||||
}
|
||||
|
||||
public override IMetadataScope Scope {
|
||||
get {
|
||||
if (owner == null)
|
||||
return null;
|
||||
|
||||
return owner.GenericParameterType == GenericParameterType.Method
|
||||
? ((MethodReference) owner).DeclaringType.Scope
|
||||
: ((TypeReference) owner).Scope;
|
||||
}
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override TypeReference DeclaringType {
|
||||
get { return owner as TypeReference; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public MethodReference DeclaringMethod {
|
||||
get { return owner as MethodReference; }
|
||||
}
|
||||
|
||||
public override ModuleDefinition Module {
|
||||
get { return module ?? owner.Module; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
if (!string.IsNullOrEmpty (base.Name))
|
||||
return base.Name;
|
||||
|
||||
return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Namespace {
|
||||
get { return string.Empty; }
|
||||
set { throw new InvalidOperationException (); }
|
||||
}
|
||||
|
||||
public override string FullName {
|
||||
get { return Name; }
|
||||
}
|
||||
|
||||
public override bool IsGenericParameter {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool ContainsGenericParameter {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override MetadataType MetadataType {
|
||||
get { return (MetadataType) etype; }
|
||||
}
|
||||
|
||||
#region GenericParameterAttributes
|
||||
|
||||
public bool IsNonVariant {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant, value); }
|
||||
}
|
||||
|
||||
public bool IsCovariant {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant, value); }
|
||||
}
|
||||
|
||||
public bool IsContravariant {
|
||||
get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant); }
|
||||
set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant, value); }
|
||||
}
|
||||
|
||||
public bool HasReferenceTypeConstraint {
|
||||
get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.ReferenceTypeConstraint); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.ReferenceTypeConstraint, value); }
|
||||
}
|
||||
|
||||
public bool HasNotNullableValueTypeConstraint {
|
||||
get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.NotNullableValueTypeConstraint); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.NotNullableValueTypeConstraint, value); }
|
||||
}
|
||||
|
||||
public bool HasDefaultConstructorConstraint {
|
||||
get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.DefaultConstructorConstraint); }
|
||||
set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.DefaultConstructorConstraint, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public GenericParameter (IGenericParameterProvider owner)
|
||||
: this (string.Empty, owner)
|
||||
{
|
||||
}
|
||||
|
||||
public GenericParameter (string name, IGenericParameterProvider owner)
|
||||
: base (string.Empty, name)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException ();
|
||||
|
||||
this.position = -1;
|
||||
this.owner = owner;
|
||||
this.type = owner.GenericParameterType;
|
||||
this.etype = ConvertGenericParameterType (this.type);
|
||||
this.token = new MetadataToken (TokenType.GenericParam);
|
||||
|
||||
}
|
||||
|
||||
internal GenericParameter (int position, GenericParameterType type, ModuleDefinition module)
|
||||
: base (string.Empty, string.Empty)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
|
||||
this.position = position;
|
||||
this.type = type;
|
||||
this.etype = ConvertGenericParameterType (type);
|
||||
this.module = module;
|
||||
this.token = new MetadataToken (TokenType.GenericParam);
|
||||
}
|
||||
|
||||
static ElementType ConvertGenericParameterType (GenericParameterType type)
|
||||
{
|
||||
switch (type) {
|
||||
case GenericParameterType.Type:
|
||||
return ElementType.Var;
|
||||
case GenericParameterType.Method:
|
||||
return ElementType.MVar;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException ();
|
||||
}
|
||||
|
||||
public override TypeDefinition Resolve ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class GenericParameterCollection : Collection<GenericParameter> {
|
||||
|
||||
readonly IGenericParameterProvider owner;
|
||||
|
||||
internal GenericParameterCollection (IGenericParameterProvider owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
internal GenericParameterCollection (IGenericParameterProvider owner, int capacity)
|
||||
: base (capacity)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnAdd (GenericParameter item, int index)
|
||||
{
|
||||
UpdateGenericParameter (item, index);
|
||||
}
|
||||
|
||||
protected override void OnInsert (GenericParameter item, int index)
|
||||
{
|
||||
UpdateGenericParameter (item, index);
|
||||
|
||||
for (int i = index; i < size; i++)
|
||||
items[i].position = i + 1;
|
||||
}
|
||||
|
||||
protected override void OnSet (GenericParameter item, int index)
|
||||
{
|
||||
UpdateGenericParameter (item, index);
|
||||
}
|
||||
|
||||
void UpdateGenericParameter (GenericParameter item, int index)
|
||||
{
|
||||
item.owner = owner;
|
||||
item.position = index;
|
||||
item.type = owner.GenericParameterType;
|
||||
}
|
||||
|
||||
protected override void OnRemove (GenericParameter item, int index)
|
||||
{
|
||||
item.owner = null;
|
||||
item.position = -1;
|
||||
item.type = GenericParameterType.Type;
|
||||
|
||||
for (int i = index + 1; i < size; i++)
|
||||
items[i].position = i - 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
[Flags]
|
||||
public enum GenericParameterAttributes : ushort {
|
||||
VarianceMask = 0x0003,
|
||||
NonVariant = 0x0000,
|
||||
Covariant = 0x0001,
|
||||
Contravariant = 0x0002,
|
||||
|
||||
SpecialConstraintMask = 0x001c,
|
||||
ReferenceTypeConstraint = 0x0004,
|
||||
NotNullableValueTypeConstraint = 0x0008,
|
||||
DefaultConstructorConstraint = 0x0010
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IConstantProvider : IMetadataTokenProvider {
|
||||
|
||||
bool HasConstant { get; set; }
|
||||
object Constant { get; set; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
internal static object NoValue = new object ();
|
||||
internal static object NotResolved = new object ();
|
||||
|
||||
public static void ResolveConstant (
|
||||
this IConstantProvider self,
|
||||
ref object constant,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
if (module == null) {
|
||||
constant = Mixin.NoValue;
|
||||
return;
|
||||
}
|
||||
|
||||
lock (module.SyncRoot) {
|
||||
if (constant != Mixin.NotResolved)
|
||||
return;
|
||||
if (module.HasImage ())
|
||||
constant = module.Read (self, (provider, reader) => reader.ReadConstant (provider));
|
||||
else
|
||||
constant = Mixin.NoValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface ICustomAttributeProvider : IMetadataTokenProvider {
|
||||
|
||||
Collection<CustomAttribute> CustomAttributes { get; }
|
||||
|
||||
bool HasCustomAttributes { get; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool GetHasCustomAttributes (
|
||||
this ICustomAttributeProvider self,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage () && module.Read (self, (provider, reader) => reader.HasCustomAttributes (provider));
|
||||
}
|
||||
|
||||
public static Collection<CustomAttribute> GetCustomAttributes (
|
||||
this ICustomAttributeProvider self,
|
||||
ref Collection<CustomAttribute> variable,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage ()
|
||||
? module.Read (ref variable, self, (provider, reader) => reader.ReadCustomAttributes (provider))
|
||||
: variable = new Collection<CustomAttribute>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IGenericInstance : IMetadataTokenProvider {
|
||||
|
||||
bool HasGenericArguments { get; }
|
||||
Collection<TypeReference> GenericArguments { get; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool ContainsGenericParameter (this IGenericInstance self)
|
||||
{
|
||||
var arguments = self.GenericArguments;
|
||||
|
||||
for (int i = 0; i < arguments.Count; i++)
|
||||
if (arguments [i].ContainsGenericParameter)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void GenericInstanceFullName (this IGenericInstance self, StringBuilder builder)
|
||||
{
|
||||
builder.Append ("<");
|
||||
var arguments = self.GenericArguments;
|
||||
for (int i = 0; i < arguments.Count; i++) {
|
||||
if (i > 0)
|
||||
builder.Append (",");
|
||||
builder.Append (arguments [i].FullName);
|
||||
}
|
||||
builder.Append (">");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IGenericParameterProvider : IMetadataTokenProvider {
|
||||
|
||||
bool HasGenericParameters { get; }
|
||||
bool IsDefinition { get; }
|
||||
ModuleDefinition Module { get; }
|
||||
Collection<GenericParameter> GenericParameters { get; }
|
||||
GenericParameterType GenericParameterType { get; }
|
||||
}
|
||||
|
||||
public enum GenericParameterType {
|
||||
Type,
|
||||
Method
|
||||
}
|
||||
|
||||
interface IGenericContext {
|
||||
|
||||
bool IsDefinition { get; }
|
||||
IGenericParameterProvider Type { get; }
|
||||
IGenericParameterProvider Method { get; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool GetHasGenericParameters (
|
||||
this IGenericParameterProvider self,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage () && module.Read (self, (provider, reader) => reader.HasGenericParameters (provider));
|
||||
}
|
||||
|
||||
public static Collection<GenericParameter> GetGenericParameters (
|
||||
this IGenericParameterProvider self,
|
||||
ref Collection<GenericParameter> collection,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage ()
|
||||
? module.Read (ref collection, self, (provider, reader) => reader.ReadGenericParameters (provider))
|
||||
: collection = new GenericParameterCollection (self);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IMarshalInfoProvider : IMetadataTokenProvider {
|
||||
|
||||
bool HasMarshalInfo { get; }
|
||||
MarshalInfo MarshalInfo { get; set; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool GetHasMarshalInfo (
|
||||
this IMarshalInfoProvider self,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage () && module.Read (self, (provider, reader) => reader.HasMarshalInfo (provider));
|
||||
}
|
||||
|
||||
public static MarshalInfo GetMarshalInfo (
|
||||
this IMarshalInfoProvider self,
|
||||
ref MarshalInfo variable,
|
||||
ModuleDefinition module)
|
||||
{
|
||||
return module.HasImage ()
|
||||
? module.Read (ref variable, self, (provider, reader) => reader.ReadMarshalInfo (provider))
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IMemberDefinition : ICustomAttributeProvider {
|
||||
|
||||
string Name { get; set; }
|
||||
string FullName { get; }
|
||||
|
||||
bool IsSpecialName { get; set; }
|
||||
bool IsRuntimeSpecialName { get; set; }
|
||||
|
||||
TypeDefinition DeclaringType { get; set; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool GetAttributes (this uint self, uint attributes)
|
||||
{
|
||||
return (self & attributes) != 0;
|
||||
}
|
||||
|
||||
public static uint SetAttributes (this uint self, uint attributes, bool value)
|
||||
{
|
||||
if (value)
|
||||
return self | attributes;
|
||||
|
||||
return self & ~attributes;
|
||||
}
|
||||
|
||||
public static bool GetMaskedAttributes (this uint self, uint mask, uint attributes)
|
||||
{
|
||||
return (self & mask) == attributes;
|
||||
}
|
||||
|
||||
public static uint SetMaskedAttributes (this uint self, uint mask, uint attributes, bool value)
|
||||
{
|
||||
if (value) {
|
||||
self &= ~mask;
|
||||
return self | attributes;
|
||||
}
|
||||
|
||||
return self & ~(mask & attributes);
|
||||
}
|
||||
|
||||
public static bool GetAttributes (this ushort self, ushort attributes)
|
||||
{
|
||||
return (self & attributes) != 0;
|
||||
}
|
||||
|
||||
public static ushort SetAttributes (this ushort self, ushort attributes, bool value)
|
||||
{
|
||||
if (value)
|
||||
return (ushort) (self | attributes);
|
||||
|
||||
return (ushort) (self & ~attributes);
|
||||
}
|
||||
|
||||
public static bool GetMaskedAttributes (this ushort self, ushort mask, uint attributes)
|
||||
{
|
||||
return (self & mask) == attributes;
|
||||
}
|
||||
|
||||
public static ushort SetMaskedAttributes (this ushort self, ushort mask, uint attributes, bool value)
|
||||
{
|
||||
if (value) {
|
||||
self = (ushort) (self & ~mask);
|
||||
return (ushort) (self | attributes);
|
||||
}
|
||||
|
||||
return (ushort) (self & ~(mask & attributes));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public enum MetadataScopeType {
|
||||
AssemblyNameReference,
|
||||
ModuleReference,
|
||||
ModuleDefinition,
|
||||
}
|
||||
|
||||
public interface IMetadataScope : IMetadataTokenProvider {
|
||||
MetadataScopeType MetadataScopeType { get; }
|
||||
string Name { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IMetadataTokenProvider {
|
||||
|
||||
MetadataToken MetadataToken { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System.Text;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public interface IMethodSignature : IMetadataTokenProvider {
|
||||
|
||||
bool HasThis { get; set; }
|
||||
bool ExplicitThis { get; set; }
|
||||
MethodCallingConvention CallingConvention { get; set; }
|
||||
|
||||
bool HasParameters { get; }
|
||||
Collection<ParameterDefinition> Parameters { get; }
|
||||
TypeReference ReturnType { get; set; }
|
||||
MethodReturnType MethodReturnType { get; }
|
||||
}
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static bool HasImplicitThis (this IMethodSignature self)
|
||||
{
|
||||
return self.HasThis && !self.ExplicitThis;
|
||||
}
|
||||
|
||||
public static void MethodSignatureFullName (this IMethodSignature self, StringBuilder builder)
|
||||
{
|
||||
builder.Append ("(");
|
||||
|
||||
if (self.HasParameters) {
|
||||
var parameters = self.Parameters;
|
||||
for (int i = 0; i < parameters.Count; i++) {
|
||||
var parameter = parameters [i];
|
||||
if (i > 0)
|
||||
builder.Append (",");
|
||||
|
||||
if (parameter.ParameterType.IsSentinel)
|
||||
builder.Append ("...,");
|
||||
|
||||
builder.Append (parameter.ParameterType.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append (")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,829 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Collections.Generic;
|
||||
using SR = System.Reflection;
|
||||
|
||||
using Mono.Cecil.Metadata;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
public interface IMetadataImporterProvider {
|
||||
IMetadataImporter GetMetadataImporter (ModuleDefinition module);
|
||||
}
|
||||
|
||||
public interface IMetadataImporter {
|
||||
AssemblyNameReference ImportReference (AssemblyNameReference reference);
|
||||
TypeReference ImportReference (TypeReference type, IGenericParameterProvider context);
|
||||
FieldReference ImportReference (FieldReference field, IGenericParameterProvider context);
|
||||
MethodReference ImportReference (MethodReference method, IGenericParameterProvider context);
|
||||
}
|
||||
|
||||
public interface IReflectionImporterProvider {
|
||||
IReflectionImporter GetReflectionImporter (ModuleDefinition module);
|
||||
}
|
||||
|
||||
public interface IReflectionImporter {
|
||||
AssemblyNameReference ImportReference (SR.AssemblyName reference);
|
||||
TypeReference ImportReference (Type type, IGenericParameterProvider context);
|
||||
FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context);
|
||||
MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context);
|
||||
}
|
||||
|
||||
struct ImportGenericContext {
|
||||
|
||||
Collection<IGenericParameterProvider> stack;
|
||||
|
||||
public bool IsEmpty { get { return stack == null; } }
|
||||
|
||||
public ImportGenericContext (IGenericParameterProvider provider)
|
||||
{
|
||||
if (provider == null)
|
||||
throw new ArgumentNullException ("provider");
|
||||
|
||||
stack = null;
|
||||
|
||||
Push (provider);
|
||||
}
|
||||
|
||||
public void Push (IGenericParameterProvider provider)
|
||||
{
|
||||
if (stack == null)
|
||||
stack = new Collection<IGenericParameterProvider> (1) { provider };
|
||||
else
|
||||
stack.Add (provider);
|
||||
}
|
||||
|
||||
public void Pop ()
|
||||
{
|
||||
stack.RemoveAt (stack.Count - 1);
|
||||
}
|
||||
|
||||
public TypeReference MethodParameter (string method, int position)
|
||||
{
|
||||
for (int i = stack.Count - 1; i >= 0; i--) {
|
||||
var candidate = stack [i] as MethodReference;
|
||||
if (candidate == null)
|
||||
continue;
|
||||
|
||||
if (method != NormalizeMethodName (candidate))
|
||||
continue;
|
||||
|
||||
return candidate.GenericParameters [position];
|
||||
}
|
||||
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
public string NormalizeMethodName (MethodReference method)
|
||||
{
|
||||
return method.DeclaringType.GetElementType ().FullName + "." + method.Name;
|
||||
}
|
||||
|
||||
public TypeReference TypeParameter (string type, int position)
|
||||
{
|
||||
for (int i = stack.Count - 1; i >= 0; i--) {
|
||||
var candidate = GenericTypeFor (stack [i]);
|
||||
|
||||
if (candidate.FullName != type)
|
||||
continue;
|
||||
|
||||
return candidate.GenericParameters [position];
|
||||
}
|
||||
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
static TypeReference GenericTypeFor (IGenericParameterProvider context)
|
||||
{
|
||||
var type = context as TypeReference;
|
||||
if (type != null)
|
||||
return type.GetElementType ();
|
||||
|
||||
var method = context as MethodReference;
|
||||
if (method != null)
|
||||
return method.DeclaringType.GetElementType ();
|
||||
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
public static ImportGenericContext For (IGenericParameterProvider context)
|
||||
{
|
||||
return context != null ? new ImportGenericContext (context) : default (ImportGenericContext);
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultReflectionImporter : IReflectionImporter {
|
||||
|
||||
readonly protected ModuleDefinition module;
|
||||
|
||||
public DefaultReflectionImporter (ModuleDefinition module)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
enum ImportGenericKind {
|
||||
Definition,
|
||||
Open,
|
||||
}
|
||||
|
||||
static readonly Dictionary<Type, ElementType> type_etype_mapping = new Dictionary<Type, ElementType> (18) {
|
||||
{ typeof (void), ElementType.Void },
|
||||
{ typeof (bool), ElementType.Boolean },
|
||||
{ typeof (char), ElementType.Char },
|
||||
{ typeof (sbyte), ElementType.I1 },
|
||||
{ typeof (byte), ElementType.U1 },
|
||||
{ typeof (short), ElementType.I2 },
|
||||
{ typeof (ushort), ElementType.U2 },
|
||||
{ typeof (int), ElementType.I4 },
|
||||
{ typeof (uint), ElementType.U4 },
|
||||
{ typeof (long), ElementType.I8 },
|
||||
{ typeof (ulong), ElementType.U8 },
|
||||
{ typeof (float), ElementType.R4 },
|
||||
{ typeof (double), ElementType.R8 },
|
||||
{ typeof (string), ElementType.String },
|
||||
#if !NET_CORE
|
||||
{ typeof (TypedReference), ElementType.TypedByRef },
|
||||
#endif
|
||||
{ typeof (IntPtr), ElementType.I },
|
||||
{ typeof (UIntPtr), ElementType.U },
|
||||
{ typeof (object), ElementType.Object },
|
||||
};
|
||||
|
||||
TypeReference ImportType (Type type, ImportGenericContext context)
|
||||
{
|
||||
return ImportType (type, context, ImportGenericKind.Open);
|
||||
}
|
||||
|
||||
TypeReference ImportType (Type type, ImportGenericContext context, ImportGenericKind import_kind)
|
||||
{
|
||||
if (IsTypeSpecification (type) || ImportOpenGenericType (type, import_kind))
|
||||
return ImportTypeSpecification (type, context);
|
||||
|
||||
var reference = new TypeReference (
|
||||
string.Empty,
|
||||
type.Name,
|
||||
module,
|
||||
ImportScope (type),
|
||||
type.IsValueType ());
|
||||
|
||||
reference.etype = ImportElementType (type);
|
||||
|
||||
if (IsNestedType (type))
|
||||
reference.DeclaringType = ImportType (type.DeclaringType, context, import_kind);
|
||||
else
|
||||
reference.Namespace = type.Namespace ?? string.Empty;
|
||||
|
||||
if (type.IsGenericType ())
|
||||
ImportGenericParameters (reference, type.GetGenericArguments ());
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
protected virtual IMetadataScope ImportScope (Type type)
|
||||
{
|
||||
return ImportScope (type.Assembly ());
|
||||
}
|
||||
|
||||
static bool ImportOpenGenericType (Type type, ImportGenericKind import_kind)
|
||||
{
|
||||
return type.IsGenericType () && type.IsGenericTypeDefinition () && import_kind == ImportGenericKind.Open;
|
||||
}
|
||||
|
||||
static bool ImportOpenGenericMethod (SR.MethodBase method, ImportGenericKind import_kind)
|
||||
{
|
||||
return method.IsGenericMethod && method.IsGenericMethodDefinition && import_kind == ImportGenericKind.Open;
|
||||
}
|
||||
|
||||
static bool IsNestedType (Type type)
|
||||
{
|
||||
return type.IsNested;
|
||||
}
|
||||
|
||||
TypeReference ImportTypeSpecification (Type type, ImportGenericContext context)
|
||||
{
|
||||
if (type.IsByRef)
|
||||
return new ByReferenceType (ImportType (type.GetElementType (), context));
|
||||
|
||||
if (type.IsPointer)
|
||||
return new PointerType (ImportType (type.GetElementType (), context));
|
||||
|
||||
if (type.IsArray)
|
||||
return new ArrayType (ImportType (type.GetElementType (), context), type.GetArrayRank ());
|
||||
|
||||
if (type.IsGenericType ())
|
||||
return ImportGenericInstance (type, context);
|
||||
|
||||
if (type.IsGenericParameter)
|
||||
return ImportGenericParameter (type, context);
|
||||
|
||||
throw new NotSupportedException (type.FullName);
|
||||
}
|
||||
|
||||
static TypeReference ImportGenericParameter (Type type, ImportGenericContext context)
|
||||
{
|
||||
if (context.IsEmpty)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
if (type.DeclaringMethod () != null)
|
||||
return context.MethodParameter (NormalizeMethodName (type.DeclaringMethod ()), type.GenericParameterPosition);
|
||||
|
||||
if (type.DeclaringType != null)
|
||||
return context.TypeParameter (NormalizeTypeFullName (type.DeclaringType), type.GenericParameterPosition);
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
static string NormalizeMethodName (SR.MethodBase method)
|
||||
{
|
||||
return NormalizeTypeFullName (method.DeclaringType) + "." + method.Name;
|
||||
}
|
||||
|
||||
static string NormalizeTypeFullName (Type type)
|
||||
{
|
||||
if (IsNestedType (type))
|
||||
return NormalizeTypeFullName (type.DeclaringType) + "/" + type.Name;
|
||||
|
||||
return type.FullName;
|
||||
}
|
||||
|
||||
TypeReference ImportGenericInstance (Type type, ImportGenericContext context)
|
||||
{
|
||||
var element_type = ImportType (type.GetGenericTypeDefinition (), context, ImportGenericKind.Definition);
|
||||
var instance = new GenericInstanceType (element_type);
|
||||
var arguments = type.GetGenericArguments ();
|
||||
var instance_arguments = instance.GenericArguments;
|
||||
|
||||
context.Push (element_type);
|
||||
try {
|
||||
for (int i = 0; i < arguments.Length; i++)
|
||||
instance_arguments.Add (ImportType (arguments [i], context));
|
||||
|
||||
return instance;
|
||||
} finally {
|
||||
context.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsTypeSpecification (Type type)
|
||||
{
|
||||
return type.HasElementType
|
||||
|| IsGenericInstance (type)
|
||||
|| type.IsGenericParameter;
|
||||
}
|
||||
|
||||
static bool IsGenericInstance (Type type)
|
||||
{
|
||||
return type.IsGenericType () && !type.IsGenericTypeDefinition ();
|
||||
}
|
||||
|
||||
static ElementType ImportElementType (Type type)
|
||||
{
|
||||
ElementType etype;
|
||||
if (!type_etype_mapping.TryGetValue (type, out etype))
|
||||
return ElementType.None;
|
||||
|
||||
return etype;
|
||||
}
|
||||
|
||||
protected AssemblyNameReference ImportScope (SR.Assembly assembly)
|
||||
{
|
||||
return ImportReference (assembly.GetName ());
|
||||
}
|
||||
|
||||
public virtual AssemblyNameReference ImportReference (SR.AssemblyName name)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
|
||||
AssemblyNameReference reference;
|
||||
if (TryGetAssemblyNameReference (name, out reference))
|
||||
return reference;
|
||||
|
||||
reference = new AssemblyNameReference (name.Name, name.Version)
|
||||
{
|
||||
PublicKeyToken = name.GetPublicKeyToken (),
|
||||
#if !NET_CORE
|
||||
Culture = name.CultureInfo.Name,
|
||||
HashAlgorithm = (AssemblyHashAlgorithm) name.HashAlgorithm,
|
||||
#endif
|
||||
};
|
||||
|
||||
module.AssemblyReferences.Add (reference);
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
bool TryGetAssemblyNameReference (SR.AssemblyName name, out AssemblyNameReference assembly_reference)
|
||||
{
|
||||
var references = module.AssemblyReferences;
|
||||
|
||||
for (int i = 0; i < references.Count; i++) {
|
||||
var reference = references [i];
|
||||
if (name.FullName != reference.FullName) // TODO compare field by field
|
||||
continue;
|
||||
|
||||
assembly_reference = reference;
|
||||
return true;
|
||||
}
|
||||
|
||||
assembly_reference = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context)
|
||||
{
|
||||
var declaring_type = ImportType (field.DeclaringType, context);
|
||||
|
||||
if (IsGenericInstance (field.DeclaringType))
|
||||
field = ResolveFieldDefinition (field);
|
||||
|
||||
context.Push (declaring_type);
|
||||
try {
|
||||
return new FieldReference {
|
||||
Name = field.Name,
|
||||
DeclaringType = declaring_type,
|
||||
FieldType = ImportType (field.FieldType, context),
|
||||
};
|
||||
} finally {
|
||||
context.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
static SR.FieldInfo ResolveFieldDefinition (SR.FieldInfo field)
|
||||
{
|
||||
#if NET_CORE
|
||||
throw new NotImplementedException ();
|
||||
#else
|
||||
return field.Module.ResolveField (field.MetadataToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SR.MethodBase ResolveMethodDefinition (SR.MethodBase method)
|
||||
{
|
||||
#if NET_CORE
|
||||
throw new NotImplementedException ();
|
||||
#else
|
||||
return method.Module.ResolveMethod (method.MetadataToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind)
|
||||
{
|
||||
if (IsMethodSpecification (method) || ImportOpenGenericMethod (method, import_kind))
|
||||
return ImportMethodSpecification (method, context);
|
||||
|
||||
var declaring_type = ImportType (method.DeclaringType, context);
|
||||
|
||||
if (IsGenericInstance (method.DeclaringType))
|
||||
method = ResolveMethodDefinition (method);
|
||||
|
||||
var reference = new MethodReference {
|
||||
Name = method.Name,
|
||||
HasThis = HasCallingConvention (method, SR.CallingConventions.HasThis),
|
||||
ExplicitThis = HasCallingConvention (method, SR.CallingConventions.ExplicitThis),
|
||||
DeclaringType = ImportType (method.DeclaringType, context, ImportGenericKind.Definition),
|
||||
};
|
||||
|
||||
if (HasCallingConvention (method, SR.CallingConventions.VarArgs))
|
||||
reference.CallingConvention &= MethodCallingConvention.VarArg;
|
||||
|
||||
if (method.IsGenericMethod)
|
||||
ImportGenericParameters (reference, method.GetGenericArguments ());
|
||||
|
||||
context.Push (reference);
|
||||
try {
|
||||
var method_info = method as SR.MethodInfo;
|
||||
reference.ReturnType = method_info != null
|
||||
? ImportType (method_info.ReturnType, context)
|
||||
: ImportType (typeof (void), default (ImportGenericContext));
|
||||
|
||||
var parameters = method.GetParameters ();
|
||||
var reference_parameters = reference.Parameters;
|
||||
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
reference_parameters.Add (
|
||||
new ParameterDefinition (ImportType (parameters [i].ParameterType, context)));
|
||||
|
||||
reference.DeclaringType = declaring_type;
|
||||
|
||||
return reference;
|
||||
} finally {
|
||||
context.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
static void ImportGenericParameters (IGenericParameterProvider provider, Type [] arguments)
|
||||
{
|
||||
var provider_parameters = provider.GenericParameters;
|
||||
|
||||
for (int i = 0; i < arguments.Length; i++)
|
||||
provider_parameters.Add (new GenericParameter (arguments [i].Name, provider));
|
||||
}
|
||||
|
||||
static bool IsMethodSpecification (SR.MethodBase method)
|
||||
{
|
||||
return method.IsGenericMethod && !method.IsGenericMethodDefinition;
|
||||
}
|
||||
|
||||
MethodReference ImportMethodSpecification (SR.MethodBase method, ImportGenericContext context)
|
||||
{
|
||||
var method_info = method as SR.MethodInfo;
|
||||
if (method_info == null)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
var element_method = ImportMethod (method_info.GetGenericMethodDefinition (), context, ImportGenericKind.Definition);
|
||||
var instance = new GenericInstanceMethod (element_method);
|
||||
var arguments = method.GetGenericArguments ();
|
||||
var instance_arguments = instance.GenericArguments;
|
||||
|
||||
context.Push (element_method);
|
||||
try {
|
||||
for (int i = 0; i < arguments.Length; i++)
|
||||
instance_arguments.Add (ImportType (arguments [i], context));
|
||||
|
||||
return instance;
|
||||
} finally {
|
||||
context.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
static bool HasCallingConvention (SR.MethodBase method, SR.CallingConventions conventions)
|
||||
{
|
||||
return (method.CallingConvention & conventions) != 0;
|
||||
}
|
||||
|
||||
public virtual TypeReference ImportReference (Type type, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckType (type);
|
||||
return ImportType (
|
||||
type,
|
||||
ImportGenericContext.For (context),
|
||||
context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
|
||||
}
|
||||
|
||||
public virtual FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckField (field);
|
||||
return ImportField (field, ImportGenericContext.For (context));
|
||||
}
|
||||
|
||||
public virtual MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckMethod (method);
|
||||
return ImportMethod (method,
|
||||
ImportGenericContext.For (context),
|
||||
context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultMetadataImporter : IMetadataImporter {
|
||||
|
||||
readonly protected ModuleDefinition module;
|
||||
|
||||
public DefaultMetadataImporter (ModuleDefinition module)
|
||||
{
|
||||
Mixin.CheckModule (module);
|
||||
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
TypeReference ImportType (TypeReference type, ImportGenericContext context)
|
||||
{
|
||||
if (type.IsTypeSpecification ())
|
||||
return ImportTypeSpecification (type, context);
|
||||
|
||||
var reference = new TypeReference (
|
||||
type.Namespace,
|
||||
type.Name,
|
||||
module,
|
||||
ImportScope (type),
|
||||
type.IsValueType);
|
||||
|
||||
MetadataSystem.TryProcessPrimitiveTypeReference (reference);
|
||||
|
||||
if (type.IsNested)
|
||||
reference.DeclaringType = ImportType (type.DeclaringType, context);
|
||||
|
||||
if (type.HasGenericParameters)
|
||||
ImportGenericParameters (reference, type);
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
protected virtual IMetadataScope ImportScope (TypeReference type)
|
||||
{
|
||||
return ImportScope (type.Scope);
|
||||
}
|
||||
|
||||
protected IMetadataScope ImportScope (IMetadataScope scope)
|
||||
{
|
||||
switch (scope.MetadataScopeType) {
|
||||
case MetadataScopeType.AssemblyNameReference:
|
||||
return ImportReference ((AssemblyNameReference) scope);
|
||||
case MetadataScopeType.ModuleDefinition:
|
||||
if (scope == module) return scope;
|
||||
return ImportReference (((ModuleDefinition) scope).Assembly.Name);
|
||||
case MetadataScopeType.ModuleReference:
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public virtual AssemblyNameReference ImportReference (AssemblyNameReference name)
|
||||
{
|
||||
Mixin.CheckName (name);
|
||||
|
||||
AssemblyNameReference reference;
|
||||
if (module.TryGetAssemblyNameReference (name, out reference))
|
||||
return reference;
|
||||
|
||||
reference = new AssemblyNameReference (name.Name, name.Version) {
|
||||
Culture = name.Culture,
|
||||
HashAlgorithm = name.HashAlgorithm,
|
||||
IsRetargetable = name.IsRetargetable,
|
||||
IsWindowsRuntime = name.IsWindowsRuntime,
|
||||
};
|
||||
|
||||
var pk_token = !name.PublicKeyToken.IsNullOrEmpty ()
|
||||
? new byte [name.PublicKeyToken.Length]
|
||||
: Empty<byte>.Array;
|
||||
|
||||
if (pk_token.Length > 0)
|
||||
Buffer.BlockCopy (name.PublicKeyToken, 0, pk_token, 0, pk_token.Length);
|
||||
|
||||
reference.PublicKeyToken = pk_token;
|
||||
|
||||
module.AssemblyReferences.Add (reference);
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
static void ImportGenericParameters (IGenericParameterProvider imported, IGenericParameterProvider original)
|
||||
{
|
||||
var parameters = original.GenericParameters;
|
||||
var imported_parameters = imported.GenericParameters;
|
||||
|
||||
for (int i = 0; i < parameters.Count; i++)
|
||||
imported_parameters.Add (new GenericParameter (parameters [i].Name, imported));
|
||||
}
|
||||
|
||||
TypeReference ImportTypeSpecification (TypeReference type, ImportGenericContext context)
|
||||
{
|
||||
switch (type.etype) {
|
||||
case ElementType.SzArray:
|
||||
var vector = (ArrayType) type;
|
||||
return new ArrayType (ImportType (vector.ElementType, context));
|
||||
case ElementType.Ptr:
|
||||
var pointer = (PointerType) type;
|
||||
return new PointerType (ImportType (pointer.ElementType, context));
|
||||
case ElementType.ByRef:
|
||||
var byref = (ByReferenceType) type;
|
||||
return new ByReferenceType (ImportType (byref.ElementType, context));
|
||||
case ElementType.Pinned:
|
||||
var pinned = (PinnedType) type;
|
||||
return new PinnedType (ImportType (pinned.ElementType, context));
|
||||
case ElementType.Sentinel:
|
||||
var sentinel = (SentinelType) type;
|
||||
return new SentinelType (ImportType (sentinel.ElementType, context));
|
||||
case ElementType.FnPtr:
|
||||
var fnptr = (FunctionPointerType) type;
|
||||
var imported_fnptr = new FunctionPointerType () {
|
||||
HasThis = fnptr.HasThis,
|
||||
ExplicitThis = fnptr.ExplicitThis,
|
||||
CallingConvention = fnptr.CallingConvention,
|
||||
ReturnType = ImportType (fnptr.ReturnType, context),
|
||||
};
|
||||
|
||||
if (!fnptr.HasParameters)
|
||||
return imported_fnptr;
|
||||
|
||||
for (int i = 0; i < fnptr.Parameters.Count; i++)
|
||||
imported_fnptr.Parameters.Add (new ParameterDefinition (
|
||||
ImportType (fnptr.Parameters [i].ParameterType, context)));
|
||||
|
||||
return imported_fnptr;
|
||||
case ElementType.CModOpt:
|
||||
var modopt = (OptionalModifierType) type;
|
||||
return new OptionalModifierType (
|
||||
ImportType (modopt.ModifierType, context),
|
||||
ImportType (modopt.ElementType, context));
|
||||
case ElementType.CModReqD:
|
||||
var modreq = (RequiredModifierType) type;
|
||||
return new RequiredModifierType (
|
||||
ImportType (modreq.ModifierType, context),
|
||||
ImportType (modreq.ElementType, context));
|
||||
case ElementType.Array:
|
||||
var array = (ArrayType) type;
|
||||
var imported_array = new ArrayType (ImportType (array.ElementType, context));
|
||||
if (array.IsVector)
|
||||
return imported_array;
|
||||
|
||||
var dimensions = array.Dimensions;
|
||||
var imported_dimensions = imported_array.Dimensions;
|
||||
|
||||
imported_dimensions.Clear ();
|
||||
|
||||
for (int i = 0; i < dimensions.Count; i++) {
|
||||
var dimension = dimensions [i];
|
||||
|
||||
imported_dimensions.Add (new ArrayDimension (dimension.LowerBound, dimension.UpperBound));
|
||||
}
|
||||
|
||||
return imported_array;
|
||||
case ElementType.GenericInst:
|
||||
var instance = (GenericInstanceType) type;
|
||||
var element_type = ImportType (instance.ElementType, context);
|
||||
var imported_instance = new GenericInstanceType (element_type);
|
||||
|
||||
var arguments = instance.GenericArguments;
|
||||
var imported_arguments = imported_instance.GenericArguments;
|
||||
|
||||
for (int i = 0; i < arguments.Count; i++)
|
||||
imported_arguments.Add (ImportType (arguments [i], context));
|
||||
|
||||
return imported_instance;
|
||||
case ElementType.Var:
|
||||
var var_parameter = (GenericParameter) type;
|
||||
if (var_parameter.DeclaringType == null)
|
||||
throw new InvalidOperationException ();
|
||||
return context.TypeParameter (var_parameter.DeclaringType.FullName, var_parameter.Position);
|
||||
case ElementType.MVar:
|
||||
var mvar_parameter = (GenericParameter) type;
|
||||
if (mvar_parameter.DeclaringMethod == null)
|
||||
throw new InvalidOperationException ();
|
||||
return context.MethodParameter (context.NormalizeMethodName (mvar_parameter.DeclaringMethod), mvar_parameter.Position);
|
||||
}
|
||||
|
||||
throw new NotSupportedException (type.etype.ToString ());
|
||||
}
|
||||
|
||||
FieldReference ImportField (FieldReference field, ImportGenericContext context)
|
||||
{
|
||||
var declaring_type = ImportType (field.DeclaringType, context);
|
||||
|
||||
context.Push (declaring_type);
|
||||
try {
|
||||
return new FieldReference {
|
||||
Name = field.Name,
|
||||
DeclaringType = declaring_type,
|
||||
FieldType = ImportType (field.FieldType, context),
|
||||
};
|
||||
} finally {
|
||||
context.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
MethodReference ImportMethod (MethodReference method, ImportGenericContext context)
|
||||
{
|
||||
if (method.IsGenericInstance)
|
||||
return ImportMethodSpecification (method, context);
|
||||
|
||||
var declaring_type = ImportType (method.DeclaringType, context);
|
||||
|
||||
var reference = new MethodReference {
|
||||
Name = method.Name,
|
||||
HasThis = method.HasThis,
|
||||
ExplicitThis = method.ExplicitThis,
|
||||
DeclaringType = declaring_type,
|
||||
CallingConvention = method.CallingConvention,
|
||||
};
|
||||
|
||||
if (method.HasGenericParameters)
|
||||
ImportGenericParameters (reference, method);
|
||||
|
||||
context.Push (reference);
|
||||
try {
|
||||
reference.ReturnType = ImportType (method.ReturnType, context);
|
||||
|
||||
if (!method.HasParameters)
|
||||
return reference;
|
||||
|
||||
var parameters = method.Parameters;
|
||||
var reference_parameters = reference.parameters = new ParameterDefinitionCollection (reference, parameters.Count);
|
||||
for (int i = 0; i < parameters.Count; i++)
|
||||
reference_parameters.Add (
|
||||
new ParameterDefinition (ImportType (parameters [i].ParameterType, context)));
|
||||
|
||||
return reference;
|
||||
} finally {
|
||||
context.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
MethodSpecification ImportMethodSpecification (MethodReference method, ImportGenericContext context)
|
||||
{
|
||||
if (!method.IsGenericInstance)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
var instance = (GenericInstanceMethod) method;
|
||||
var element_method = ImportMethod (instance.ElementMethod, context);
|
||||
var imported_instance = new GenericInstanceMethod (element_method);
|
||||
|
||||
var arguments = instance.GenericArguments;
|
||||
var imported_arguments = imported_instance.GenericArguments;
|
||||
|
||||
for (int i = 0; i < arguments.Count; i++)
|
||||
imported_arguments.Add (ImportType (arguments [i], context));
|
||||
|
||||
return imported_instance;
|
||||
}
|
||||
|
||||
public virtual TypeReference ImportReference (TypeReference type, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckType (type);
|
||||
return ImportType (type, ImportGenericContext.For (context));
|
||||
}
|
||||
|
||||
public virtual FieldReference ImportReference (FieldReference field, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckField (field);
|
||||
return ImportField (field, ImportGenericContext.For (context));
|
||||
}
|
||||
|
||||
public virtual MethodReference ImportReference (MethodReference method, IGenericParameterProvider context)
|
||||
{
|
||||
Mixin.CheckMethod (method);
|
||||
return ImportMethod (method, ImportGenericContext.For (context));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static partial class Mixin {
|
||||
|
||||
public static void CheckModule (ModuleDefinition module)
|
||||
{
|
||||
if (module == null)
|
||||
throw new ArgumentNullException (Argument.module.ToString ());
|
||||
}
|
||||
|
||||
public static bool TryGetAssemblyNameReference (this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference)
|
||||
{
|
||||
var references = module.AssemblyReferences;
|
||||
|
||||
for (int i = 0; i < references.Count; i++) {
|
||||
var reference = references [i];
|
||||
if (!Equals (name_reference, reference))
|
||||
continue;
|
||||
|
||||
assembly_reference = reference;
|
||||
return true;
|
||||
}
|
||||
|
||||
assembly_reference = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Equals (byte [] a, byte [] b)
|
||||
{
|
||||
if (ReferenceEquals (a, b))
|
||||
return true;
|
||||
if (a == null)
|
||||
return false;
|
||||
if (a.Length != b.Length)
|
||||
return false;
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
if (a [i] != b [i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Equals<T> (T a, T b) where T : class, IEquatable<T>
|
||||
{
|
||||
if (ReferenceEquals (a, b))
|
||||
return true;
|
||||
if (a == null)
|
||||
return false;
|
||||
return a.Equals (b);
|
||||
}
|
||||
|
||||
static bool Equals (AssemblyNameReference a, AssemblyNameReference b)
|
||||
{
|
||||
if (ReferenceEquals (a, b))
|
||||
return true;
|
||||
if (a.Name != b.Name)
|
||||
return false;
|
||||
if (!Equals (a.Version, b.Version))
|
||||
return false;
|
||||
if (a.Culture != b.Culture)
|
||||
return false;
|
||||
if (!Equals (a.PublicKeyToken, b.PublicKeyToken))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public sealed class LinkedResource : Resource {
|
||||
|
||||
internal byte [] hash;
|
||||
string file;
|
||||
|
||||
public byte [] Hash {
|
||||
get { return hash; }
|
||||
}
|
||||
|
||||
public string File {
|
||||
get { return file; }
|
||||
set { file = value; }
|
||||
}
|
||||
|
||||
public override ResourceType ResourceType {
|
||||
get { return ResourceType.Linked; }
|
||||
}
|
||||
|
||||
public LinkedResource (string name, ManifestResourceAttributes flags)
|
||||
: base (name, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public LinkedResource (string name, ManifestResourceAttributes flags, string file)
|
||||
: base (name, flags)
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
[Flags]
|
||||
public enum ManifestResourceAttributes : uint {
|
||||
VisibilityMask = 0x0007,
|
||||
Public = 0x0001, // The resource is exported from the Assembly
|
||||
Private = 0x0002 // The resource is private to the Assembly
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public class MarshalInfo {
|
||||
|
||||
internal NativeType native;
|
||||
|
||||
public NativeType NativeType {
|
||||
get { return native; }
|
||||
set { native = value; }
|
||||
}
|
||||
|
||||
public MarshalInfo (NativeType native)
|
||||
{
|
||||
this.native = native;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ArrayMarshalInfo : MarshalInfo {
|
||||
|
||||
internal NativeType element_type;
|
||||
internal int size_parameter_index;
|
||||
internal int size;
|
||||
internal int size_parameter_multiplier;
|
||||
|
||||
public NativeType ElementType {
|
||||
get { return element_type; }
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public int SizeParameterIndex {
|
||||
get { return size_parameter_index; }
|
||||
set { size_parameter_index = value; }
|
||||
}
|
||||
|
||||
public int Size {
|
||||
get { return size; }
|
||||
set { size = value; }
|
||||
}
|
||||
|
||||
public int SizeParameterMultiplier {
|
||||
get { return size_parameter_multiplier; }
|
||||
set { size_parameter_multiplier = value; }
|
||||
}
|
||||
|
||||
public ArrayMarshalInfo ()
|
||||
: base (NativeType.Array)
|
||||
{
|
||||
element_type = NativeType.None;
|
||||
size_parameter_index = -1;
|
||||
size = -1;
|
||||
size_parameter_multiplier = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CustomMarshalInfo : MarshalInfo {
|
||||
|
||||
internal Guid guid;
|
||||
internal string unmanaged_type;
|
||||
internal TypeReference managed_type;
|
||||
internal string cookie;
|
||||
|
||||
public Guid Guid {
|
||||
get { return guid; }
|
||||
set { guid = value; }
|
||||
}
|
||||
|
||||
public string UnmanagedType {
|
||||
get { return unmanaged_type; }
|
||||
set { unmanaged_type = value; }
|
||||
}
|
||||
|
||||
public TypeReference ManagedType {
|
||||
get { return managed_type; }
|
||||
set { managed_type = value; }
|
||||
}
|
||||
|
||||
public string Cookie {
|
||||
get { return cookie; }
|
||||
set { cookie = value; }
|
||||
}
|
||||
|
||||
public CustomMarshalInfo ()
|
||||
: base (NativeType.CustomMarshaler)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SafeArrayMarshalInfo : MarshalInfo {
|
||||
|
||||
internal VariantType element_type;
|
||||
|
||||
public VariantType ElementType {
|
||||
get { return element_type; }
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public SafeArrayMarshalInfo ()
|
||||
: base (NativeType.SafeArray)
|
||||
{
|
||||
element_type = VariantType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FixedArrayMarshalInfo : MarshalInfo {
|
||||
|
||||
internal NativeType element_type;
|
||||
internal int size;
|
||||
|
||||
public NativeType ElementType {
|
||||
get { return element_type; }
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public int Size {
|
||||
get { return size; }
|
||||
set { size = value; }
|
||||
}
|
||||
|
||||
public FixedArrayMarshalInfo ()
|
||||
: base (NativeType.FixedArray)
|
||||
{
|
||||
element_type = NativeType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FixedSysStringMarshalInfo : MarshalInfo {
|
||||
|
||||
internal int size;
|
||||
|
||||
public int Size {
|
||||
get { return size; }
|
||||
set { size = value; }
|
||||
}
|
||||
|
||||
public FixedSysStringMarshalInfo ()
|
||||
: base (NativeType.FixedSysString)
|
||||
{
|
||||
size = -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
sealed class MemberDefinitionCollection<T> : Collection<T> where T : IMemberDefinition {
|
||||
|
||||
TypeDefinition container;
|
||||
|
||||
internal MemberDefinitionCollection (TypeDefinition container)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
internal MemberDefinitionCollection (TypeDefinition container, int capacity)
|
||||
: base (capacity)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
protected override void OnAdd (T item, int index)
|
||||
{
|
||||
Attach (item);
|
||||
}
|
||||
|
||||
protected sealed override void OnSet (T item, int index)
|
||||
{
|
||||
Attach (item);
|
||||
}
|
||||
|
||||
protected sealed override void OnInsert (T item, int index)
|
||||
{
|
||||
Attach (item);
|
||||
}
|
||||
|
||||
protected sealed override void OnRemove (T item, int index)
|
||||
{
|
||||
Detach (item);
|
||||
}
|
||||
|
||||
protected sealed override void OnClear ()
|
||||
{
|
||||
foreach (var definition in this)
|
||||
Detach (definition);
|
||||
}
|
||||
|
||||
void Attach (T element)
|
||||
{
|
||||
if (element.DeclaringType == container)
|
||||
return;
|
||||
|
||||
if (element.DeclaringType != null)
|
||||
throw new ArgumentException ("Member already attached");
|
||||
|
||||
element.DeclaringType = this.container;
|
||||
}
|
||||
|
||||
static void Detach (T element)
|
||||
{
|
||||
element.DeclaringType = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public abstract class MemberReference : IMetadataTokenProvider {
|
||||
|
||||
string name;
|
||||
TypeReference declaring_type;
|
||||
|
||||
internal MetadataToken token;
|
||||
internal object projection;
|
||||
|
||||
public virtual string Name {
|
||||
get { return name; }
|
||||
set {
|
||||
if (IsWindowsRuntimeProjection && value != name)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
name = value;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string FullName {
|
||||
get;
|
||||
}
|
||||
|
||||
public virtual TypeReference DeclaringType {
|
||||
get { return declaring_type; }
|
||||
set { declaring_type = value; }
|
||||
}
|
||||
|
||||
public MetadataToken MetadataToken {
|
||||
get { return token; }
|
||||
set { token = value; }
|
||||
}
|
||||
|
||||
public bool IsWindowsRuntimeProjection {
|
||||
get { return projection != null; }
|
||||
}
|
||||
|
||||
internal MemberReferenceProjection WindowsRuntimeProjection {
|
||||
get { return (MemberReferenceProjection) projection; }
|
||||
set { projection = value; }
|
||||
}
|
||||
|
||||
internal bool HasImage {
|
||||
get {
|
||||
var module = Module;
|
||||
if (module == null)
|
||||
return false;
|
||||
|
||||
return module.HasImage;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ModuleDefinition Module {
|
||||
get { return declaring_type != null ? declaring_type.Module : null; }
|
||||
}
|
||||
|
||||
public virtual bool IsDefinition {
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public virtual bool ContainsGenericParameter {
|
||||
get { return declaring_type != null && declaring_type.ContainsGenericParameter; }
|
||||
}
|
||||
|
||||
internal MemberReference ()
|
||||
{
|
||||
}
|
||||
|
||||
internal MemberReference (string name)
|
||||
{
|
||||
this.name = name ?? string.Empty;
|
||||
}
|
||||
|
||||
internal string MemberFullName ()
|
||||
{
|
||||
if (declaring_type == null)
|
||||
return name;
|
||||
|
||||
return declaring_type.FullName + "::" + name;
|
||||
}
|
||||
|
||||
public IMemberDefinition Resolve ()
|
||||
{
|
||||
return ResolveDefinition ();
|
||||
}
|
||||
|
||||
protected abstract IMemberDefinition ResolveDefinition ();
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return FullName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
sealed class BlobHeap : Heap {
|
||||
|
||||
public BlobHeap (byte [] data)
|
||||
: base (data)
|
||||
{
|
||||
}
|
||||
|
||||
public byte [] Read (uint index)
|
||||
{
|
||||
if (index == 0 || index > this.data.Length - 1)
|
||||
return Empty<byte>.Array;
|
||||
|
||||
int position = (int) index;
|
||||
int length = (int) data.ReadCompressedUInt32 (ref position);
|
||||
|
||||
if (length > data.Length - position)
|
||||
return Empty<byte>.Array;
|
||||
|
||||
var buffer = new byte [length];
|
||||
|
||||
Buffer.BlockCopy (data, position, buffer, 0, length);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void GetView (uint signature, out byte [] buffer, out int index, out int length)
|
||||
{
|
||||
if (signature == 0 || signature > data.Length - 1) {
|
||||
buffer = null;
|
||||
index = length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = data;
|
||||
|
||||
index = (int) signature;
|
||||
length = (int) buffer.ReadCompressedUInt32 (ref index);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,505 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Cecil.PE;
|
||||
|
||||
using RVA = System.UInt32;
|
||||
|
||||
#if !READ_ONLY
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
sealed class TableHeapBuffer : HeapBuffer {
|
||||
|
||||
readonly ModuleDefinition module;
|
||||
readonly MetadataBuilder metadata;
|
||||
|
||||
readonly internal TableInformation [] table_infos = new TableInformation [Mixin.TableCount];
|
||||
readonly internal MetadataTable [] tables = new MetadataTable [Mixin.TableCount];
|
||||
|
||||
bool large_string;
|
||||
bool large_blob;
|
||||
bool large_guid;
|
||||
|
||||
readonly int [] coded_index_sizes = new int [Mixin.CodedIndexCount];
|
||||
readonly Func<Table, int> counter;
|
||||
|
||||
internal uint [] string_offsets;
|
||||
|
||||
public override bool IsEmpty {
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public TableHeapBuffer (ModuleDefinition module, MetadataBuilder metadata)
|
||||
: base (24)
|
||||
{
|
||||
this.module = module;
|
||||
this.metadata = metadata;
|
||||
this.counter = GetTableLength;
|
||||
}
|
||||
|
||||
int GetTableLength (Table table)
|
||||
{
|
||||
return (int) table_infos [(int) table].Length;
|
||||
}
|
||||
|
||||
public TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
|
||||
{
|
||||
var md_table = (TTable) tables [(int) table];
|
||||
if (md_table != null)
|
||||
return md_table;
|
||||
|
||||
md_table = new TTable ();
|
||||
tables [(int) table] = md_table;
|
||||
return md_table;
|
||||
}
|
||||
|
||||
public void WriteBySize (uint value, int size)
|
||||
{
|
||||
if (size == 4)
|
||||
WriteUInt32 (value);
|
||||
else
|
||||
WriteUInt16 ((ushort) value);
|
||||
}
|
||||
|
||||
public void WriteBySize (uint value, bool large)
|
||||
{
|
||||
if (large)
|
||||
WriteUInt32 (value);
|
||||
else
|
||||
WriteUInt16 ((ushort) value);
|
||||
}
|
||||
|
||||
public void WriteString (uint @string)
|
||||
{
|
||||
WriteBySize (string_offsets [@string], large_string);
|
||||
}
|
||||
|
||||
public void WriteBlob (uint blob)
|
||||
{
|
||||
WriteBySize (blob, large_blob);
|
||||
}
|
||||
|
||||
public void WriteGuid (uint guid)
|
||||
{
|
||||
WriteBySize (guid, large_guid);
|
||||
}
|
||||
|
||||
public void WriteRID (uint rid, Table table)
|
||||
{
|
||||
WriteBySize (rid, table_infos [(int) table].IsLarge);
|
||||
}
|
||||
|
||||
int GetCodedIndexSize (CodedIndex coded_index)
|
||||
{
|
||||
var index = (int) coded_index;
|
||||
var size = coded_index_sizes [index];
|
||||
if (size != 0)
|
||||
return size;
|
||||
|
||||
return coded_index_sizes [index] = coded_index.GetSize (counter);
|
||||
}
|
||||
|
||||
public void WriteCodedRID (uint rid, CodedIndex coded_index)
|
||||
{
|
||||
WriteBySize (rid, GetCodedIndexSize (coded_index));
|
||||
}
|
||||
|
||||
public void WriteTableHeap ()
|
||||
{
|
||||
WriteUInt32 (0); // Reserved
|
||||
WriteByte (GetTableHeapVersion ()); // MajorVersion
|
||||
WriteByte (0); // MinorVersion
|
||||
WriteByte (GetHeapSizes ()); // HeapSizes
|
||||
WriteByte (10); // Reserved2
|
||||
WriteUInt64 (GetValid ()); // Valid
|
||||
WriteUInt64 (0xc416003301fa00); // Sorted
|
||||
|
||||
WriteRowCount ();
|
||||
WriteTables ();
|
||||
}
|
||||
|
||||
void WriteRowCount ()
|
||||
{
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
var table = tables [i];
|
||||
if (table == null || table.Length == 0)
|
||||
continue;
|
||||
|
||||
WriteUInt32 ((uint) table.Length);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTables ()
|
||||
{
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
var table = tables [i];
|
||||
if (table == null || table.Length == 0)
|
||||
continue;
|
||||
|
||||
table.Write (this);
|
||||
}
|
||||
}
|
||||
|
||||
ulong GetValid ()
|
||||
{
|
||||
ulong valid = 0;
|
||||
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
var table = tables [i];
|
||||
if (table == null || table.Length == 0)
|
||||
continue;
|
||||
|
||||
table.Sort ();
|
||||
valid |= (1UL << i);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void ComputeTableInformations ()
|
||||
{
|
||||
if (metadata.metadata_builder != null)
|
||||
ComputeTableInformations (metadata.metadata_builder.table_heap);
|
||||
|
||||
ComputeTableInformations (metadata.table_heap);
|
||||
}
|
||||
|
||||
void ComputeTableInformations (TableHeapBuffer table_heap)
|
||||
{
|
||||
var tables = table_heap.tables;
|
||||
for (int i = 0; i < tables.Length; i++) {
|
||||
var table = tables [i];
|
||||
if (table != null && table.Length > 0)
|
||||
table_infos [i].Length = (uint) table.Length;
|
||||
}
|
||||
}
|
||||
|
||||
byte GetHeapSizes ()
|
||||
{
|
||||
byte heap_sizes = 0;
|
||||
|
||||
if (metadata.string_heap.IsLarge) {
|
||||
large_string = true;
|
||||
heap_sizes |= 0x01;
|
||||
}
|
||||
|
||||
if (metadata.guid_heap.IsLarge) {
|
||||
large_guid = true;
|
||||
heap_sizes |= 0x02;
|
||||
}
|
||||
|
||||
if (metadata.blob_heap.IsLarge) {
|
||||
large_blob = true;
|
||||
heap_sizes |= 0x04;
|
||||
}
|
||||
|
||||
return heap_sizes;
|
||||
}
|
||||
|
||||
byte GetTableHeapVersion ()
|
||||
{
|
||||
switch (module.Runtime) {
|
||||
case TargetRuntime.Net_1_0:
|
||||
case TargetRuntime.Net_1_1:
|
||||
return 1;
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void FixupData (RVA data_rva)
|
||||
{
|
||||
var table = GetTable<FieldRVATable> (Table.FieldRVA);
|
||||
if (table.length == 0)
|
||||
return;
|
||||
|
||||
var field_idx_size = GetTable<FieldTable> (Table.Field).IsLarge ? 4 : 2;
|
||||
var previous = this.position;
|
||||
|
||||
base.position = table.position;
|
||||
for (int i = 0; i < table.length; i++) {
|
||||
var rva = ReadUInt32 ();
|
||||
base.position -= 4;
|
||||
WriteUInt32 (rva + data_rva);
|
||||
base.position += field_idx_size;
|
||||
}
|
||||
|
||||
base.position = previous;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ResourceBuffer : ByteBuffer {
|
||||
|
||||
public ResourceBuffer ()
|
||||
: base (0)
|
||||
{
|
||||
}
|
||||
|
||||
public uint AddResource (byte [] resource)
|
||||
{
|
||||
var offset = (uint) this.position;
|
||||
WriteInt32 (resource.Length);
|
||||
WriteBytes (resource);
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DataBuffer : ByteBuffer {
|
||||
|
||||
public DataBuffer ()
|
||||
: base (0)
|
||||
{
|
||||
}
|
||||
|
||||
public RVA AddData (byte [] data)
|
||||
{
|
||||
var rva = (RVA) position;
|
||||
WriteBytes (data);
|
||||
return rva;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class HeapBuffer : ByteBuffer {
|
||||
|
||||
public bool IsLarge {
|
||||
get { return base.length > 65535; }
|
||||
}
|
||||
|
||||
public abstract bool IsEmpty { get; }
|
||||
|
||||
protected HeapBuffer (int length)
|
||||
: base (length)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
sealed class GuidHeapBuffer : HeapBuffer {
|
||||
|
||||
readonly Dictionary<Guid, uint> guids = new Dictionary<Guid, uint> ();
|
||||
|
||||
public override bool IsEmpty {
|
||||
get { return length == 0; }
|
||||
}
|
||||
|
||||
public GuidHeapBuffer ()
|
||||
: base (16)
|
||||
{
|
||||
}
|
||||
|
||||
public uint GetGuidIndex (Guid guid)
|
||||
{
|
||||
uint index;
|
||||
if (guids.TryGetValue (guid, out index))
|
||||
return index;
|
||||
|
||||
index = (uint) guids.Count + 1;
|
||||
WriteGuid (guid);
|
||||
guids.Add (guid, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
void WriteGuid (Guid guid)
|
||||
{
|
||||
WriteBytes (guid.ToByteArray ());
|
||||
}
|
||||
}
|
||||
|
||||
class StringHeapBuffer : HeapBuffer {
|
||||
|
||||
protected Dictionary<string, uint> strings = new Dictionary<string, uint> (StringComparer.Ordinal);
|
||||
|
||||
public sealed override bool IsEmpty {
|
||||
get { return length <= 1; }
|
||||
}
|
||||
|
||||
public StringHeapBuffer ()
|
||||
: base (1)
|
||||
{
|
||||
WriteByte (0);
|
||||
}
|
||||
|
||||
public virtual uint GetStringIndex (string @string)
|
||||
{
|
||||
uint index;
|
||||
if (strings.TryGetValue (@string, out index))
|
||||
return index;
|
||||
|
||||
index = (uint) strings.Count + 1;
|
||||
strings.Add (@string, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
public uint [] WriteStrings ()
|
||||
{
|
||||
var sorted = SortStrings (strings);
|
||||
strings = null;
|
||||
|
||||
// Add 1 for empty string whose index and offset are both 0
|
||||
var string_offsets = new uint [sorted.Count + 1];
|
||||
string_offsets [0] = 0;
|
||||
|
||||
// Find strings that can be folded
|
||||
var previous = string.Empty;
|
||||
foreach (var entry in sorted) {
|
||||
var @string = entry.Key;
|
||||
var index = entry.Value;
|
||||
var position = base.position;
|
||||
|
||||
if (previous.EndsWith (@string, StringComparison.Ordinal) && !IsLowSurrogateChar (entry.Key [0])) {
|
||||
// Map over the tail of prev string. Watch for null-terminator of prev string.
|
||||
string_offsets [index] = (uint) (position - (Encoding.UTF8.GetByteCount (entry.Key) + 1));
|
||||
} else {
|
||||
string_offsets [index] = (uint) position;
|
||||
WriteString (@string);
|
||||
}
|
||||
|
||||
previous = entry.Key;
|
||||
}
|
||||
|
||||
return string_offsets;
|
||||
}
|
||||
|
||||
static List<KeyValuePair<string, uint>> SortStrings (Dictionary<string, uint> strings)
|
||||
{
|
||||
var sorted = new List<KeyValuePair<string, uint>> (strings);
|
||||
sorted.Sort (new SuffixSort ());
|
||||
return sorted;
|
||||
}
|
||||
|
||||
static bool IsLowSurrogateChar (int c)
|
||||
{
|
||||
return unchecked((uint)(c - 0xDC00)) <= 0xDFFF - 0xDC00;
|
||||
}
|
||||
|
||||
protected virtual void WriteString (string @string)
|
||||
{
|
||||
WriteBytes (Encoding.UTF8.GetBytes (@string));
|
||||
WriteByte (0);
|
||||
}
|
||||
|
||||
// Sorts strings such that a string is followed immediately by all strings
|
||||
// that are a suffix of it.
|
||||
private class SuffixSort : IComparer<KeyValuePair<string, uint>> {
|
||||
|
||||
public int Compare(KeyValuePair<string, uint> xPair, KeyValuePair<string, uint> yPair)
|
||||
{
|
||||
var x = xPair.Key;
|
||||
var y = yPair.Key;
|
||||
|
||||
for (int i = x.Length - 1, j = y.Length - 1; i >= 0 & j >= 0; i--, j--) {
|
||||
if (x [i] < y [j]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x [i] > y [j]) {
|
||||
return +1;
|
||||
}
|
||||
}
|
||||
|
||||
return y.Length.CompareTo (x.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class BlobHeapBuffer : HeapBuffer {
|
||||
|
||||
readonly Dictionary<ByteBuffer, uint> blobs = new Dictionary<ByteBuffer, uint> (new ByteBufferEqualityComparer ());
|
||||
|
||||
public override bool IsEmpty {
|
||||
get { return length <= 1; }
|
||||
}
|
||||
|
||||
public BlobHeapBuffer ()
|
||||
: base (1)
|
||||
{
|
||||
WriteByte (0);
|
||||
}
|
||||
|
||||
public uint GetBlobIndex (ByteBuffer blob)
|
||||
{
|
||||
uint index;
|
||||
if (blobs.TryGetValue (blob, out index))
|
||||
return index;
|
||||
|
||||
index = (uint) base.position;
|
||||
WriteBlob (blob);
|
||||
blobs.Add (blob, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
void WriteBlob (ByteBuffer blob)
|
||||
{
|
||||
WriteCompressedUInt32 ((uint) blob.length);
|
||||
WriteBytes (blob);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UserStringHeapBuffer : StringHeapBuffer {
|
||||
|
||||
public override uint GetStringIndex (string @string)
|
||||
{
|
||||
uint index;
|
||||
if (strings.TryGetValue (@string, out index))
|
||||
return index;
|
||||
|
||||
index = (uint) base.position;
|
||||
WriteString (@string);
|
||||
strings.Add (@string, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
protected override void WriteString (string @string)
|
||||
{
|
||||
WriteCompressedUInt32 ((uint) @string.Length * 2 + 1);
|
||||
|
||||
byte special = 0;
|
||||
|
||||
for (int i = 0; i < @string.Length; i++) {
|
||||
var @char = @string [i];
|
||||
WriteUInt16 (@char);
|
||||
|
||||
if (special == 1)
|
||||
continue;
|
||||
|
||||
if (@char < 0x20 || @char > 0x7e) {
|
||||
if (@char > 0x7e
|
||||
|| (@char >= 0x01 && @char <= 0x08)
|
||||
|| (@char >= 0x0e && @char <= 0x1f)
|
||||
|| @char == 0x27
|
||||
|| @char == 0x2d) {
|
||||
|
||||
special = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteByte (special);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PdbHeapBuffer : HeapBuffer {
|
||||
|
||||
public override bool IsEmpty {
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public PdbHeapBuffer ()
|
||||
: base (0)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
enum CodedIndex {
|
||||
TypeDefOrRef,
|
||||
HasConstant,
|
||||
HasCustomAttribute,
|
||||
HasFieldMarshal,
|
||||
HasDeclSecurity,
|
||||
MemberRefParent,
|
||||
HasSemantics,
|
||||
MethodDefOrRef,
|
||||
MemberForwarded,
|
||||
Implementation,
|
||||
CustomAttributeType,
|
||||
ResolutionScope,
|
||||
TypeOrMethodDef,
|
||||
HasCustomDebugInformation,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
enum ElementType : byte {
|
||||
None = 0x00,
|
||||
Void = 0x01,
|
||||
Boolean = 0x02,
|
||||
Char = 0x03,
|
||||
I1 = 0x04,
|
||||
U1 = 0x05,
|
||||
I2 = 0x06,
|
||||
U2 = 0x07,
|
||||
I4 = 0x08,
|
||||
U4 = 0x09,
|
||||
I8 = 0x0a,
|
||||
U8 = 0x0b,
|
||||
R4 = 0x0c,
|
||||
R8 = 0x0d,
|
||||
String = 0x0e,
|
||||
Ptr = 0x0f, // Followed by <type> token
|
||||
ByRef = 0x10, // Followed by <type> token
|
||||
ValueType = 0x11, // Followed by <type> token
|
||||
Class = 0x12, // Followed by <type> token
|
||||
Var = 0x13, // Followed by generic parameter number
|
||||
Array = 0x14, // <type> <rank> <boundsCount> <bound1> <loCount> <lo1>
|
||||
GenericInst = 0x15, // <type> <type-arg-count> <type-1> ... <type-n> */
|
||||
TypedByRef = 0x16,
|
||||
I = 0x18, // System.IntPtr
|
||||
U = 0x19, // System.UIntPtr
|
||||
FnPtr = 0x1b, // Followed by full method signature
|
||||
Object = 0x1c, // System.Object
|
||||
SzArray = 0x1d, // Single-dim array with 0 lower bound
|
||||
MVar = 0x1e, // Followed by generic parameter number
|
||||
CModReqD = 0x1f, // Required modifier : followed by a TypeDef or TypeRef token
|
||||
CModOpt = 0x20, // Optional modifier : followed by a TypeDef or TypeRef token
|
||||
Internal = 0x21, // Implemented within the CLI
|
||||
Modifier = 0x40, // Or'd with following element types
|
||||
Sentinel = 0x41, // Sentinel for varargs method signature
|
||||
Pinned = 0x45, // Denotes a local variable that points at a pinned object
|
||||
|
||||
// special undocumented constants
|
||||
Type = 0x50,
|
||||
Boxed = 0x51,
|
||||
Enum = 0x55
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
sealed class GuidHeap : Heap {
|
||||
|
||||
public GuidHeap (byte [] data)
|
||||
: base (data)
|
||||
{
|
||||
}
|
||||
|
||||
public Guid Read (uint index)
|
||||
{
|
||||
const int guid_size = 16;
|
||||
|
||||
if (index == 0 || ((index - 1) + guid_size) > data.Length)
|
||||
return new Guid ();
|
||||
|
||||
var buffer = new byte [guid_size];
|
||||
|
||||
Buffer.BlockCopy (this.data, (int) ((index - 1) * guid_size), buffer, 0, guid_size);
|
||||
|
||||
return new Guid (buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
namespace Mono.Cecil.Metadata {
|
||||
|
||||
abstract class Heap {
|
||||
|
||||
public int IndexSize;
|
||||
|
||||
readonly internal byte [] data;
|
||||
|
||||
protected Heap (byte [] data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Cecil {
|
||||
|
||||
public struct MetadataToken : IEquatable<MetadataToken> {
|
||||
|
||||
readonly uint token;
|
||||
|
||||
public uint RID {
|
||||
get { return token & 0x00ffffff; }
|
||||
}
|
||||
|
||||
public TokenType TokenType {
|
||||
get { return (TokenType) (token & 0xff000000); }
|
||||
}
|
||||
|
||||
public static readonly MetadataToken Zero = new MetadataToken ((uint) 0);
|
||||
|
||||
public MetadataToken (uint token)
|
||||
{
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public MetadataToken (TokenType type)
|
||||
: this (type, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public MetadataToken (TokenType type, uint rid)
|
||||
{
|
||||
token = (uint) type | rid;
|
||||
}
|
||||
|
||||
public MetadataToken (TokenType type, int rid)
|
||||
{
|
||||
token = (uint) type | (uint) rid;
|
||||
}
|
||||
|
||||
public int ToInt32 ()
|
||||
{
|
||||
return (int) token;
|
||||
}
|
||||
|
||||
public uint ToUInt32 ()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return (int) token;
|
||||
}
|
||||
|
||||
public bool Equals (MetadataToken other)
|
||||
{
|
||||
return other.token == token;
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj is MetadataToken) {
|
||||
var other = (MetadataToken) obj;
|
||||
return other.token == token;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator == (MetadataToken one, MetadataToken other)
|
||||
{
|
||||
return one.token == other.token;
|
||||
}
|
||||
|
||||
public static bool operator != (MetadataToken one, MetadataToken other)
|
||||
{
|
||||
return one.token != other.token;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return string.Format ("[{0}:0x{1}]", TokenType, RID.ToString ("x4"));
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue