public static ExceptionHandler FromReader(CilMethodBody cilMethodBody, IBinaryStreamReader reader, bool fatFormat) { var offset = reader.Position; var handerType = fatFormat ? reader.ReadUInt32() : reader.ReadUInt16(); var tryOffset = fatFormat ? reader.ReadInt32() : reader.ReadUInt16(); var tryLength = fatFormat ? reader.ReadInt32() : reader.ReadByte(); var handlerOffset = fatFormat ? reader.ReadInt32() : reader.ReadUInt16(); var handlerLength = fatFormat ? reader.ReadInt32() : reader.ReadByte(); var classTokenOrFilterOffset = reader.ReadUInt32(); var handler = new ExceptionHandler((ExceptionHandlerType)handerType) { IsFat = fatFormat, TryStart = cilMethodBody.GetInstructionByOffset(tryOffset), TryEnd = cilMethodBody.GetInstructionByOffset(tryOffset + tryLength), HandlerStart = cilMethodBody.GetInstructionByOffset(handlerOffset), HandlerEnd = cilMethodBody.GetInstructionByOffset(handlerOffset + handlerLength), }; switch (handler.HandlerType) { case ExceptionHandlerType.Exception: handler.CatchType = (ITypeDefOrRef)((IOperandResolver)cilMethodBody).ResolveMember(new MetadataToken(classTokenOrFilterOffset)); break; case ExceptionHandlerType.Filter: handler.FilterStart = cilMethodBody.GetInstructionByOffset((int)classTokenOrFilterOffset); break; } return(handler); }
public StackInbalanceException(CilMethodBody body, int offset) : base(string.Format("Stack inbalance was detected at offset {0:X4} in method body of {1}", offset, body.Method)) { Body = body; Offset = offset; }
/// <summary> /// Interprets a raw method body to a CILMethodBody, disassembling all instructions, obtaining the local variables /// and reading the extra sections for exception handlers. /// </summary> /// <param name="method">The parent method the method body is associated to.</param> /// <param name="rawMethodBody">The raw method body to convert.</param> /// <returns>The converted method body.</returns> public static CilMethodBody FromRawMethodBody(MethodDefinition method, CilRawMethodBody rawMethodBody) { var body = new CilMethodBody(method); var fatBody = rawMethodBody as CilRawFatMethodBody; if (fatBody != null) { // Read fat method body header fields. body.MaxStack = fatBody.MaxStack; body.InitLocals = fatBody.InitLocals; if (method.Image.TryResolveMember(new MetadataToken(fatBody.LocalVarSigToken), out var signature)) { body.Signature = signature as StandAloneSignature; } } else { // Set values for tiny method bodies. body.MaxStack = 8; body.InitLocals = false; } // Read code. var codeReader = new MemoryStreamReader(rawMethodBody.Code); var disassembler = new CilDisassembler(codeReader, body); foreach (var instruction in disassembler.Disassemble()) { body.Instructions.Add(instruction); } if (fatBody != null) { // Read exception handlers. foreach (var section in fatBody.ExtraSections) { var sectionReader = new MemoryStreamReader(section.Data); while (sectionReader.CanRead(section.IsFat ? ExceptionHandler.FatExceptionHandlerSize : ExceptionHandler.SmallExceptionHandlerSize)) { body.ExceptionHandlers.Add(ExceptionHandler.FromReader(body, sectionReader, section.IsFat)); } } } return(body); }
/// <summary> /// Determines the amount of values pushed onto the stack by this instruction. /// </summary> /// <param name="parent">The parent method body the instruction is residing in.</param> /// <returns>A non-negative number representing the amount of values pushed onto the stack.</returns> public int GetStackPushCount(CilMethodBody parent) { MethodSignature signature = null; var member = Operand as ICallableMemberReference; var standalone = Operand as StandAloneSignature; if (member != null) { signature = member.Signature as MethodSignature; } else if (standalone != null) { signature = standalone.Signature as MethodSignature; } switch (OpCode.StackBehaviourPush) { case CilStackBehaviour.Push1: case CilStackBehaviour.Pushi: case CilStackBehaviour.Pushi8: case CilStackBehaviour.Pushr4: case CilStackBehaviour.Pushr8: case CilStackBehaviour.Pushref: return(1); case CilStackBehaviour.Push1_push1: return(2); case CilStackBehaviour.Varpush: if (signature != null && (!signature.ReturnType.IsTypeOf("System", "Void") || OpCode.Code == CilCode.Newobj)) { return(1); } break; } return(0); }
public static CilMethodBody FromRawMethodBody(MethodDefinition method, CilRawMethodBody rawMethodBody) { var body = new CilMethodBody(method); var fatBody = rawMethodBody as CilRawFatMethodBody; if (fatBody != null) { body.MaxStack = fatBody.MaxStack; body.InitLocals = fatBody.InitLocals; IMetadataMember signature; if (method.Image.TryResolveMember(new MetadataToken(fatBody.LocalVarSigToken), out signature)) { body.Signature = signature as StandAloneSignature; } } var codeReader = new MemoryStreamReader(rawMethodBody.Code); var disassembler = new CilDisassembler(codeReader, body); foreach (var instruction in disassembler.Disassemble()) { body.Instructions.Add(instruction); } if (fatBody != null) { foreach (var section in fatBody.ExtraSections) { var sectionReader = new MemoryStreamReader(section.Data); body.ExceptionHandlers.Add(ExceptionHandler.FromReader(body, sectionReader, section.IsFat)); } } return(body); }
public DefaultOperandBuilder(CilMethodBody methodBody, MetadataBuffer buffer) { _methodBody = methodBody; _buffer = buffer; }
public int GetStackDelta(CilMethodBody parent) { int delta = 0; MethodSignature signature = null; var member = Operand as IMethodDefOrRef; var standalone = Operand as StandAloneSignature; if (member != null) { signature = (MethodSignature)member.Signature; } else if (standalone != null) { signature = (MethodSignature)standalone.Signature; } switch (OpCode.StackBehaviourPop) { case CilStackBehaviour.Pop1: case CilStackBehaviour.Popi: case CilStackBehaviour.Popref: delta = -1; break; case CilStackBehaviour.Pop1_pop1: case CilStackBehaviour.Popi_pop1: case CilStackBehaviour.Popi_popi: case CilStackBehaviour.Popi_popi8: case CilStackBehaviour.Popi_popr4: case CilStackBehaviour.Popi_popr8: case CilStackBehaviour.Popref_pop1: case CilStackBehaviour.Popref_popi: delta = -2; break; case CilStackBehaviour.Popi_popi_popi: case CilStackBehaviour.Popref_popi_popi: case CilStackBehaviour.Popref_popi_popi8: case CilStackBehaviour.Popref_popi_popr4: case CilStackBehaviour.Popref_popi_popr8: case CilStackBehaviour.Popref_popi_popref: delta = -3; break; case CilStackBehaviour.Varpop: if (signature == null) { if (OpCode.Code == CilCode.Ret) { delta = parent.Method.Signature.ReturnType.IsTypeOf("System", "Void") ? 0 : -1; } else { throw new ArgumentException("Invalid or unsupported operand."); } } else { delta = -signature.Parameters.Count; if (signature.HasThis) { delta--; } } break; } switch (OpCode.StackBehaviourPush) { case CilStackBehaviour.Push1: case CilStackBehaviour.Pushi: case CilStackBehaviour.Pushi8: case CilStackBehaviour.Pushr4: case CilStackBehaviour.Pushr8: case CilStackBehaviour.Pushref: delta++; break; case CilStackBehaviour.Push1_push1: delta += 2; break; case CilStackBehaviour.Varpush: if (signature == null) { throw new ArgumentException("Invalid or unsupported operand."); } if (!signature.ReturnType.IsTypeOf("System", "Void")) { delta++; } break; case CilStackBehaviour.Popref_popi_pop1: delta += 3; break; } return(delta); }
public CilInstructionFormatter(CilMethodBody methodBody) { _methodBody = methodBody ?? throw new ArgumentNullException(nameof(methodBody)); }
public CilInstructionCollection(CilMethodBody body) { _body = body ?? throw new ArgumentNullException(nameof(body)); }
/// <summary> /// Determines the stack delta of the instruction. That is, the amount of values pushed onto the stack /// subtracted from the amount of values popped from the stack. /// </summary> /// <param name="parent">The parent method body the instruction is residing in.</param> /// <returns>A number representing the stack delta.</returns> public int GetStackDelta(CilMethodBody parent) { return(GetStackPushCount(parent) - GetStackPopCount(parent)); }
/// <summary> /// Determines the amount of values popped from the stack by this instruction. /// </summary> /// <param name="parent">The parent method body the instruction is residing in.</param> /// <returns>A non-negative number representing the amount of values popped from the stack.</returns> public int GetStackPopCount(CilMethodBody parent) { MethodSignature signature = null; var member = Operand as ICallableMemberReference; var standalone = Operand as StandAloneSignature; if (member != null) { signature = member.Signature as MethodSignature; } else if (standalone != null) { signature = standalone.Signature as MethodSignature; } switch (OpCode.StackBehaviourPop) { case CilStackBehaviour.Pop1: case CilStackBehaviour.Popi: case CilStackBehaviour.Popref: return(1); case CilStackBehaviour.Pop1_pop1: case CilStackBehaviour.Popi_pop1: case CilStackBehaviour.Popi_popi: case CilStackBehaviour.Popi_popi8: case CilStackBehaviour.Popi_popr4: case CilStackBehaviour.Popi_popr8: case CilStackBehaviour.Popref_pop1: case CilStackBehaviour.Popref_popi: return(2); case CilStackBehaviour.Popi_popi_popi: case CilStackBehaviour.Popref_popi_pop1: case CilStackBehaviour.Popref_popi_popi: case CilStackBehaviour.Popref_popi_popi8: case CilStackBehaviour.Popref_popi_popr4: case CilStackBehaviour.Popref_popi_popr8: case CilStackBehaviour.Popref_popi_popref: return(3); case CilStackBehaviour.Varpop: if (signature == null) { if (OpCode.Code == CilCode.Ret) { return(parent.Method.Signature.ReturnType.IsTypeOf("System", "Void") ? 0 : 1); } } else { int count = signature.Parameters.Count; if (signature.HasThis && OpCode.Code != CilCode.Newobj) { count++; } return(count); } break; } return(0); }