//---------------------------------------------------------------------------------------------------------------------- // Predict that the last 0 or 1 pushed onto the stack being the value to be returned. Returns false on error. Naughty me! //---------------------------------------------------------------------------------------------------------------------- public bool GetBooleanValue(string methodName) { MethodInfo method = m_MasterType.GetMethod(methodName); if (method != null) { byte[] methodData = method.GetMethodBody().GetILAsByteArray(); BinaryReader codeReader = new BinaryReader( new MemoryStream(methodData) ); bool lastCode = false; while (codeReader.PeekChar() >= 0) { OpCode op = OPCodeCache.Hit(codeReader.ReadByte()); if (op == OpCodes.Ldc_I4_1) { lastCode = true; } else if (op == OpCodes.Ldc_I4_0) { lastCode = false; } } return(lastCode); } return(false); }
// heart and soul, yay! private void AnalyseILCode(byte[] code) { BinaryReader codeReader = new BinaryReader( new MemoryStream(code) ); while (codeReader.PeekChar() >= 0) { OpCode op = OPCodeCache.Hit(codeReader.ReadByte()); if (op == OpCodes.Ldc_I4) { m_Stack.Push(codeReader.ReadInt32()); } else if (op == OpCodes.Ldc_R8) { m_Stack.Push(codeReader.ReadDouble()); } else if (op == OpCodes.Ldc_R4) { m_Stack.Push(codeReader.ReadSingle()); } else if (op.Value > 0x15 && op.Value < 0x1F) { m_Stack.Push(op.Value - 0x16); } else if (op == OpCodes.Ldc_I4_M1) { m_Stack.Push(-1); } else if (op == OpCodes.Ldc_I4_S) { m_Stack.Push((int)codeReader.ReadByte()); } else if (op == OpCodes.Ldstr) { int stringDescriptor = codeReader.ReadInt32(); if (MatchMetadata(stringDescriptor, MetadataToken.String)) // sanity check, am I really a string? { m_Stack.Push(m_Module.ResolveString(stringDescriptor)); } else { m_Stack.Push("(error - string value couldn't be resolved.)"); } } else if (op == OpCodes.Call || op == OpCodes.Callvirt) { int methodDescriptor = codeReader.ReadInt32(); if (MatchMetadata(methodDescriptor, MetadataToken.Method)) // sanity check, am I really a method? { MethodBase mb = m_Module.ResolveMethod(methodDescriptor); if ((mb.DeclaringType.IsSubclassOf(typeof(Mobile)) || mb.DeclaringType == typeof(Mobile)) && !mb.IsConstructor) { Dispatch(mb.Name, mb.GetParameters().Length); } else { Dispatch(mb.Name, mb.DeclaringType.Name, mb.GetParameters().Length); } } } else { // all opcodes that push something onto the stack have been taken care of. // now we have to check whether the given opcode has an operand or not. // if so, we'll skip appropriate amount of bytes. OperandType operandType = op.OperandType; switch (operandType) { case OperandType.InlineNone: { } break; case OperandType.InlineR: case OperandType.InlineI8: { codeReader.ReadInt64(); } break; case OperandType.InlineSwitch: { int switchBranches = codeReader.ReadInt32(); while (switchBranches-- > 0) { codeReader.ReadInt32(); } } break; case OperandType.ShortInlineR: case OperandType.InlineType: case OperandType.InlineTok: case OperandType.InlineString: case OperandType.InlineSig: case OperandType.InlineMethod: case OperandType.InlineI: case OperandType.InlineField: case OperandType.InlineBrTarget: { codeReader.ReadInt32(); } break; case OperandType.InlineVar: { codeReader.ReadInt16(); } break; case OperandType.ShortInlineVar: case OperandType.ShortInlineI: case OperandType.ShortInlineBrTarget: { codeReader.ReadByte(); } break; } } } }