public static object ReadPointer(Type pointerType, int size, ImageReader rdr, ReaderContext ctx) { Debug.Print("Reading pointer at offset {0}, size {1}", rdr.Offset, size); uint newOffset; switch (size) { default: throw new InvalidOperationException("Field size must be > 0."); case 1: newOffset = rdr.ReadByte(); break; case 2: newOffset = rdr.ReadUInt16(); break; case 4: newOffset = rdr.ReadUInt32(); break; } Debug.Print("Structure of type {0} must start at offset {1:X}", pointerType.Name, newOffset); rdr = rdr.Clone(); rdr.Offset = newOffset; var dst = Activator.CreateInstance(pointerType); var sr = new StructureReader(dst); sr.Read(rdr); return dst; }
private MachineOperand ParseOperandInner(byte addressMode, byte operandBits, PrimitiveType dataWidth, ImageReader rdr) { Constant offset; switch (addressMode) { case 0: // Data register direct. return DataRegisterOperand(operandBits, 0); case 1: // Address register direct return new RegisterOperand(AddressRegister(operandBits, 0)); case 2: // Address register indirect return MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0)); case 3: // Address register indirect with postincrement. return MemoryOperand.PostIncrement(dataWidth, AddressRegister(operandBits, 0)); case 4: // Address register indirect with predecrement. return MemoryOperand.PreDecrement(dataWidth, AddressRegister(operandBits, 0)); case 5: // Address register indirect with displacement. offset = Constant.Int16(rdr.ReadBeInt16()); return MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0), offset); case 6: // Address register indirect with index return AddressRegisterIndirectWithIndex(dataWidth, rdr); case 7: switch (operandBits) { case 0: // Absolute short address return new M68kAddressOperand(rdr.ReadBeUInt16()); case 1: // Absolute long address return new M68kAddressOperand(rdr.ReadBeUInt32()); case 2: // Program counter with displacement var off = rdr.Address - dasm.instr.Address; off += rdr.ReadBeInt16(); return new MemoryOperand(dataWidth, Registers.pc, Constant.Int16((short) off)); case 3: // Program counter with index var addrExt = rdr.Address; ushort extension = rdr.ReadBeUInt16(); if (EXT_FULL(extension)) { if (EXT_EFFECTIVE_ZERO(extension)) { return new M68kImmediateOperand(Constant.Word32(0)); } Constant @base = null; Constant outer = null; if (EXT_BASE_DISPLACEMENT_PRESENT(extension)) @base = EXT_BASE_DISPLACEMENT_LONG(extension) ? rdr.ReadBe(PrimitiveType.Word32) : rdr.ReadBe(PrimitiveType.Int16); if (EXT_OUTER_DISPLACEMENT_PRESENT(extension)) outer = EXT_OUTER_DISPLACEMENT_LONG(extension) ? rdr.ReadBe(PrimitiveType.Word32) : rdr.ReadBe(PrimitiveType.Int16); RegisterStorage base_reg = EXT_BASE_REGISTER_PRESENT(extension) ? Registers.pc : null; RegisterStorage index_reg = null; PrimitiveType index_width = null; int index_scale = 0; if (EXT_INDEX_REGISTER_PRESENT(extension)) { index_reg = EXT_INDEX_AR(extension) ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension)) : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension)); index_width = EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16; index_scale = (EXT_INDEX_SCALE(extension) != 0) ? 1 << EXT_INDEX_SCALE(extension) : 0; } return new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_width, index_scale, (extension & 7) > 0 && (extension & 7) < 4, (extension & 7) > 4); } return new IndirectIndexedOperand( EXT_8BIT_DISPLACEMENT(extension), Registers.pc, EXT_INDEX_AR(extension) ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension)) : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension)), EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16, 1 << EXT_INDEX_SCALE(extension)); case 4: // Immediate if (dataWidth.Size == 1) // don't want the instruction stream to get misaligned! rdr.ReadByte(); return new M68kImmediateOperand(rdr.ReadBe(dataWidth)); default: throw new NotImplementedException(string.Format("Address mode {0}:{1} not implemented.", addressMode, operandBits)); } default: throw new NotImplementedException(string.Format("Address mode {0:X1} not implemented.", addressMode)); } }
private static M68kImmediateOperand GetImmediate(ImageReader rdr, PrimitiveType type) { if (type.Size == 1) { rdr.ReadByte(); // skip a byte so we get the appropriate lsb byte and align the word stream. } return new M68kImmediateOperand(rdr.ReadBe(type)); }
private static string ReadSectionName(ImageReader rdr) { byte [] bytes = new Byte[8]; for (int b = 0; b < bytes.Length; ++b) { bytes[b] = rdr.ReadByte(); } Encoding asc = Encoding.ASCII; char [] chars = asc.GetChars(bytes); int i; for (i = chars.Length - 1; i >= 0; --i) { if (chars[i] != 0) { ++i; break; } } return new String(chars, 0, i); }
public void ReadOptionalHeader(ImageReader 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 = rdr.Read(arch.WordWidth); var stackCommit = rdr.Read(arch.WordWidth); var heapReserve = rdr.Read(arch.WordWidth); var heapCommit = rdr.Read(arch.WordWidth); rdr.ReadLeUInt32(); // loader flags uint dictionaryCount = rdr.ReadLeUInt32(); if (dictionaryCount == 0) return; rvaExportTable = rdr.ReadLeUInt32(); sizeExportTable = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; rvaImportTable = rdr.ReadLeUInt32(); uint importTableSize = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; rdr.ReadLeUInt32(); // resource address rdr.ReadLeUInt32(); // resource size if (--dictionaryCount == 0) return; rdr.ReadLeUInt32(); // exception address rdr.ReadLeUInt32(); // exception size if (--dictionaryCount == 0) return; rdr.ReadLeUInt32(); // certificate address rdr.ReadLeUInt32(); // certificate size if (--dictionaryCount == 0) return; uint rvaBaseRelocAddress = rdr.ReadLeUInt32(); uint baseRelocSize = 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(); }
/// <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, ImageReader rdr, Point ptAddr, bool render) { StringBuilder sbCode = new StringBuilder(" "); // 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(SystemBrushes.Window, rc.X, rc.Y, cx, rc.Height); g.DrawString(s, ctrl.Font, SystemBrushes.ControlText, 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; if (!ctrl.ImageMap.TryFindItem(addr, out item)) break; ulong 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); char ch = (char) b; sbCode.Append(Char.IsControl(ch) ? '.' : ch); } else { s = "??"; sbCode.Append(' '); } 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 && 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(SystemBrushes.Window, rc); g.DrawString(sbCode.ToString(), ctrl.Font, SystemBrushes.WindowText, rc.X + cellSize.Width, rc.Top, StringFormat.GenericTypographic); } return null; }