static int getMapId(Type idMapType, MethodBase method) { IDTagAttribute id = Attribute.GetCustomAttribute(method, typeof(IDTagAttribute), false) as IDTagAttribute; int overrideId = id == null ? 0 : id.ID; var fieldName = string.Format("{0}-{1}{2}", method.DeclaringType.FullName.Replace('.', '-') .Replace('+', '-'), method.Name, overrideId); var field = idMapType.GetField(fieldName); if (field == null) { throw new Exception(string.Format("cat not find id field: {0}, for {1}", fieldName, method)); } return((int)field.GetValue(null)); }
static FieldInfo getRedirectField(MethodBase method) { var redirectTypeName = "IFix.RedirectTo." + method.DeclaringType.AssemblyQualifiedName; var redirectType = Type.GetType(redirectTypeName); if (redirectType == null) { throw new Exception("cat not find redirect type: " + redirectTypeName); } IDTagAttribute id = Attribute.GetCustomAttribute(method, typeof(IDTagAttribute), false) as IDTagAttribute; var redirectFieldName = string.Format("_rf_{0}{1}", method.Name, id == null ? 0 : id.ID); var redirectField = redirectType.GetField(redirectFieldName, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); if (redirectField == null) { throw new Exception(string.Format("cat not find redirect field: {0}, for {1}", redirectFieldName, redirectType)); } return(redirectField); }
static int getMapId(List <Type> idMapArray, MethodBase method) { IDTagAttribute id = Attribute.GetCustomAttribute(method, typeof(IDTagAttribute), false) as IDTagAttribute; int overrideId = id == null ? 0 : id.ID; var fieldName = string.Format("{0}-{1}{2}", method.DeclaringType.FullName.Replace('.', '-') .Replace('+', '-'), method.Name, overrideId); FieldInfo field = null; for (int i = 0; i < idMapArray.Count; i++) { field = idMapArray[i].GetField(fieldName); if (field != null) { break; } } if (field == null) { throw new Exception(string.Format("cat not find id field: {0}, for {1}", fieldName, method)); } return((int)field.GetValue(null)); }
// #lizard forgives unsafe static public VirtualMachine Load(Stream stream, bool checkNew = true) { List <IntPtr> nativePointers = new List <IntPtr>(); IntPtr nativePointer; Instruction **unmanagedCodes = null; Type[] externTypes; MethodBase[] externMethods; List <ExceptionHandler[]> exceptionHandlers = new List <ExceptionHandler[]>(); string[] internStrings; FieldInfo[] fieldInfos; Type[] staticFieldTypes; int[] cctors; AnonymousStoreyInfo[] anonymousStoreyInfos; using (BinaryReader reader = new BinaryReader(stream)) { var instructionMagic = reader.ReadUInt64(); if (instructionMagic != Instruction.INSTRUCTION_FORMAT_MAGIC) { throw new Exception("instruction magic not match, expect " + Instruction.INSTRUCTION_FORMAT_MAGIC + ", but got " + instructionMagic); } var interfaceBridgeTypeName = reader.ReadString(); var interfaceBridgeType = Type.GetType(interfaceBridgeTypeName); if (interfaceBridgeType == null) { throw new Exception("assembly may be not injected yet, cat find " + interfaceBridgeTypeName); } //BindingFlags flag = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static // | BindingFlags.NonPublic |BindingFlags.Public; int externTypeCount = reader.ReadInt32(); externTypes = new Type[externTypeCount]; for (int i = 0; i < externTypeCount; i++) { var assemblyQualifiedName = reader.ReadString(); externTypes[i] = Type.GetType(assemblyQualifiedName); if (externTypes[i] == null) { throw new Exception("can not load type [" + assemblyQualifiedName + "]"); } } int methodCount = reader.ReadInt32(); nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(Instruction *) * methodCount); unmanagedCodes = (Instruction **)nativePointer.ToPointer(); nativePointers.Add(nativePointer); for (int j = 0; j < methodCount; j++) { //Console.WriteLine("==================method" + j + "=================="); int codeSize = reader.ReadInt32(); nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(Instruction) * codeSize); var unmanagedCode = (Instruction *)nativePointer.ToPointer(); for (int i = 0; i < codeSize; i++) { unmanagedCode[i].Code = (Code)reader.ReadInt32(); unmanagedCode[i].Operand = reader.ReadInt32(); //Console.WriteLine(i + " Code=" + unmanagedCode[i].Code + " Operand=" // + unmanagedCode[i].Operand); } unmanagedCodes[j] = unmanagedCode; nativePointers.Add(nativePointer); ExceptionHandler[] ehsOfMethod = new ExceptionHandler[reader.ReadInt32()]; for (int i = 0; i < ehsOfMethod.Length; i++) { ExceptionHandler ehOfMethod = new ExceptionHandler(); ehOfMethod.HandlerType = (ExceptionHandlerType)reader.ReadInt32(); ehOfMethod.CatchTypeId = reader.ReadInt32(); ehOfMethod.TryStart = reader.ReadInt32(); ehOfMethod.TryEnd = reader.ReadInt32(); ehOfMethod.HandlerStart = reader.ReadInt32(); ehOfMethod.HandlerEnd = reader.ReadInt32(); ehsOfMethod[i] = ehOfMethod; if (ehOfMethod.HandlerType == ExceptionHandlerType.Catch) { ehOfMethod.CatchType = ehOfMethod.CatchTypeId == -1 ? typeof(object) : externTypes[ehOfMethod.CatchTypeId]; } } exceptionHandlers.Add(ehsOfMethod); } int externMethodCount = reader.ReadInt32(); externMethods = new MethodBase[externMethodCount]; for (int i = 0; i < externMethodCount; i++) { externMethods[i] = readMethod(reader, externTypes); } int internStringsCount = reader.ReadInt32(); internStrings = new string[internStringsCount]; for (int i = 0; i < internStringsCount; i++) { internStrings[i] = reader.ReadString(); } fieldInfos = new FieldInfo[reader.ReadInt32()]; for (int i = 0; i < fieldInfos.Length; i++) { var type = externTypes[reader.ReadInt32()]; var fieldName = reader.ReadString(); fieldInfos[i] = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); if (fieldInfos[i] == null) { throw new Exception("can not load field [" + fieldName + "] of " + type); } } staticFieldTypes = new Type[reader.ReadInt32()]; cctors = new int[staticFieldTypes.Length]; for (int i = 0; i < staticFieldTypes.Length; i++) { staticFieldTypes[i] = externTypes[reader.ReadInt32()]; cctors[i] = reader.ReadInt32(); } Dictionary <MethodInfo, int> itfMethodToId = new Dictionary <MethodInfo, int>(); int maxId = 0; foreach (var itf in interfaceBridgeType.GetInterfaces()) { InterfaceMapping map = interfaceBridgeType.GetInterfaceMap(itf); for (int i = 0; i < map.InterfaceMethods.Length; i++) { IDTagAttribute idTag = Attribute.GetCustomAttribute(map.TargetMethods[i], typeof(IDTagAttribute), false) as IDTagAttribute; MethodInfo im = map.InterfaceMethods[i]; if (idTag == null) { throw new Exception(string.Format("can not find id for {0}", im)); } int id = idTag.ID; //VirtualMachine._Info(string.Format("{0} [{1}]", im, id)); maxId = id > maxId ? id : maxId; itfMethodToId.Add(im, id); } } anonymousStoreyInfos = new AnonymousStoreyInfo[reader.ReadInt32()]; for (int i = 0; i < anonymousStoreyInfos.Length; i++) { int fieldNum = reader.ReadInt32(); int[] fieldTypes = new int[fieldNum]; for (int fieldIdx = 0; fieldIdx < fieldNum; ++fieldIdx) { fieldTypes[fieldIdx] = reader.ReadInt32(); } int ctorId = reader.ReadInt32(); int ctorParamNum = reader.ReadInt32(); var slots = readSlotInfo(reader, itfMethodToId, externTypes, maxId); int virtualMethodNum = reader.ReadInt32(); int[] vTable = new int[virtualMethodNum]; for (int vm = 0; vm < virtualMethodNum; vm++) { vTable[vm] = reader.ReadInt32(); } anonymousStoreyInfos[i] = new AnonymousStoreyInfo() { CtorId = ctorId, FieldNum = fieldNum, FieldTypes = fieldTypes, CtorParamNum = ctorParamNum, Slots = slots, VTable = vTable }; } var virtualMachine = new VirtualMachine(unmanagedCodes, () => { for (int i = 0; i < nativePointers.Count; i++) { System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointers[i]); } }) { ExternTypes = externTypes, ExternMethods = externMethods, ExceptionHandlers = exceptionHandlers.ToArray(), InternStrings = internStrings, FieldInfos = fieldInfos, AnonymousStoreyInfos = anonymousStoreyInfos, StaticFieldTypes = staticFieldTypes, Cctors = cctors }; var wrappersManagerImplName = reader.ReadString(); WrappersManager wrapperManager = Activator.CreateInstance(Type.GetType(wrappersManagerImplName, true), virtualMachine) as WrappersManager; if (wrapperManager == null) { throw new Exception("can not create WrappersManager!"); } virtualMachine.WrappersManager = wrapperManager; var assemblyStr = reader.ReadString(); var idMapList = new List <Type>(); for (int i = 0; i < 100; i++) { var idMapType = Type.GetType("IFix.IDMAP" + i + assemblyStr, false); if (idMapType == null) { break; } idMapList.Add(idMapType); } lock (removers) { var assembly = wrapperManager.GetType().Assembly; Action remover; if (removers.TryGetValue(assembly, out remover)) { removers.Remove(assembly); remover(); } //int fixCount = reader.ReadInt32(); //FieldInfo[] toSet = new FieldInfo[fixCount]; //for (int i = 0; i < fixCount; i++) //{ // var fixMethod = readMethod(reader, externTypes); // var fixMethodIdx = reader.ReadInt32(); // var redirectField = getRedirectField(fixMethod); // toSet[i] = redirectField; // var wrapper = wrapperManager.CreateWrapper(fixMethodIdx); // if (wrapper == null) // { // throw new Exception("create wrapper fail"); // } // redirectField.SetValue(null, wrapper); //} //removers[assembly] = () => //{ // for (int i = 0; i < fixCount; i++) // { // toSet[i].SetValue(null, null); // } //}; int fixCount = reader.ReadInt32(); int[] methodIdArray = new int[fixCount]; int[] posArray = new int[fixCount]; int maxPos = -1; for (int i = 0; i < fixCount; i++) { var fixMethod = readMethod(reader, externTypes); var fixMethodId = reader.ReadInt32(); var pos = getMapId(idMapList, fixMethod); methodIdArray[i] = fixMethodId; posArray[i] = pos; if (pos > maxPos) { maxPos = pos; } } Array arr = wrapperManager.InitWrapperArray(maxPos + 1) as Array; for (int i = 0; i < fixCount; i++) { var wrapper = wrapperManager.CreateWrapper(methodIdArray[i]); if (wrapper == null) { throw new Exception("create wrapper fail"); } arr.SetValue(wrapper, posArray[i]); } removers[assembly] = () => { wrapperManager.InitWrapperArray(0); }; } if (checkNew) { int newClassCount = reader.ReadInt32(); for (int i = 0; i < newClassCount; i++) { var newClassFullName = reader.ReadString(); var newClassName = Type.GetType(newClassFullName); if (newClassName != null) { throw new Exception(newClassName + " class is expected to be a new class , but it already exists "); } } } return(virtualMachine); } }