public static Elf64_Sym Load(EndianImageReader rdr) { var sym = new Elf64_Sym(); sym.st_name = rdr.ReadUInt32(); sym.st_info = rdr.ReadByte(); sym.st_other = rdr.ReadByte(); sym.st_shndx = rdr.ReadUInt16(); sym.st_value = rdr.ReadUInt64(); sym.st_size = rdr.ReadUInt64(); return(sym); }
public void LoadElfIdentification(EndianImageReader rdr) { var elfMagic = rdr.ReadBeInt32(); if (elfMagic != ELF_MAGIC) { throw new BadImageFormatException("File is not in ELF format."); } this.fileClass = rdr.ReadByte(); this.endianness = rdr.ReadByte(); this.fileVersion = rdr.ReadByte(); this.osAbi = rdr.ReadByte(); }
public void VisitPointer(Pointer ptr) { switch (ptr.Size) { case 2: fmt.WriteKeyword("dw"); fmt.Write("\t"); fmt.Write(string.Format("0x{0:X4}", rdr.ReadByte())); fmt.WriteLine(); return; case 4: fmt.WriteKeyword("dd"); fmt.Write("\t"); fmt.Write(string.Format("0x{0:X8}", rdr.ReadUInt32())); fmt.WriteLine(); return; case 8: fmt.WriteKeyword("dq"); fmt.Write("\t"); fmt.Write(string.Format("0x{0:X16}", rdr.ReadUInt64())); fmt.WriteLine(); return; } }
/// <summary> /// Paints a line of the memory control, starting with the address. /// </summary> /// <remarks> /// The strategy is to find any items present at the current address, and try /// to paint as many adjacent items as possible. /// </remarks> /// <param name="g"></param> /// <param name="rc"></param> /// <param name="rdr"></param> private Address PaintLine(Graphics g, Rectangle rc, EndianImageReader rdr, Point ptAddr, bool render) { StringBuilder sxbCode = new StringBuilder(" "); var abCode = new List <byte>(); // Draw the address part. rc.X = 0; string s = string.Format("{0}", rdr.Address); int cx = (int)g.MeasureString(s + "X", ctrl.Font, rc.Width, StringFormat.GenericTypographic).Width; if (!render && new Rectangle(rc.X, rc.Y, cx, rc.Height).Contains(ctrl.ptDown)) { return(rdr.Address); } else { g.FillRectangle(this.defaultTheme.Background, rc.X, rc.Y, cx, rc.Height); g.DrawString(s, ctrl.Font, defaultTheme.Foreground, rc.X, rc.Y, StringFormat.GenericTypographic); } cx -= cellSize.Width / 2; rc = new Rectangle(cx, rc.Top, rc.Width - cx, rc.Height); uint rowBytesLeft = ctrl.cbRow; ulong linearSelected = ctrl.addrSelected != null?ctrl.addrSelected.ToLinear() : ~0UL; ulong linearAnchor = ctrl.addrAnchor != null?ctrl.addrAnchor.ToLinear() : ~0UL; ulong linearBeginSelection = Math.Min(linearSelected, linearAnchor); ulong linearEndSelection = Math.Max(linearSelected, linearAnchor); do { Address addr = rdr.Address; ulong linear = addr.ToLinear(); ImageMapItem item; ulong cbIn = 0; if (ctrl.ImageMap.TryFindItem(addr, out item)) { cbIn = (linear - item.Address.ToLinear()); // # of bytes 'inside' the block we are. } uint cbToDraw = 16; // item.Size - cbIn; // See if the chunk goes off the edge of the line. If so, clip it. if (cbToDraw > rowBytesLeft) { cbToDraw = rowBytesLeft; } // Now paint the bytes in this span. for (int i = 0; i < cbToDraw; ++i) { Address addrByte = rdr.Address; ctrl.ImageMap.TryFindItem(addrByte, out item); bool isSelected = linearBeginSelection <= addrByte.ToLinear() && addrByte.ToLinear() <= linearEndSelection; bool isCursor = addrByte.ToLinear() == linearSelected; if (rdr.IsValid) { byte b = rdr.ReadByte(); s = string.Format("{0:X2}", b); abCode.Add(b); } else { s = " "; abCode.Add(0x20); //$BUG: encoding? What about Ebcdic? rdr.Offset += 1; } cx = cellSize.Width * 3; Rectangle rcByte = new Rectangle( rc.Left, rc.Top, cx, rc.Height); if (!render && rcByte.Contains(ptAddr)) { return(addrByte); } var theme = GetBrushTheme(item, isSelected); g.FillRectangle(theme.Background, rc.Left, rc.Top, cx, rc.Height); if (!isSelected && theme.StartMarker != null && item != null && addrByte.ToLinear() == item.Address.ToLinear()) { var pts = new Point[] { rc.Location, rc.Location, rc.Location, }; pts[1].Offset(4, 0); pts[2].Offset(0, 4); g.FillClosedCurve(theme.StartMarker, pts); } g.DrawString(s, ctrl.Font, theme.Foreground, rc.Left + cellSize.Width / 2, rc.Top, StringFormat.GenericTypographic); if (isCursor) { ControlPaint.DrawFocusRectangle(g, rc); } rc = new Rectangle(rc.X + cx, rc.Y, rc.Width - cx, rc.Height); } rowBytesLeft -= cbToDraw; } while (rowBytesLeft > 0); if (render) { g.FillRectangle(this.defaultTheme.Background, rc); sxbCode.Append(RenderCode(abCode.ToArray())); g.DrawString(sxbCode.ToString(), ctrl.Font, this.defaultTheme.Foreground, rc.X + cellSize.Width, rc.Top, StringFormat.GenericTypographic); } return(null); }
/// <summary> /// Apply relocations to a segment. /// </summary> private bool ApplyRelocations(EndianImageReader rdr, int cRelocations, NeSegment seg) { Address address = null; NeRelocationEntry rep; Debug.Print("== Relocating segment {0}", seg.Address); for (int i = 0; i < cRelocations; i++) { rep = new NeRelocationEntry { address_type = (NE_RADDR)rdr.ReadByte(), relocation_type = (NE_RELTYPE)rdr.ReadByte(), offset = rdr.ReadLeUInt16(), target1 = rdr.ReadLeUInt16(), target2 = rdr.ReadLeUInt16(), }; Debug.Print(" {0}", WriteRelocationEntry(rep)); // Get the target address corresponding to this entry. // If additive, there is no target chain list. Instead, add source // and target. bool additive = (rep.relocation_type & NE_RELTYPE.ADDITIVE) != 0; Tuple <Address, ImportReference> impRef; uint lp; string module = ""; switch (rep.relocation_type & (NE_RELTYPE)3) { case NE_RELTYPE.ORDINAL: module = moduleNames[rep.target1 - 1]; // Synthesize an import lp = ((uint)rep.target1 << 16) | rep.target2; if (importStubs.TryGetValue(lp, out impRef)) { address = impRef.Item1; } else { address = addrImportStubs; importStubs.Add(lp, new Tuple <Address, ImportReference>( address, new OrdinalImportReference(address, module, rep.target2, SymbolType.ExternalProcedure))); addrImportStubs += 8; } break; case NE_RELTYPE.NAME: module = moduleNames[rep.target1 - 1]; uint offName = lfaNew + this.offImportedNamesTable + rep.target2; var nameRdr = new LeImageReader(RawImage, offName); byte fnNameLength = nameRdr.ReadByte(); var abFnName = nameRdr.ReadBytes(fnNameLength); // Synthesize the import. lp = ((uint)rep.target1 << 16) | rep.target2; if (importStubs.TryGetValue(lp, out impRef)) { address = impRef.Item1; } else { address = addrImportStubs; string fnName = Encoding.ASCII.GetString(abFnName); importStubs.Add(lp, new Tuple <Address, ImportReference>( address, new NamedImportReference(address, module, fnName, SymbolType.ExternalProcedure))); addrImportStubs += 8; } break; case NE_RELTYPE.INTERNAL: if ((rep.target1 & 0xff) == 0xff) { address = this.entryPoints[rep.target2 - 1].Address; } else { address = segments[rep.target1 - 1].Address + rep.target2; } Debug.Print(" {0}: {1:X4}:{2:X4} {3}", i + 1, address.Selector.Value, address.Offset, ""); break; case NE_RELTYPE.OSFIXUP: /* Relocation type 7: * * These appear to be used as fixups for the Windows * floating point emulator. Let's just ignore them and * try to use the hardware floating point. Linux should * successfully emulate the coprocessor if it doesn't * exist. */ /* * TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n", * i + 1, rep->relocation_type, rep->offset, * rep->target1, rep->target2, * NE_GetRelocAddrName( rep->address_type, additive ) ); */ continue; } ushort offset = rep.offset; // Apparently, high bit of address_type is sometimes set; // we ignore it for now. if (rep.address_type > NE_RADDR.OFFSET32) { listener.Error( string.Format( "Module {0}: unknown relocation address type {1:X2}. Please report", module, rep.address_type)); return(false); } if (additive) { var sp = seg.Address + offset; Debug.Print(" {0} (contains: {1:X4})", sp, mem.ReadLeUInt16(sp)); byte b; ushort w; switch (rep.address_type & (NE_RADDR)0x7f) { case NE_RADDR.LOWBYTE: b = mem.ReadByte(sp); mem.WriteByte(sp, (byte)(b + address.Offset)); break; case NE_RADDR.OFFSET16: w = mem.ReadLeUInt16(sp); mem.WriteLeUInt16(sp, (ushort)(w + address.Offset)); break; case NE_RADDR.POINTER32: w = mem.ReadLeUInt16(sp); mem.WriteLeUInt16(sp, (ushort)(w + address.Offset)); mem.WriteLeUInt16(sp + 2, address.Selector.Value); break; case NE_RADDR.SELECTOR: // Borland creates additive records with offset zero. Strange, but OK. w = mem.ReadLeUInt16(sp); if (w != 0) { listener.Error(string.Format("Additive selector to {0:X4}. Please report.", w)); } else { mem.WriteLeUInt16(sp, address.Selector.Value); } break; default: goto unknown; } } else { // Non-additive fixup. do { var sp = seg.Address + offset; ushort next_offset = mem.ReadLeUInt16(sp); Debug.Print(" {0} (contains: {1:X4})", sp, next_offset); switch (rep.address_type & (NE_RADDR)0x7f) { case NE_RADDR.LOWBYTE: mem.WriteByte(sp, (byte)address.Offset); break; case NE_RADDR.OFFSET16: mem.WriteLeUInt16(sp, (ushort)address.Offset); break; case NE_RADDR.POINTER32: mem.WriteLeUInt16(sp, (ushort)address.Offset); mem.WriteLeUInt16(sp + 2, address.Selector.Value); break; case NE_RADDR.SELECTOR: mem.WriteLeUInt16(sp, address.Selector.Value); break; default: goto unknown; } if (next_offset == offset) { break; // avoid infinite loop } if (next_offset >= seg.Alloc) { break; } offset = next_offset; } while (offset != 0xffff); } } return(true); unknown: listener.Warn("{0}: unknown ADDR TYPE {1}, " + "TYPE {2}, OFFSET {3:X4}, TARGET {4:X4} {5:X4}", seg.Address.Selector, rep.address_type, rep.relocation_type, rep.offset, rep.target1, rep.target2); return(false); }
public void ReadOptionalHeader(EndianImageReader rdr, short expectedMagic) { if (optionalHeaderSize <= 0) { throw new BadImageFormatException("Optional header size should be larger than 0 in a PE executable image file."); } short magic = rdr.ReadLeInt16(); if (magic != expectedMagic) { throw new BadImageFormatException("Not a valid PE Header."); } rdr.ReadByte(); // Linker major version rdr.ReadByte(); // Linker minor version rdr.ReadLeUInt32(); // code size (== .text section size) rdr.ReadLeUInt32(); // size of initialized data rdr.ReadLeUInt32(); // size of uninitialized data rvaStartAddress = rdr.ReadLeUInt32(); uint rvaBaseOfCode = rdr.ReadLeUInt32(); preferredBaseOfImage = innerLoader.ReadPreferredImageBase(rdr); rdr.ReadLeUInt32(); // section alignment rdr.ReadLeUInt32(); // file alignment rdr.ReadLeUInt16(); // OS major version rdr.ReadLeUInt16(); // OS minor version rdr.ReadLeUInt16(); // Image major version rdr.ReadLeUInt16(); // Image minor version rdr.ReadLeUInt16(); // Subsystem major version rdr.ReadLeUInt16(); // Subsystem minor version rdr.ReadLeUInt32(); // reserved uint sizeOfImage = rdr.ReadLeUInt32(); uint sizeOfHeaders = rdr.ReadLeUInt32(); uint checksum = rdr.ReadLeUInt32(); ushort subsystem = rdr.ReadLeUInt16(); ushort dllFlags = rdr.ReadLeUInt16(); var stackReserve = innerLoader.ReadWord(rdr); var stackCommit = innerLoader.ReadWord(rdr); var heapReserve = innerLoader.ReadWord(rdr); var heapCommit = innerLoader.ReadWord(rdr); rdr.ReadLeUInt32(); // loader flags uint dictionaryCount = rdr.ReadLeUInt32(); if (dictionaryCount == 0) { return; } this.rvaExportTable = rdr.ReadLeUInt32(); this.sizeExportTable = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } this.rvaImportTable = rdr.ReadLeUInt32(); uint importTableSize = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } this.rvaResources = rdr.ReadLeUInt32(); // resource address rdr.ReadLeUInt32(); // resource size if (--dictionaryCount == 0) { return; } this.rvaExceptionTable = rdr.ReadLeUInt32(); // exception address this.sizeExceptionTable = rdr.ReadLeUInt32(); // exception size if (--dictionaryCount == 0) { return; } rdr.ReadLeUInt32(); // certificate address rdr.ReadLeUInt32(); // certificate size if (--dictionaryCount == 0) { return; } this.rvaBaseRelocationTable = rdr.ReadLeUInt32(); this.sizeBaseRelocationTable = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaDebug = rdr.ReadLeUInt32(); uint cbDebug = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaArchitecture = rdr.ReadLeUInt32(); uint cbArchitecture = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaGlobalPointer = rdr.ReadLeUInt32(); uint cbGlobalPointer = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaTls = rdr.ReadLeUInt32(); uint cbTls = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaLoadConfig = rdr.ReadLeUInt32(); uint cbLoadConfig = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaBoundImport = rdr.ReadLeUInt32(); uint cbBoundImport = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } uint rvaIat = rdr.ReadLeUInt32(); uint cbIat = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) { return; } this.rvaDelayImportDescriptor = rdr.ReadLeUInt32(); uint cbDelayImportDescriptor = rdr.ReadLeUInt32(); }
public override CilInstruction DisassembleInstruction() { if (!rdr.IsValid) { return(null); } var addr = rdr.Address; var opcode = rdr.ReadByte(); instr = new CilInstruction { Address = addr, Operands = MachineInstruction.NoOperands, }; switch (opcode) { #region OPCODES case 0x00: instr.Opcode = OpCodes.Nop; break; case 0x01: instr.Opcode = OpCodes.Break; break; case 0x02: instr.Opcode = OpCodes.Ldarg_0; break; case 0x03: instr.Opcode = OpCodes.Ldarg_1; break; case 0x04: instr.Opcode = OpCodes.Ldarg_2; break; case 0x05: instr.Opcode = OpCodes.Ldarg_3; break; case 0x06: instr.Opcode = OpCodes.Ldloc_0; break; case 0x07: instr.Opcode = OpCodes.Ldloc_1; break; case 0x08: instr.Opcode = OpCodes.Ldloc_2; break; case 0x09: instr.Opcode = OpCodes.Ldloc_3; break; case 0x0A: instr.Opcode = OpCodes.Stloc_0; break; // Pop a value from stack into local variable 0. case 0x0B: instr.Opcode = OpCodes.Stloc_1; break; //Pop a value from stack into local variable 1. case 0x0C: instr.Opcode = OpCodes.Stloc_2; break; //Pop a value from stack into local variable 2. case 0x0D: instr.Opcode = OpCodes.Stloc_3; break; //Pop a value from stack into local variable 3. case 0x0E: //Load argument numbered num onto the stack, short form. instr.Opcode = OpCodes.Ldarg_S; // <uint8 (num)> instr.Operand = rdr.ReadByte(); break; case 0x0F: instr.Opcode = OpCodes.Ldarga_S; // <uint8 (argNum)> instr.Operand = rdr.ReadByte(); break; //Fetch the address of argument argNum, short form. case 0x10: instr.Opcode = OpCodes.Starg_S; // .s <uint8 (num)> instr.Operand = rdr.ReadByte(); break; //Store value to the argument numbered num, short form. case 0x11: instr.Opcode = OpCodes.Ldloc_S; // <uint8 (indx)> instr.Operand = rdr.ReadByte(); break; //Load local variable of index indx onto stack, short form. case 0x12: instr.Opcode = OpCodes.Ldloca_S; // .s <uint8 (indx)> instr.Operand = rdr.ReadByte(); break; //Load address of local variable with index indx, short form. case 0x13: instr.Opcode = OpCodes.Stloc_S; // <uint8 (indx)> instr.Operand = rdr.ReadByte(); break; //Pop a value from stack into local variable indx, short form. case 0x14: instr.Opcode = OpCodes.Ldnull; break; //Push a null reference on the stack. case 0x15: instr.Opcode = OpCodes.Ldc_I4_M1; break; //Push -1 onto the stack as int32. case 0x16: instr.Opcode = OpCodes.Ldc_I4_0; break; case 0x17: instr.Opcode = OpCodes.Ldc_I4_1; break; //Push 1 onto the stack as int32. case 0x18: instr.Opcode = OpCodes.Ldc_I4_2; break; //Push 2 onto the stack as int32. case 0x19: instr.Opcode = OpCodes.Ldc_I4_3; break; //Push 3 onto the stack as int32. case 0x1A: instr.Opcode = OpCodes.Ldc_I4_4; break; //Push 4 onto the stack as int32. case 0x1B: instr.Opcode = OpCodes.Ldc_I4_5; break; //Push 5 onto the stack as int32. case 0x1C: instr.Opcode = OpCodes.Ldc_I4_6; break; //Push 6 onto the stack as int32. case 0x1D: instr.Opcode = OpCodes.Ldc_I4_7; break; //Push 7 onto the stack as int32. case 0x1E: instr.Opcode = OpCodes.Ldc_I4_8; break; //Push 8 onto the stack as int32. case 0x1F: instr.Opcode = OpCodes.Ldc_I4_S; // <int8 (num)> instr.Operand = rdr.ReadSByte(); break; //Push num onto the stack as int32, short form. case 0x20: instr.Opcode = OpCodes.Ldc_I4;// <int32 (num)> instr.Operand = rdr.ReadLeInt32(); break; //Push num of type int32 onto the stack as int32. case 0x21: instr.Opcode = OpCodes.Ldc_I8;// <int64 (num)> instr.Operand = rdr.ReadLeInt64(); break; //Push num of type int64 onto the stack as int64. case 0x22: instr.Opcode = OpCodes.Ldc_R4;// <float32 (num)> instr.Operand = rdr.ReadLeUInt64(); break; //Push num of type float32 onto the stack as F. case 0x23: instr.Opcode = OpCodes.Ldc_R8; // <float64 (num)> instr.Operand = rdr.ReadLeUInt64(); break; //Push num of type float64 onto the stack as F. case 0x25: instr.Opcode = OpCodes.Dup; break; //Duplicate the value on the top of the stack. case 0x26: instr.Opcode = OpCodes.Pop; break; //Pop value from the stack. case 0x27: instr.Opcode = OpCodes.Jmp;// <method> break; //Exit current method and jump to the specified method. case 0x28: instr.Opcode = OpCodes.Call;// <method> break; //Call method described by method. case 0x29: instr.Opcode = OpCodes.Calli;// <callsitedescr> break; //Call method indicated on the stack with arguments described by callsitedescr. case 0x2A: instr.Opcode = OpCodes.Ret; break; //Return from method, possibly with a value. case 0x2B: instr.Opcode = OpCodes.Br_S; // <int8 (target)> break; //Branch to target, short form. case 0x2C: instr.Opcode = OpCodes.Brfalse_S;// <int8 (target)> break; //Branch to target if value is zero (false), short form. case 0x2D: instr.Opcode = OpCodes.Brtrue_S; // <int8 (target)> break; //Branch to target if value is non-zero (true), short form. case 0x2E: instr.Opcode = OpCodes.Beq_S; //.s <int8 (target)> break; //Branch to target if equal, short form. case 0x2F: instr.Opcode = OpCodes.Bge_S; //.s <int8 (target)> break; //Branch to target if greater than or equal to, short form. case 0x30: instr.Opcode = OpCodes.Bgt_S; // .s <int8 (target)> break; //Branch to target if greater than, short form. case 0x31: instr.Opcode = OpCodes.Ble_S; // .s <int8 (target)> break; //Branch to target if less than or equal to, short form. case 0x32: instr.Opcode = OpCodes.Blt_S; //.s <int8 (target)> break; //Branch to target if less than, short form. case 0x33: instr.Opcode = OpCodes.Bne_Un_S;//.un.s <int8 (target)> break; //Branch to target if unequal or unordered, short form. case 0x34: instr.Opcode = OpCodes.Bge_Un_S;// <int8 (target)> break; //Branch to target if greater than or equal to (unsigned or unordered), short form case 0x35: instr.Opcode = OpCodes.Bgt_Un_S;// <int8 (target)> break; //Branch to target if greater than (unsigned or unordered), short form. case 0x36: instr.Opcode = OpCodes.Ble_Un_S;// <int8 (target)> break; //Branch to target if less than or equal to (unsigned or unordered), short form case 0x37: instr.Opcode = OpCodes.Blt_Un_S;//.un.s <int8 (target)> break; //Branch to target if less than (unsigned or unordered), short form. case 0x38: instr.Opcode = OpCodes.Br;// <int32 (target)> break; //Branch to target. case 0x39: instr.Opcode = OpCodes.Brfalse;// <int32 (target)> break; //Branch to target if value is zero (alias for brfalse). case 0x3A: instr.Opcode = OpCodes.Brtrue;// <int32 (target)> break; //Branch to target if value is non-zero (true). case 0x3B: instr.Opcode = OpCodes.Beq;// <int32 (target)> break; //Branch to target if equal. case 0x3C: instr.Opcode = OpCodes.Bge;// <int32 (target)> break; //Branch to target if greater than or equal to. case 0x3D: instr.Opcode = OpCodes.Bgt; // <int32 (target)> break; //Branch to target if greater than. case 0x3E: instr.Opcode = OpCodes.Ble; // <int32 (target)> break; //Branch to target if less than or equal to. case 0x3F: instr.Opcode = OpCodes.Blt;// <int32 (target)> break; //Branch to target if less than. case 0x40: instr.Opcode = OpCodes.Bne_Un;// <int32 (target)> break; //Branch to target if unequal or unordered. case 0x41: instr.Opcode = OpCodes.Bge_Un;// <int32 (target)> break; //Branch to target if greater than or equal to (unsigned or unordered). case 0x42: instr.Opcode = OpCodes.Bgt_Un;// <int32 (target)> break; //Branch to target if greater than (unsigned or unordered). case 0x43: instr.Opcode = OpCodes.Ble_Un;// <int32 (target)> break; //Branch to target if less than or equal to (unsigned or unordered). case 0x44: instr.Opcode = OpCodes.Blt_Un;// <int32 (target)> break; //Branch to target if less than (unsigned or unordered). case 0x45: instr.Opcode = OpCodes.Switch;// <uint32, int32,int32 (t1..tN)> break; //Jump to one of n values. case 0x46: instr.Opcode = OpCodes.Ldind_I1; break; //Indirect load value of type int8 as int32 on the stack. case 0x47: instr.Opcode = OpCodes.Ldind_U1; break; //Indirect load value of type unsigned int8 as int32 on the stack case 0x48: instr.Opcode = OpCodes.Ldind_I2; break; //Indirect load value of type int16 as int32 on the stack. case 0x49: instr.Opcode = OpCodes.Ldind_U2; break; //Indirect load value of type unsigned int16 as int32 on the stack case 0x4A: instr.Opcode = OpCodes.Ldind_I4; break; //Indirect load value of type int32 as int32 on the stack. case 0x4B: instr.Opcode = OpCodes.Ldind_U4; break; //Indirect load value of type unsigned int32 as int32 on the stack case 0x4C: instr.Opcode = OpCodes.Ldind_I8; break; //Indirect load value of type int64 as int64 on the stack. case 0x4D: instr.Opcode = OpCodes.Ldind_I; break; //Indirect load value of type native int as native int on the stack case 0x4E: instr.Opcode = OpCodes.Ldind_R4; break; //Indirect load value of type float32 as F on the stack. case 0x4F: instr.Opcode = OpCodes.Ldind_R8; break; //Indirect load value of type float64 as F on the stack. case 0x50: instr.Opcode = OpCodes.Ldind_Ref; break; //Indirect load value of type object ref as O on the stack. case 0x51: instr.Opcode = OpCodes.Stind_Ref; break; //Store value of type object ref (type O) into memory at address case 0x52: instr.Opcode = OpCodes.Stind_I1; break; //Store value of type int8 into memory at address case 0x53: instr.Opcode = OpCodes.Stind_I2; break; //Store value of type int16 into memory at address case 0x54: instr.Opcode = OpCodes.Stind_I4; break; //Store value of type int32 into memory at address case 0x55: instr.Opcode = OpCodes.Stind_I8; break; // Store value of type int64 into memory at address case 0x56: instr.Opcode = OpCodes.Stind_R4; break; //Store value of type float32 into memory at address case 0x57: instr.Opcode = OpCodes.Stind_R8; break; //Store value of type float64 into memory at address case 0x58: instr.Opcode = OpCodes.Add; break; //Add two values, returning a new value. case 0x59: instr.Opcode = OpCodes.Sub; break; //Subtract value2 from value1, returning a new value. case 0x5A: instr.Opcode = OpCodes.Mul; break; //Multiply values. case 0x5B: instr.Opcode = OpCodes.Div; break; //Divide two values to return a quotient or floating-point result. case 0x5C: instr.Opcode = OpCodes.Div_Un; break; //Divide two values, unsigned, returning a quotient. case 0x5D: instr.Opcode = OpCodes.Rem; break; //Remainder when dividing one value by another. case 0x5E: instr.Opcode = OpCodes.Rem_Un; break; //Remainder when dividing one unsigned value by another. case 0x5F: instr.Opcode = OpCodes.And; break; //Bitwise AND of two integral values, returns an integral value. case 0x60: instr.Opcode = OpCodes.Or; break; //Bitwise OR of two integer values, returns an integer. case 0x61: instr.Opcode = OpCodes.Xor; break; //Bitwise XOR of integer values, returns an integer. case 0x62: instr.Opcode = OpCodes.Shl; break; //Shift an integer left (shifting in zeros), return an integer. case 0x63: instr.Opcode = OpCodes.Shr; break; //Shift an integer right (shift in sign), return an integer. case 0x64: instr.Opcode = OpCodes.Shr_Un; break; //Shift an integer right (shift in zero), return an integer. case 0x65: instr.Opcode = OpCodes.Neg; break; //Negate value. case 0x66: instr.Opcode = OpCodes.Not; break; //Bitwise complement (logical not). case 0x67: instr.Opcode = OpCodes.Conv_I1; break; //Convert to int8, pushing int32 on stack. case 0x68: instr.Opcode = OpCodes.Conv_I2; break; //Convert to int16, pushing int32 on stack. case 0x69: instr.Opcode = OpCodes.Conv_I4; break; //Convert to int32, pushing int32 on stack. case 0x6A: instr.Opcode = OpCodes.Conv_I8; break; //Convert to int64, pushing int64 on stack. case 0x6B: instr.Opcode = OpCodes.Conv_R4; break; //Convert to float32, pushing F on stack. case 0x6C: instr.Opcode = OpCodes.Conv_R8; break; //Convert to float64, pushing F on stack. case 0x6D: instr.Opcode = OpCodes.Conv_U4; break; //Convert to unsigned int32, pushing int32 on stack. case 0x6E: instr.Opcode = OpCodes.Conv_U8; break; //Convert to unsigned int64, pushing int64 on stack. case 0x6F: instr.Opcode = OpCodes.Callvirt; // <method> break; //Call a method associated with an object. Object model instruction case 0x70: instr.Opcode = OpCodes.Cpobj; // <typeTok> break; //Copy a value type from src to dest. Object model instruction case 0x71: instr.Opcode = OpCodes.Ldobj;// <typeTok> break; //Copy the value stored at address src to the stack. Object model instruction case 0x72: instr.Opcode = OpCodes.Ldstr;// <string> break; //Push a string object for the literal string. Object model instruction case 0x73: instr.Opcode = OpCodes.Newobj;// <ctor> break; //Allocate an uninitialized object or value type and call ctor. Object model instruction case 0x74: instr.Opcode = OpCodes.Castclass; // <class> break; //Cast obj to class. Object model instruction case 0x75: instr.Opcode = OpCodes.Isinst; //<class> break; //Test if obj is an instance of class, returning null or an instance of that class or interface. Object model instruction case 0x76: instr.Opcode = OpCodes.Conv_R_Un; break; //Convert unsigned integer to floating-point, pushing F on stack. case 0x79: instr.Opcode = OpCodes.Unbox; //<valuetype> break; //Extract a value-type from obj, its boxed representation. Object model instruction case 0x7A: instr.Opcode = OpCodes.Throw; break; //Throw an exception. Object model instruction case 0x7B: instr.Opcode = OpCodes.Ldfld; // <field> break; //Push the value of field of object (or value type) obj, onto the stack. Object model instruction case 0x7C: instr.Opcode = OpCodes.Ldflda; // <field> break; //Push the address of field of object obj on the stack. Object model instruction case 0x7D: instr.Opcode = OpCodes.Stfld; //<field> break; //Replace the value of field of the object obj with value. Object model instruction case 0x7E: instr.Opcode = OpCodes.Ldsfld;// <field> break; //Push the value of field on the stack. Object model instruction case 0x7F: instr.Opcode = OpCodes.Ldsflda;// <field> break; //Push the address of the static field, field, on the stack. Object model instruction case 0x80: instr.Opcode = OpCodes.Stsfld; // <field> break; //Replace the value of field with val. Object model instruction case 0x81: instr.Opcode = OpCodes.Stobj; //<typeTok> break; //Store a value of type typeTok at an address. Object model instruction case 0x82: instr.Opcode = OpCodes.Conv_Ovf_I1_Un; break; //Convert unsigned to an int8 (on the stack as int32) and throw an exception on overflow. case 0x83: instr.Opcode = OpCodes.Conv_Ovf_I2_Un; break; //Convert unsigned to an int16 (on the stack as int32) and throw an exception on overflow. case 0x84: instr.Opcode = OpCodes.Conv_Ovf_I4_Un; break; //Convert unsigned to an int32 (on the stack as int32) and throw an exception on overflow. case 0x85: instr.Opcode = OpCodes.Conv_Ovf_I8_Un; break; //Convert unsigned to an int64 (on the stack as int64) and throw an exception on overflow. case 0x86: instr.Opcode = OpCodes.Conv_Ovf_U1_Un; break; //Convert unsigned to an unsigned int8 (on the stack as int32) and throw an exception on overflow. case 0x87: instr.Opcode = OpCodes.Conv_Ovf_I2_Un; break; //Convert unsigned to an unsigned int16 (on the stack as int32) and throw an exception on overflow. case 0x88: instr.Opcode = OpCodes.Conv_Ovf_U4_Un; break; //Convert unsigned to an unsigned int32 (on the stack as int32) and throw an exception on overflow. case 0x89: instr.Opcode = OpCodes.Conv_Ovf_U8_Un; break; //Convert unsigned to an unsigned int64 (on the stack as int64) and throw an exception on overflow. case 0x8A: instr.Opcode = OpCodes.Conv_Ovf_I_Un; break; //Convert unsigned to a native int (on the stack as native int) and throw an exception on overflow. case 0x8B: instr.Opcode = OpCodes.Conv_Ovf_U_Un; break; //Convert unsigned to a native unsigned int (on the stack as native int) and throw an exception on overflow. case 0x8C: instr.Opcode = OpCodes.Box;// <typeTok> break; //Convert a boxable value to its boxed form Object model instruction case 0x8D: instr.Opcode = OpCodes.Newarr;// <etype> break; //Create a new array with elements of type etype. Object model instruction case 0x8E: instr.Opcode = OpCodes.Ldlen; break; //Push the length (of type native unsigned int) of array on the stack. Object model instruction case 0x8F: instr.Opcode = OpCodes.Ldelema;// <class> break; //Load the address of element at index onto the top of the stack. Object model instruction case 0x90: instr.Opcode = OpCodes.Ldelem_I1; break; //Load the element with type int8 at index onto the top of the stack as an int32. Object model instruction case 0x91: instr.Opcode = OpCodes.Ldelem_U1; break; //Load the element with type unsigned int8 at index onto the top of the stack as an int32. Object model instruction case 0x92: instr.Opcode = OpCodes.Ldelem_I2; break; //Load the element with type int16 at index onto the top of the stack as an int32. Object model instruction case 0x93: instr.Opcode = OpCodes.Ldelem_U2; break; //Load the element with type unsigned int16 at index onto the top of the stack as an int32. Object model instruction case 0x94: instr.Opcode = OpCodes.Ldelem_I4; break; //Load the element with type int32 at index onto the top of the stack as an int32. Object model instruction case 0x95: instr.Opcode = OpCodes.Ldelem_U4; break; //Load the element with type unsigned int32 at index onto the top of the stack as an int32. Object model instruction case 0x96: instr.Opcode = OpCodes.Ldelem_I8; break; //Load the element with type unsigned int64 at index onto the top of the stack as an int64 (alias for ldelem.i8). Object model instruction case 0x97: instr.Opcode = OpCodes.Ldelem_I; break; //Load the element with type native int at index onto the top of the stack as a native int. Object model instruction case 0x98: instr.Opcode = OpCodes.Ldelem_R4; break; //Load the element with type float32 at index onto the top of the stack as an F Object model instruction case 0x99: instr.Opcode = OpCodes.Ldelem_R8; break; //Load the element with type float64 at index onto the top of the stack as an F. Object model instruction case 0x9A: instr.Opcode = OpCodes.Ldelem_Ref; break; //Load the element at index onto the top of the stack as an O. The type of the O is the same as the element type of the array pushed on the CIL stack. Object model instruction case 0x9B: instr.Opcode = OpCodes.Stelem_I; break; //Replace array element at index with the i value on the stack. Object model instruction case 0x9C: instr.Opcode = OpCodes.Stelem_I1; break; //Replace array element at index with the int8 value on the stack. Object model instruction case 0x9D: instr.Opcode = OpCodes.Stelem_I2; break; //Replace array element at index with the int16 value on the stack. Object model instruction case 0x9E: instr.Opcode = OpCodes.Stelem_I4; break; //Replace array element at index with the int32 value on the stack. Object model instruction case 0x9F: instr.Opcode = OpCodes.Stelem_I8; break; //Replace array element at index with the int64 value on the stack. Object model instruction case 0xA0: instr.Opcode = OpCodes.Stelem_R4; break; //Replace array element at index with the float32 value on the stack. Object model instruction case 0xA1: instr.Opcode = OpCodes.Stelem_R8; break; //Replace array element at index with the float64 value on the stack. Object model instruction case 0xA2: instr.Opcode = OpCodes.Stelem_Ref; break; //Replace array element at index with the ref value on the stack. Object model instruction case 0xA3: instr.Opcode = OpCodes.Ldelem;// <typeTok> break; //Load the element at index onto the top of the stack. Object model instruction case 0xA4: instr.Opcode = OpCodes.Stelem;// <typeTok> break; //Replace array element at index with the value on the stack Object model instruction case 0xA5: instr.Opcode = OpCodes.Unbox_Any;//<typeTok> break; //Extract a value-type from obj, its boxed representation Object model instruction case 0xB3: instr.Opcode = OpCodes.Conv_Ovf_I1; break; //Convert to an int8 (on the stack as int32) and throw an exception on overflow. case 0xB4: instr.Opcode = OpCodes.Conv_Ovf_U1; break; //Convert to an unsigned int8 (on the stack as int32) and throw an exception on overflow. case 0xB5: instr.Opcode = OpCodes.Conv_Ovf_I2; break; //Convert to an int16 (on the stack as int32) and throw an exception on overflow. case 0xB6: instr.Opcode = OpCodes.Conv_Ovf_U2; break; //Convert to an unsigned int16 (on the stack as int32) and throw an exception on overflow. case 0xB7: instr.Opcode = OpCodes.Conv_Ovf_I4; break; //Convert to an int32 (on the stack as int32) and throw an exception on overflow. case 0xB8: instr.Opcode = OpCodes.Conv_Ovf_U4; break; //Convert to an unsigned int32 (on the stack as int32) and throw an exception on overflow. case 0xB9: instr.Opcode = OpCodes.Conv_Ovf_I8; break; //Convert to an int64 (on the stack as int64) and throw an exception on overflow. case 0xBA: instr.Opcode = OpCodes.Conv_Ovf_U8; break; //Convert to an unsigned int64 (on the stack as int64) and throw an exception on overflow. case 0xC2: instr.Opcode = OpCodes.Refanyval;// <type> break; //Push the address stored in a typed reference. Object model instruction case 0xC3: instr.Opcode = OpCodes.Ckfinite; break; //Throw ArithmeticException if value is not a finite number. case 0xC6: instr.Opcode = OpCodes.Mkrefany; // <class> break; //Push a typed reference to ptr of type class onto the stack. Object model instruction case 0xD0: instr.Opcode = OpCodes.Ldtoken;// <token> break; //Convert metadata token to its runtime representation. Object model instruction case 0xD1: instr.Opcode = OpCodes.Conv_U2; break; // Convert to unsigned int16, pushing int32 on stack. case 0xD2: instr.Opcode = OpCodes.Conv_U1; break; // Convert to unsigned int8, pushing int32 on stack. case 0xD3: instr.Opcode = OpCodes.Conv_I; break; // Convert to native int, pushing native int on stack. case 0xD4: instr.Opcode = OpCodes.Conv_Ovf_I; break; // Convert to a native int (on the stack as native int) and throw an exception on overflow. case 0xD5: instr.Opcode = OpCodes.Conv_Ovf_U; break; // Convert to a native unsigned int (on the stack as native int) and throw an exception on overflow. case 0xD6: instr.Opcode = OpCodes.Add_Ovf; break; // Add signed integer values with overflow check. case 0xD7: instr.Opcode = OpCodes.Add_Ovf_Un; break; // Add unsigned integer values with overflow check. case 0xD8: instr.Opcode = OpCodes.Mul_Ovf; break; // Multiply signed integer values. Signed result shall fit in same size case 0xD9: instr.Opcode = OpCodes.Mul_Ovf_Un; break; // Multiply unsigned integer values. Unsigned result shall fit in same size case 0xDA: instr.Opcode = OpCodes.Sub_Ovf; break; // Subtract native int from a native int. Signed result shall fit in same size case 0xDB: instr.Opcode = OpCodes.Sub_Ovf_Un; break; // Subtract native unsigned int from a native unsigned int. Unsigned result shall fit in same size. case 0xDC: instr.Opcode = OpCodes.Endfinally; break; // End finally clause of an exception block. case 0xDD: instr.Opcode = OpCodes.Leave; // <int32 (target)> break; //Exit a protected region of code. case 0xDE: instr.Opcode = OpCodes.Leave_S; // <int8 (target)> break; //Exit a protected region of code, short form. case 0xDF: instr.Opcode = OpCodes.Stind_I; break; // Store value of type native int into memory at address case 0xE0: instr.Opcode = OpCodes.Conv_U; break; //Convert to native unsigned int, pushing native int on stack. case 0xFE: switch (rdr.ReadByte()) { case 0x00: instr.Opcode = OpCodes.Arglist; break; // Return argument list handle for the current method. case 0x01: instr.Opcode = OpCodes.Ceq; break; // Push 1 (of type int32) if value1 equals value2, else push 0. case 0x02: instr.Opcode = OpCodes.Cgt; break; // Push 1 (of type int32) if value1 > value2, else push 0. case 0x03: instr.Opcode = OpCodes.Cgt_Un; break; // Push 1 (of type int32) if value1 > value2, unsigned or unordered, else push 0. case 0x04: instr.Opcode = OpCodes.Clt; break; // Push 1 (of type int32) if value1 < value2, else push 0. case 0x05: instr.Opcode = OpCodes.Clt_Un; break; // Push 1 (of type int32) if value1 < value2, unsigned or unordered, else push 0. case 0x06: instr.Opcode = OpCodes.Ldftn;// <method> break; // Push a pointer to a method referenced by method, on the stack. case 0x07: instr.Opcode = OpCodes.Ldvirtftn;// <method> break; // Push address of virtual method on the stack. Object model instruction case 0x09: instr.Opcode = OpCodes.Ldarg;//<uint16 (num)> break; //Load argument numbered num onto the stack. case 0x0A: instr.Opcode = OpCodes.Ldarga;// <uint16 (argNum)> break; //Fetch the address of argument argNum. case 0x0B: instr.Opcode = OpCodes.Starg; // <uint16 (num)> break; //Store value to the argument numbered num. case 0x0C: instr.Opcode = OpCodes.Ldloc; //<uint16 (indx)> break; //Load local variable of index indx onto stack. case 0x0D: instr.Opcode = OpCodes.Ldloca; //<uint16 (indx)> break; //Load address of local variable with index indx. case 0x0E: instr.Opcode = OpCodes.Stloc; // <uint16 (indx)> break; // Pop a value from stack into local variable indx. case 0x0F: instr.Opcode = OpCodes.Localloc; break; // Allocate space from the local memory pool. case 0x11: instr.Opcode = OpCodes.Endfilter; break; // End an exception handling filter clause. case 0x12: instr.Opcode = OpCodes.Unaligned; //. (alignment) break; //Subsequent pointer instruction might be unaligned. Prefix to instruction case 0x13: instr.Opcode = OpCodes.Volatile; break; //Subsequent pointer reference is volatile. Prefix to instruction case 0x14: instr.Opcode = OpCodes.Tailcall; break; // Subsequent call terminates current method Prefix to instruction case 0x15: instr.Opcode = OpCodes.Initobj; // <typeTok> break; // Initialize the value at address dest. Object model instruction case 0x16: instr.Opcode = OpCodes.Constrained; //. <thisType> break; // Call a virtual method on a type constrained to be type T Prefix to instruction case 0x17: instr.Opcode = OpCodes.Cpblk; break; // Copy data from memory to memory. case 0x18: instr.Opcode = OpCodes.Initblk; break; //Set all bytes in a block of memory to a given byte value. case 0x19: throw new NotImplementedException(); //instr.Opcode = OpCodes.no { //break; //typecheck, //rangecheck, //nullcheck //The specified fault check(s) normally performed as part of the execution of the subsequent instruction can/shall be skipped. Prefix to instruction case 0x1A: instr.Opcode = OpCodes.Rethrow; break; // Rethrow the current exception. Object model instruction case 0x1C: instr.Opcode = OpCodes.Sizeof; //<typeTok> break; //Push the size, in bytes, of a type as an unsigned int32. Object model instruction case 0x1D: instr.Opcode = OpCodes.Refanytype; break; //Push the type token stored in a typed reference. Object model instruction case 0x1E: instr.Opcode = OpCodes.Readonly; break; //Specify that the subsequent array address operation performs no type check at runtime, and that it returns a controlled-mutability managed pointer Prefix to instruction } break; #endregion } instr.Length = (int)(rdr.Address - addr); return(instr); }