Ejemplo n.º 1
0
 private MachineOperand ImmediateOperand(PrimitiveType width)
 {
     if (!rdr.TryRead(width, out Constant imm))
     {
         return(null);
     }
     return(new ImmediateOperand(imm));
 }
Ejemplo n.º 2
0
        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());
            }
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        /// <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);
        }
Ejemplo n.º 5
0
        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());
        }
Ejemplo n.º 6
0
 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);
 }
Ejemplo n.º 7
0
        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
            });
        }