private bool IsTerminatingInstruction(CILInstruction cilInstr) { // Return or throw instructions are terminating instructions if (cilInstr is Instr) { if (((Instr)cilInstr).GetOp() == Op.ret) return true; if (((Instr)cilInstr).GetOp() == Op.throwOp) return true; if (((Instr)cilInstr).GetOp() == Op.rethrow) return true; } // jmp is a terminating instruction if (cilInstr is MethInstr) { if (((MethInstr)cilInstr).GetMethodOp() == MethodOp.jmp) return true; } return false; }
/*------------------------- private methods ----------------------------*/ private void AddToBuffer(CILInstruction inst) { if (tide >= buffer.Length) { CILInstruction[] tmp = buffer; buffer = new CILInstruction[tmp.Length * 2]; for (int i=0; i < tide; i++) { buffer[i] = tmp[i]; } } //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size); //inst.offset = offset; //offset += inst.size; inst.index = (uint)tide; buffer[tide++] = inst; }
private void InsertInstructions(int ix, CILInstruction[] newInsts, int numNew) { CILInstruction[] newBuff = buffer, oldBuff = buffer; int newSize = tide + numNew - numReplace; if (buffer.Length < newSize) { newBuff = new CILInstruction[newSize]; for (int i=0; i < ix; i++) { newBuff[i] = oldBuff[i]; } } // shuffle up int offset = numNew-numReplace; int end = ix + numReplace; for (int i=tide-1; i >= end; i--) { newBuff[i+offset] = oldBuff[i]; } // insert new instructions for (int i=0; i < numNew; i++) { newBuff[ix+i] = newInsts[i]; } buffer = newBuff; tide += numNew - numReplace; UpdateIndexesFrom(ix); }
internal void SetAndResolveInstructions(CILInstruction[] insts) { offset = 0; ArrayList labels = new ArrayList(); for (int i=0; i < insts.Length; i++) { insts[i].offset = offset; offset += insts[i].size; if (insts[i] is BranchInstr) { ((BranchInstr)insts[i]).MakeTargetLabel(labels); } else if (insts[i] is SwitchInstr) { ((SwitchInstr)insts[i]).MakeTargetLabels(labels); } } if (exceptions != null) { for (int i=0; i < exceptions.Count; i++) { exceptions[i] = ((EHClause)exceptions[i]).MakeTryBlock(labels); } } if (labels.Count == 0) { buffer = insts; tide = buffer.Length; return; } buffer = new CILInstruction[insts.Length + labels.Count]; int currentPos = 0; tide = 0; for (int i=0; i < labels.Count; i++) { CILLabel lab = (CILLabel)labels[i]; while ((currentPos < insts.Length) && (insts[currentPos].offset < lab.offset)) buffer[tide++] = insts[currentPos++]; buffer[tide++] = lab; } while (currentPos < insts.Length) { buffer[tide++] = insts[currentPos++]; } }
/// <summary> /// Set the instruction to be the new array of instructions, this will replace /// any existing instructions. This method cannot be called when in "insert" mode. /// </summary> /// <param name="insts">The new instructions</param> public void SetInstructions(CILInstruction[] insts) { if (inserting) throw new Exception("Cannot replace instructions during insert."); buffer = insts; tide = buffer.Length; for (int i=0; i < tide; i++) { if (insts[i] == null) tide = i; insts[i].index = (uint)i; } }
/* private long GetOffset(int rva) { for (int i=0; i < inputSections.Length; i++) { long offs = inputSections[i].GetOffset(rva); if (offs > 0) return offs; } return 0; } public bool ReadPadding(int boundary) { while ((Position % boundary) != 0) { if (buffer[index++] != 0) { return false; } } return true; } public String ReadName() { int len = NAMELEN; char [] nameStr = new char[NAMELEN]; char ch = (char)ReadByte(); int i=0; for (; (i < NAMELEN) && (ch != '\0'); i++) { nameStr[i] = ch; ch = (char)ReadByte(); } return new String(nameStr,0,i); } internal String ReadString() { char [] str = new char[STRLEN]; int i=0; char ch = (char)ReadByte(); for (; ch != '\0'; i++) { str[i] = ch; ch = (char)ReadByte(); } return new String(str,0,i); } public long GetPos() { return BaseStream.Position; } public void SetPos(int ix) { BaseStream.Position = ix; } */ /* public void SetToRVA(int rva) { index = PESection.GetOffset(rva); // Console.WriteLine("Setting buffer to rva " + PEConsts.Hex(rva) + " = index " + PEConsts.Hex(index)); // Console.WriteLine("Setting buffer to rva " + rva + " = index " + index); } public byte[] GetBuffer() { return buffer; } */ private CILInstruction[] DoByteCodes(uint len, MethodDef thisMeth) { uint pos = 0; ArrayList instrList = new ArrayList(); //int instrIx = 0; while (pos < len) { uint offset = pos; uint opCode = ReadByte(); pos++; IType iType = IType.op; if (opCode == 0xFE) { uint ix = ReadByte(); pos++; opCode = (opCode << 8) + ix; iType = FileImage.longInstrMap[ix]; } else iType = FileImage.instrMap[opCode]; if (Diag.DiagOn) Console.WriteLine("Got instruction type " + iType); CILInstruction nextInstr = null; if (iType == IType.specialOp) { pos += 4; if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode)); switch (opCode) { case ((int)SpecialOp.ldc_i8) : nextInstr = new LongInstr((SpecialOp)opCode,ReadInt64()); pos += 4; break; case ((int)SpecialOp.ldc_r4) : nextInstr = new FloatInstr((SpecialOp)opCode,ReadSingle()); break; case ((int)SpecialOp.ldc_r8) : nextInstr = new DoubleInstr((SpecialOp)opCode,ReadDouble()); pos += 4; break; case ((int)SpecialOp.calli) : nextInstr = new SigInstr((SpecialOp)opCode,(CalliSig)GetTokenElement(ReadUInt32())); break; case ((int)SpecialOp.Switch) : // switch uint count = ReadUInt32(); int[] offsets = new int[count]; for (uint i=0; i < count; i++) offsets[i] = ReadInt32(); pos += (4 * count); nextInstr = new SwitchInstr(offsets); break; case ((int)SpecialOp.ldstr) : // ldstr uint strIx = ReadUInt32(); strIx = strIx & FileImage.ElementMask; nextInstr = new StringInstr((SpecialOp)opCode,userstring.GetUserString(strIx)); break; case ((int)MethodOp.ldtoken) : MetaDataElement elem = GetTokenElement(ReadUInt32()); if (elem is Method) nextInstr = new MethInstr((MethodOp)opCode,(Method)elem); else if (elem is Field) nextInstr = new FieldInstr((FieldOp)opCode,(Field)elem); else nextInstr =new TypeInstr((TypeOp)opCode,(Type)elem); break; } } else if (iType == IType.branchOp) { if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode)); if ((opCode < 0x38) || (opCode == 0xDE)) { // br or leave.s nextInstr = new BranchInstr(opCode,ReadSByte()); pos++; } else { nextInstr = new BranchInstr(opCode,ReadInt32()); pos += 4; } } else { if (Diag.DiagOn) Console.Write(Hex.Byte((int)opCode)); switch (iType) { case (IType.op) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (Op)opCode); nextInstr = new Instr((Op)opCode); break; case (IType.methOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (MethodOp)opCode); nextInstr = new MethInstr((MethodOp)opCode,(Method)GetTokenElement(ReadUInt32())); pos += 4; break; case (IType.typeOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (TypeOp)opCode); uint ttok = ReadUInt32(); Type typeToken = (Type)GetTokenElement(ttok); if (typeToken is GenericParTypeSpec) typeToken = ((GenericParTypeSpec)typeToken).GetGenericParam(thisMeth); nextInstr = new TypeInstr((TypeOp)opCode,typeToken); pos += 4; break; case (IType.fieldOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (FieldOp)opCode); nextInstr = new FieldInstr((FieldOp)opCode,(Field)GetTokenElement(ReadUInt32())); pos += 4; break; case (IType.int8Op) : nextInstr = new IntInstr((IntOp)opCode,ReadSByte()); pos++; break; case (IType.uint8Op) : nextInstr = new UIntInstr((IntOp)opCode,ReadByte()); pos++; break; case (IType.uint16Op) : nextInstr =new UIntInstr((IntOp)opCode,ReadUInt16()); pos++; break; case (IType.int32Op) : nextInstr =new IntInstr((IntOp)opCode,ReadInt32()); pos += 4; break; } } if (nextInstr != null) nextInstr.Resolve(); instrList.Add(nextInstr); } CILInstruction[] instrs = new CILInstruction[instrList.Count]; for (int i=0; i < instrs.Length; i++) { instrs[i] = (CILInstruction)instrList[i]; } return instrs; }
public void Add(CILInstruction inst, uint offset) { while (_current < _buffer.Length && _buffer[_current].offset < offset) _debugBuffer.Add(_buffer[_current++]); if (_debugBuffer.Count > 0 && offset >= ((CILInstruction) _debugBuffer[_debugBuffer.Count - 1]).offset) { inst.offset = offset; _debugBuffer.Add(inst); } else { int i; for (i = 0; i < _debugBuffer.Count; i++) if (((CILInstruction) _debugBuffer[i]).offset > offset) break; inst.offset = offset; _debugBuffer.Insert((i > 0 ? i - 1 : i), inst); } }
public MergeBuffer(CILInstruction[] buffer) { _debugBuffer = new ArrayList(); _buffer = buffer; }