private MachineOperand ImmediateOperand(PrimitiveType width) { if (!rdr.TryRead(width, out Constant imm)) { return(null); } return(new ImmediateOperand(imm)); }
public void WriteOpcodes(MemoryArea image, IProcessorArchitecture arch, Address begin, Address addrEnd, InstrWriter writer) { EndianImageReader rdr = arch.CreateImageReader(image, begin); var byteSize = (7 + arch.InstructionBitSize) / 8; string instrByteFormat = $"{{0:X{byteSize * 2}}} "; // each byte is two nybbles. var instrByteSize = PrimitiveType.CreateWord(arch.InstructionBitSize); while (rdr.Address < addrEnd && rdr.TryRead(instrByteSize, out var v)) { writer.WriteFormat(instrByteFormat, v.ToUInt64()); } }
public void VisitPointer(Pointer ptr) { if (!rdr.TryRead(PrimitiveType.Create(Domain.Pointer, ptr.BitSize), out var c)) { return; } var addr = Address.FromConstant(c); if (!program.SegmentMap.IsValidAddress(addr)) { return; } scanner.EnqueueUserGlobalData(addr, ptr.Pointee, null); }
/// <summary> /// Render some memory, reading from the provided <see cref="ImageReader"/>, into /// a suitable output device <paramref name="output" />. This method /// takes into account that the image reader may not be positioned at /// the beginning of a logical line; in that case it will render /// filler space to ensure the display lines up. /// </summary> /// <param name="rdr">Imagereader to read the data from.</param> /// <param name="enc">Text encoding used to render textual data.</param> /// <param name="output">Output device to which the rendered strings /// are emitted.</param> public bool RenderLine(EndianImageReader rdr, Encoding enc, IMemoryFormatterOutput output) { output.BeginLine(); var offStart = rdr.Offset; var addr = rdr.Address; output.RenderAddress(addr); var addrStart = Align(addr, unitsPerLine); var prePaddingUnits = (int)(addr - addrStart); var offsetEndLine = (rdr.Offset - prePaddingUnits) + unitsPerLine; output.RenderFillerSpan(PaddingCells(prePaddingUnits)); bool moreData = true; int postPaddingUnits = 0; while (moreData && rdr.Offset < offsetEndLine) { addr = rdr.Address; moreData = rdr.TryRead(dtUnit, out var c); if (moreData) { output.RenderUnit(addr, string.Format(unitFormat, c.GetValue())); } else { postPaddingUnits = (int)(offsetEndLine - rdr.Offset); } } output.RenderFillerSpan(PaddingCells(postPaddingUnits)); var cb = rdr.Offset - offStart; rdr.Offset = offStart; var bytes = rdr.ReadBytes((int)cb); string sBytes = RenderAsText(enc, bytes); output.RenderUnitsAsText(prePaddingUnits * this.bytesPerUnit, sBytes, postPaddingUnits * this.bytesPerUnit); output.EndLine(bytes); return(moreData && rdr.IsValid); }
public override string RenderInstructionOpcode(MachineInstruction instr, EndianImageReader rdr) { var bitSize = this.InstructionBitSize; var instrSize = PrimitiveType.CreateWord(bitSize); var sb = new StringBuilder(); var numBase = this.DefaultBase; int digits = 6; for (int i = 0; i < instr.Length; ++i) { if (rdr.TryRead(instrSize, out var v)) { sb.Append(Convert.ToString((long)v.ToUInt64(), numBase) .PadLeft(digits, '0')); sb.Append(' '); } } return(sb.ToString()); }
public CodeFormatter VisitPrimitive(PrimitiveType pt) { if (pt.Size > 8) { var bytes = rdr.ReadBytes(pt.Size); FormatRawBytes(bytes); } else { if (rdr.TryRead(pt, out var cValue)) { cValue.Accept(codeFormatter); } else { codeFormatter.InnerFormatter.WriteLine("?? /* Can't read address {0} */", rdr.Address); } } return(codeFormatter); }
private X86Instruction DecodeOperands(Opcode opcode, byte op, string strFormat, InstrClass iclass) { if (strFormat == null) { return(null); } MachineOperand pOperand; PrimitiveType width = null; PrimitiveType iWidth = dataWidth; byte modRm; List <MachineOperand> ops = new List <MachineOperand>(); int i = 0; while (i != strFormat.Length) { if (strFormat[i] == ',') { ++i; } pOperand = null; MemoryOperand memOp; char chFmt = strFormat[i++]; switch (chFmt) { case '1': pOperand = new ImmediateOperand(Constant.Byte(1)); break; case '3': pOperand = new ImmediateOperand(Constant.Byte(3)); break; case 'A': // Absolute memory address. ++i; if (!rdr.TryReadLeUInt16(out ushort off)) { return(null); } if (!rdr.TryReadLeUInt16(out ushort seg)) { return(null); } var addr = mode.CreateSegmentedAddress(seg, off); if (addr == null) { return(null); } pOperand = new X86AddressOperand(addr); break; case 'C': // control register encoded in the reg field. ++i; if (!TryEnsureModRM(out modRm)) { return(null); } var creg = mode.GetControlRegister((modRm >> 3) & 7); if (creg == null) { return(null); } pOperand = new RegisterOperand(creg); break; case 'D': // debug register encoded in the reg field. ++i; if (!TryEnsureModRM(out modRm)) { return(null); } var dreg = mode.GetDebugRegister((modRm >> 3) & 7); if (dreg == null) { return(null); } pOperand = new RegisterOperand(dreg); break; case 'E': // memory or register operand specified by mod & r/m fields. width = OperandWidth(strFormat, ref i); ++i; pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, GpRegFromBits); if (pOperand == null) { return(null); } break; case 'Q': // memory or register MMX operand specified by mod & r/m fields. width = SseOperandWidth(strFormat, ref i); pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, MmxRegFromBits); if (pOperand == null) { return(null); } break; case 'G': // register operand specified by the reg field of the modRM byte. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits)); break; case 'H': // If VEX encoding, use vvvv register. if (currentDecodingContext.IsVex) { width = SseOperandWidth(strFormat, ref i); pOperand = new RegisterOperand(XmmRegFromBits(currentDecodingContext.VexRegister, width)); } else { i = strFormat.IndexOf(',', i); } break; case 'N': // MMX register operand specified by the r/m field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, MmxRegFromBits)); break; case 'P': // MMX register operand specified by the reg field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits)); break; case 'I': // Immediate operand. if (strFormat[i] == 'x') { iWidth = width; // Use width of the previous operand. } else { width = OperandWidth(strFormat, ref i); // Don't use the width of the previous operand. } ++i; pOperand = CreateImmediateOperand(width, dataWidth); if (pOperand == null) { return(null); } break; case 'L': // The upper 4 bits of the 8-bit immediate selects a 128-bit XMM register or a 256-bit YMM register, determined // by operand type. if (!rdr.TryReadByte(out var lReg)) { return(null); } if (strFormat[i] == 'x') { iWidth = width; // Use width of the previous operand. } else { width = OperandWidth(strFormat, ref i); // Don't use the width of the previous operand. } ++i; pOperand = new RegisterOperand(XmmRegFromBits((lReg >> 4) & 0xF, width)); break; case 'J': // Relative ("near") jump. width = OperandWidth(strFormat, ref i); ++i; Constant cOffset; if (!rdr.TryRead(width, out cOffset)) { return(null); } long jOffset = cOffset.ToInt64(); ulong uAddr = (ulong)((long)rdr.Address.Offset + jOffset); if (defaultAddressWidth.BitSize == 64) //$REVIEW: not too keen on the switch statement here. { pOperand = AddressOperand.Ptr64(uAddr); } else if (defaultAddressWidth.BitSize == 32) { pOperand = AddressOperand.Ptr32((uint)uAddr); } else { pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr)); } break; case 'M': // modRM may only refer to memory. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } if ((modRm & 0xC0) == 0xC0) { return(null); } pOperand = DecodeModRM(dataWidth, this.currentDecodingContext.SegmentOverride, GpRegFromBits) as MemoryOperand; if (pOperand == null) { return(null); } break; case 'O': // Offset of the operand is encoded directly after the opcode. width = OperandWidth(strFormat, ref i); ++i; if (!rdr.TryReadLe(addressWidth, out var offset)) { return(null); } pOperand = memOp = new MemoryOperand(width, offset); memOp.SegOverride = this.currentDecodingContext.SegmentOverride; break; case 'R': // register operand specified by the mod field of the modRM byte. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, GpRegFromBits)); break; case 'S': // Segment register encoded by reg field of modRM byte. ++i; // Skip over the 'w'. if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(SegFromBits(modRm >> 3)); break; case 'U': // XMM operand specified by the modRm field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, XmmRegFromBits)); break; case 'V': // XMM operand specified by the reg field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits)); break; case 'W': // memory or XMM operand specified by mod & r/m fields. width = SseOperandWidth(strFormat, ref i); pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, XmmRegFromBits); break; case 'a': // Implicit use of accumulator. pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat, ref i))); ++i; break; case 'b': iWidth = PrimitiveType.Byte; pOperand = null; break; case 'c': // Implicit use of CL. pOperand = new RegisterOperand(Registers.cl); break; case 'd': // Implicit use of DX or EDX. width = OperandWidth(strFormat, ref i); ++i; pOperand = new RegisterOperand(RegFromBitsRexW(2, width)); break; case 'r': // Register encoded as last 3 bits of instruction. iWidth = width = OperandWidth(strFormat, ref i); ++i; pOperand = new RegisterOperand(RegFromBitsRexB(op, width)); break; case 's': // Segment encoded as next byte of the format string. pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0')); break; case 'F': // Floating-point ST(x) if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new FpuOperand(modRm & 0x07); break; case 'f': // ST(0) pOperand = new FpuOperand(0); break; default: throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat)); } if (pOperand != null) { ops.Add(pOperand); } } return(new X86Instruction(opcode, iclass, iWidth, addressWidth, ops.ToArray()) { repPrefix = this.currentDecodingContext.F2Prefix ? 2 : this.currentDecodingContext.F3Prefix ? 3 : 0 }); }