SMAPI Android Transportation

This commit is contained in:
yangzhi 2019-04-10 01:27:45 +08:00
parent 44ddc4ca42
commit 589d48a969
656 changed files with 105236 additions and 16795 deletions

1
SMAPI

@ -1 +0,0 @@
Subproject commit 9e521091fe4b13a9091bcb30c9f73ef210ace2dd

325
src/Harmony/Attributes.cs Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)")]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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));
}
}
}
*/
}

View File

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

194
src/Harmony/Patch.cs Normal file
View File

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

View File

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

View File

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

15
src/Harmony/Priority.cs Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

831
src/Mod.csproj Normal file
View File

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

25
src/Mod.sln Normal file
View File

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

66
src/ModEntry.cs Normal file
View File

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

141
src/Mono/Cecil/ArrayType.cs Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{
}
}
}

106
src/Mono/Cecil/CallSite.cs Normal file
View File

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

234
src/Mono/Cecil/Cil/Code.cs Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

5
src/Mono/Cecil/Consts.cs Normal file
View File

@ -0,0 +1,5 @@
static class Consts
{
public const string AssemblyName = "Mono.Cecil";
public const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf";
}

View File

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

View File

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

View File

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

View 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 EventAttributes : ushort {
None = 0x0000,
SpecialName = 0x0200, // Event is special
RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event
}
}

View File

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

View File

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

View File

@ -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,
};
}
}
}

View File

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

View File

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

View File

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

View File

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

View 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;
}
}
}

View File

@ -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)
{
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 (">");
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 (")");
}
}
}

829
src/Mono/Cecil/Import.cs Normal file
View File

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

View File

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

View 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
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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