/// <summary> /// Set the buffer as input. /// </summary> /// <param name="u">TODO u.</param> /// <param name="buf">Pointer to memory to be read from.</param> /// <param name="len">The maximum amount of memory to be read.</param> public static unsafe void UdSetInputBuffer(ref Ud u, IntPtr buf, Int32 len) { UdInputInitialization(ref u); u.InputBuffer = (Byte *)buf.ToPointer(); u.InputBufferSize = len; u.InputBufferIndex = 0; }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="addr">TODO addr.</param> public void UdSynPrintAddr(ref Ud u, Int64 addr) { String name = null; if (u.SymResolver != null) { Int64 offset = 0; name = u.SymResolver(ref u, addr, ref offset); if (!String.IsNullOrEmpty(name)) { if (offset > 0) { UdAsmPrintf(ref u, "{0}{1:+#;-#}", name, offset); } else { UdAsmPrintf(ref u, "{0}", name); } return; } } UdAsmPrintf(ref u, "0x{0:x}", addr); }
/// <summary> /// Prints an operand cast. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> public void OperandCast(ref Ud u, ref UdOperand op) { if (u.BrFar > 0) { Syn.UdAsmPrintf(ref u, "far "); } switch (op.Size) { case 8: Syn.UdAsmPrintf(ref u, "byte "); break; case 16: Syn.UdAsmPrintf(ref u, "word "); break; case 32: Syn.UdAsmPrintf(ref u, "dword "); break; case 64: Syn.UdAsmPrintf(ref u, "qword "); break; case 80: Syn.UdAsmPrintf(ref u, "tword "); break; default: break; } }
/// <summary> /// Initializes ud_t object. /// </summary> /// <param name="u">TODO u.</param> public static void UdInit(ref Ud u) { u = new Ud(); UdSetMode(ref u, 16); u.Mnemonic = UdMnemonicCode.UD_Iinvalid; UdSetPc(ref u, 0); UdSetAsmBuffer(ref u, u.AsmBufferInt, u.AsmBufferInt.Length); }
/// <summary> /// Initializes the input system. /// </summary> /// <param name="u">TODO u.</param> private static void UdInputInitialization(ref Ud u) { u.InputHook = null; u.InputBuffer = null; u.InputBufferSize = 0; u.InputBufferIndex = 0; u.InputCur = 0; u.InputCtr = 0; u.InputEnd = 0; u.InputPeek = Decode.UdEoi; }
/// <summary> /// Return the operand struct representing the nth operand of the currently disassembled instruction. Returns NULL if there's no such operand. /// </summary> /// <param name="u">TODO u.</param> /// <param name="n">TODO n.</param> /// <param name="op">TODO op.</param> private static void UdInsnOpr(ref Ud u, Int32 n, out UdOperand?op) { if (n > 3 || u.Operand[n].UdType == UdType.UD_NONE) { op = null; } else { op = u.Operand[n]; } }
/// <summary> /// Allow the user to set an assembler output buffer. If `buf` is NULL, we switch back to the internal buffer. /// </summary> /// <param name="u">TODO u.</param> /// <param name="buf">TODO buf.</param> /// <param name="size">TODO size.</param> private static void UdSetAsmBuffer(ref Ud u, Char[] buf, Int32 size) { if (buf == null) { UdSetAsmBuffer(ref u, u.AsmBufferInt, u.AsmBufferInt.Length); } else { u.AsmBuffer = buf; u.AsmBufferSize = size; } }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> public void UdSynPrintImm(ref Ud u, ref UdOperand op) { UInt64 v; if (op.OperandCode == UdOperandCode.OP_sI && op.Size != u.OprMode) { if (op.Size == 8) { v = (UInt64)op.Lval.SByte; } else { Debug.Assert(op.Size == 32, "TODO: REASON"); v = (UInt64)op.Lval.SdWord; } if (u.OprMode < 64) { v = v & ((1ul << u.OprMode) - 1ul); } } else { switch (op.Size) { case 8: v = op.Lval.UByte; break; case 16: v = op.Lval.UWord; break; case 32: v = op.Lval.UdWord; break; case 64: v = op.Lval.UqWord; break; default: Debug.Assert(false, "invalid offset"); v = 0; // keep cc happy break; } } UdAsmPrintf(ref u, "0x{0:x}", v); }
/// <summary> /// Set Disassembly mode. /// </summary> /// <param name="u">TODO u.</param> /// <param name="m">TODO m.</param> public static void UdSetMode(ref Ud u, Byte m) { switch (m) { case 16: case 32: case 64: u.DisMode = m; return; default: u.DisMode = 16; return; } }
/// <summary> /// Set vendor. /// </summary> /// <param name="u">TODO u.</param> /// <param name="v">TODO v</param> public static void UdSetVendor(ref Ud u, Int32 v) { switch (v) { case Decode.UdVendorIntel: u.Vendor = Decode.UdVendorIntel; break; case Decode.UdVendorAny: u.Vendor = Decode.UdVendorAny; break; default: u.Vendor = Decode.UdVendorAmd; break; } }
/// <summary> /// returns the disassembled instruction. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static String UdInsnAsm(ref Ud u) { if (u.AsmBuffer == null || u.AsmBuffer.Length == 0) { return(String.Empty); } Int32 count = Array.IndexOf <Char>(u.AsmBuffer, '\0', 0); if (count < 0) { count = u.AsmBuffer.Length; } Char[] c = new Char[count]; Array.Copy(u.AsmBuffer, c, count); return(new String(c)); }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="opr">TODO opr.</param> /// <returns>TODO TODO.</returns> public UInt64 UdSynRelTarget(ref Ud u, ref UdOperand opr) { UInt64 trunc_mask = 0xffffffffffffffff >> (64 - u.OprMode); switch (opr.Size) { case 8: return((u.Pc + (UInt64)opr.Lval.SByte) & trunc_mask); case 16: return((u.Pc + (UInt64)opr.Lval.SWord) & trunc_mask); case 32: return((u.Pc + (UInt64)opr.Lval.SdWord) & trunc_mask); default: Debug.Assert(false, "invalid relative offset size."); return(0); } }
/// <summary> /// Returns hex form of disassembled instruction. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static String UdInsnHex(ref Ud u) { StringBuilder sourceHex = new StringBuilder(); if (u.Error == 0) { UInt32 i; IntPtr src_ptr = UdInsnPtr(ref u); unsafe { Byte *src = (Byte *)src_ptr.ToPointer(); for (i = 0; i < UdInsnLen(ref u); i++) { sourceHex.AppendFormat("{0:2X", src[i]); } } } return(sourceHex.ToString()); }
/// <summary> /// Skip n input bytes. /// </summary> /// <param name="u">TODO u.</param> /// <param name="n">TODO n.</param> private static void UdInputSkip(ref Ud u, Int32 n) { if (u.InputEnd > 0) { return; } if (u.InputBuffer == null) { while (n-- > 0) { Int32 c = u.InputHook(ref u); if (c == Decode.UdEoi) { goto eoi; } } return; } else { if (n > u.InputBufferSize || u.InputBufferIndex > u.InputBufferSize - n) { u.InputBufferIndex = u.InputBufferSize; goto eoi; } u.InputBufferIndex += n; return; } eoi: u.InputEnd = 1; u.Error = 1; u.ErrorMessage = "cannot skip, eoi received\b"; }
/// <summary> /// Printf style function for printing translated assembly output. /// </summary> /// <param name="u">TODO u.</param> /// <param name="fmt">TODO fmt.</param> /// <param name="args">TODO args.</param> /// <returns> /// Returns the number of characters written and moves the buffer pointer forward. On an overflow, returns a negative number and truncates the output. /// </returns> public static Int32 UdAsmPrintf(ref Ud u, String fmt, params Object[] args) { Int32 ret; Int32 avail; avail = u.AsmBufferSize - u.AsmBufferFill - 1 /* nullchar */; Char[] str = String.Format(fmt, args).ToArray(); Array.Copy(str, 0, u.AsmBuffer, u.AsmBufferFill, Math.Min(str.Length, avail)); ret = str.Length; //// ret = vsnprintf((char*)u.asm_buf + u.asm_buf_fill, avail, fmt, ap); if (ret < 0 || ret > avail) { u.AsmBufferFill = u.AsmBufferSize - 1; ret = -1; } else { u.AsmBufferFill += ret; } return(ret); }
/// <summary> /// Disassembles one instruction and returns the number of bytes disassembled. A zero means end of disassembly. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> public static Int32 UdDisassemble(ref Ud u) { Int32 len; if (u.InputEnd > 0) { return(0); } if ((len = decode.UdDecode(ref u)) > 0) { if (u.Translator != null) { for (Int32 i = 0; i < u.AsmBuffer.Length; i++) { u.AsmBuffer[i] = '\0'; } u.Translator(ref u); } } return(len); }
/// <summary> /// Set file as input for disassembly. /// </summary> /// <param name="u">TODO u.</param> /// <param name="file">File stream that will be read from. The stream must support reading.</param> private static void UdSetFileInput(ref Ud u, FileStream file) { UdInputInitialization(ref u); u.InputHook = InputFileHook; u.InputFile = file; }
/// <summary> /// Set FILE as input. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static Int32 InputFileHook(ref Ud u) { return(u.InputFile.ReadByte()); }
/// <summary> /// Sets input hook. /// </summary> /// <param name="u">TODO u.</param> /// <param name="hook">TODO hook.</param> private static void UdSetInputHook(ref Ud u, UdInputCallback hook) { UdInputInitialization(ref u); u.InputHook = hook; }
/// <summary> /// translates to intel syntax. /// </summary> /// <param name="u">TODO u.</param> public void UdTranslateIntel(ref Ud u) { // Check if P_OSO prefix is used if (BitOps.P_OSO(u.ItabEntry.Prefix) == 0 && u.PfxOpr > 0) { switch (u.DisMode) { case 16: Syn.UdAsmPrintf(ref u, "o32 "); break; case 32: case 64: Syn.UdAsmPrintf(ref u, "o16 "); break; } } // Check if P_ASO prefix was used if (BitOps.P_ASO(u.ItabEntry.Prefix) == 0 && u.PfxAdr > 0) { switch (u.DisMode) { case 16: Syn.UdAsmPrintf(ref u, "a32 "); break; case 32: Syn.UdAsmPrintf(ref u, "a16 "); break; case 64: Syn.UdAsmPrintf(ref u, "a32 "); break; } } if (u.PfxSeg > 0 && u.Operand[0].UdType != UdType.UD_OP_MEM && u.Operand[1].UdType != UdType.UD_OP_MEM) { Syn.UdAsmPrintf(ref u, "{0} ", Syn.UdRegTab[u.PfxSeg - (byte)UdType.UD_R_AL]); } if (u.PfxLock > 0) { Syn.UdAsmPrintf(ref u, "lock "); } if (u.PfxRep > 0) { Syn.UdAsmPrintf(ref u, "rep "); } else if (u.PfxRepe > 0) { Syn.UdAsmPrintf(ref u, "repe "); } else if (u.PfxRepne > 0) { Syn.UdAsmPrintf(ref u, "repne "); } // Print the instruction mnemonic Syn.UdAsmPrintf(ref u, "{0}", Udis86.UdLookupMnemonic(u.Mnemonic)); if (u.Operand[0].UdType != UdType.UD_NONE) { Int32 cast = 0; Syn.UdAsmPrintf(ref u, " "); if (u.Operand[0].UdType == UdType.UD_OP_MEM) { if (u.Operand[1].UdType == UdType.UD_OP_IMM || u.Operand[1].UdType == UdType.UD_OP_CONST || u.Operand[1].UdType == UdType.UD_NONE || (u.Operand[0].Size != u.Operand[1].Size && u.Operand[1].UdType != UdType.UD_OP_REG)) { cast = 1; } else if (u.Operand[1].UdType == UdType.UD_OP_REG && u.Operand[1].Base == UdType.UD_R_CL) { switch (u.Mnemonic) { case UdMnemonicCode.UD_Ircl: case UdMnemonicCode.UD_Irol: case UdMnemonicCode.UD_Iror: case UdMnemonicCode.UD_Ircr: case UdMnemonicCode.UD_Ishl: case UdMnemonicCode.UD_Ishr: case UdMnemonicCode.UD_Isar: cast = 1; break; default: break; } } } this.GenOperand(ref u, ref u.Operand[0], cast); } if (u.Operand[1].UdType != UdType.UD_NONE) { Int32 cast = 0; Syn.UdAsmPrintf(ref u, ", "); if (u.Operand[1].UdType == UdType.UD_OP_MEM && u.Operand[0].Size != u.Operand[1].Size && !Udis86.UdOprIsSeg(u.Operand[0])) { cast = 1; } this.GenOperand(ref u, ref u.Operand[1], cast); } if (u.Operand[2].UdType != UdType.UD_NONE) { Int32 cast = 0; Syn.UdAsmPrintf(ref u, ", "); if (u.Operand[2].UdType == UdType.UD_OP_MEM && u.Operand[2].Size != u.Operand[1].Size) { cast = 1; } this.GenOperand(ref u, ref u.Operand[2], cast); } if (u.Operand[3].UdType != UdType.UD_NONE) { Syn.UdAsmPrintf(ref u, ", "); this.GenOperand(ref u, ref u.Operand[3], 0); } }
/// <summary> /// Set code origin address. /// </summary> /// <param name="u">TODO u.</param> /// <param name="o">TODO o.</param> public static void UdSetPc(ref Ud u, UInt64 o) { u.Pc = o; }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static IntPtr UdGetUserOpaqueData(ref Ud u) { return(u.UserOpaqueData); }
/// <summary> /// Get/set user opaqute data pointer. /// </summary> /// <param name="u">TODO u.</param> /// <param name="opaque">TODO opaque.</param> private static void UdSetUserOpaqueData(ref Ud u, IntPtr opaque) { u.UserOpaqueData = opaque; }
/// <summary> /// Sets the output syntax. /// </summary> /// <param name="u">TODO u.</param> /// <param name="t">TODO t</param> private static void UdSetSyntax(ref Ud u, UdTranslatorDelegate t) { u.Translator = t; }
/// <summary> /// Returns the count of bytes disassembled. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static Int32 UdInsnLen(ref Ud u) { return(u.InputCtr); }
/// <summary> /// Returns a pointer to buffer containing the bytes that were disassembled. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static unsafe IntPtr UdInsnPtr(ref Ud u) { return((u.InputBuffer == null) ? u.InputSessionPinner : new IntPtr(u.InputBuffer + u.InputBufferIndex - u.InputCtr)); }
/// <summary> /// Returns non-zero on end-of-input. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static Int32 UdInputEnd(ref Ud u) { return(u.InputEnd); }
/// <summary> /// Set symbol resolver for relative targets used in the translation phase. The resolver is a function that takes a ulong address and returns a /// symbolic name for the that address.The function also takes a second argument pointing to an integer that the client can optionally set to a /// non-zero value for offsetted targets. (symbol+offset) The function may also return NULL, in which case the translator only prints the target address. /// </summary> /// <param name="u">TODO u.</param> /// <param name="resolver">TODO resolver.</param> private static void UdSetSymResolver(ref Ud u, UdSymbolResolverDelegate resolver) { u.SymResolver = resolver; }
/// <summary> /// Return the current instruction mnemonic. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static UdMnemonicCode UdInsnMnemonic(ref Ud u) { return(u.Mnemonic); }
/// <summary> /// Returns the offset. /// </summary> /// <param name="u">TODO u.</param> /// <returns>TODO TODO.</returns> private static UInt64 UdInsnOff(ref Ud u) { return(u.InstructionOffset); }