/* ============================================================================= * ud_inp_set_buffer * Set buffer as input. * ============================================================================= */ /// <summary> /// Set the buffer as input /// </summary> /// <param name="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 ud_set_input_buffer(ref ud u, IntPtr buf, int len) { ud_inp_init(ref u); u.inp_buf = (byte *)buf.ToPointer(); u.inp_buf_size = len; u.inp_buf_index = 0; }
decode_mem_disp(ref ud u, int size, ref ud_operand op) { switch (size) { case 8: op.offset = 8; op.lval.ubyte = inp_uint8(ref u); break; case 16: op.offset = 16; op.lval.uword = inp_uint16(ref u); break; case 32: op.offset = 32; op.lval.udword = inp_uint32(ref u); break; case 64: op.offset = 64; op.lval.uqword = inp_uint64(ref u); break; default: return; } }
//#endif /* __UD_STANDALONE__ */ /* ============================================================================= * ud_input_skip * Skip n input bytes. * ============================================================================ */ static unsafe void ud_input_skip(ref ud u, int n) { if (u.inp_end > 0) { return; } if (u.inp_buf == null) { while (n-- > 0) { int c = u.inp_hook(ref u); if (c == Decode.UD_EOI) { goto eoi; } } return; } else { if (n > u.inp_buf_size || u.inp_buf_index > u.inp_buf_size - n) { u.inp_buf_index = u.inp_buf_size; goto eoi; } u.inp_buf_index += n; return; } eoi: u.inp_end = 1; u.error = 1; u.errorMessage = "cannot skip, eoi received\b"; return; }
ud_insn_hex(ref ud u) { //u.insn_hexcode[0] = '\0'; StringBuilder src_hex = new StringBuilder(); if (u.error == 0) { int i; IAssemblyCode src_ptr = ud_insn_ptr(ref u); unsafe { //byte* src = (byte*)src_ptr.ToPointer(); for (i = 0; i < ud_insn_len(ref u); i++) { src_hex.AppendFormat("{0:2X", src_ptr[i]); } } //byte[] src_ptr = ud_insn_ptr(ref u); // //char[] src_hex; // /* for each byte used to decode instruction */ //for (i = 0; i < src_ptr.Length; // && i < u.insn_hexcode.Length / 2; // ++i) //{ // src_hex.Append(String.Format("{0:2x}", src_ptr[i] & 0xFF)); //} } return(src_hex.ToString()); }
/* ============================================================================= * ud_inp_set_buffer * Set buffer as input. * ============================================================================= */ /// <summary> /// Set the buffer as input /// </summary> /// <param name="u">The u.</param> /// <param name="code">The code.</param> public static unsafe void ud_set_input_buffer(ref ud u, IAssemblyCode code) { ud_inp_init(ref u); u.inp_buf = code; u.inp_buf_size = code.Length; u.inp_buf_index = 0; }
/* ----------------------------------------------------------------------------- * clear_insn() - clear instruction structure * ----------------------------------------------------------------------------- */ void clear_insn(ref ud u) { u.error = 0; u.pfx_seg = 0; u.pfx_opr = 0; u.pfx_adr = 0; u.pfx_lock = 0; u.pfx_repne = 0; u.pfx_rep = 0; u.pfx_repe = 0; u.pfx_rex = 0; u.pfx_str = 0; u.mnemonic = ud_mnemonic_code.UD_Inone; u.itab_entry = new ud_itab_entry(); u.have_modrm = 0; u.br_far = 0; u.vex_op = 0; u._rex = 0; u.operand[0] = new ud_operand(); u.operand[1] = new ud_operand(); u.operand[2] = new ud_operand(); u.operand[3] = new ud_operand(); //memset( &u.operand[ 0 ], 0, sizeof( ud_operand ) ); //memset( &u.operand[ 1 ], 0, sizeof( ud_operand ) ); //memset( &u.operand[ 2 ], 0, sizeof( ud_operand ) ); }
unsafe int inp_peek(ref ud u) { if (u.inp_end == 0) { if (u.inp_buf != null) { if (u.inp_buf_index < u.inp_buf_size) { return(u.inp_buf[u.inp_buf_index]); } } else if (u.inp_peek != UD_EOI) { return(u.inp_peek); } else { int c; if ((c = u.inp_hook(ref u)) != UD_EOI) { u.inp_peek = c; return(u.inp_peek); } } } u.inp_end = 1; u.error = 1; u.errorMessage = "byte expected, eoi received"; return(0); }
/* ============================================================================= * ud_decode() - Instruction decoder. Returns the number of bytes decoded. * ============================================================================= */ public int ud_decode(ref ud u) { inp_start(ref u); clear_insn(ref u); u.le = InstructionTables.ud_lookup_table_list[0]; u.error = (byte)((decode_prefixes(ref u) == -1 || decode_opcode(ref u) == -1 || u.error == 1) ? 1 : 0); /* Handle decode error. */ if (u.error == 1) { /* clear out the decode data. */ clear_insn(ref u); /* mark the sequence of bytes as invalid. */ u.itab_entry = InstructionTables.ud_itab[0]; /* entry 0 is invalid */ u.mnemonic = u.itab_entry.Mnemonic; } /* maybe this stray segment override byte * should be spewed out? */ if (BitOps.P_SEG(u.itab_entry.Prefix) == 0 && u.operand[0].type != ud_type.UD_OP_MEM && u.operand[1].type != ud_type.UD_OP_MEM) { u.pfx_seg = 0; } u.insn_offset = u.pc; /* set offset of instruction */ u.asm_buf_fill = 0; /* set translation buffer index to 0 */ u.pc += (uint)u.inp_ctr; /* move program counter by bytes decoded */ /* return number of bytes disassembled. */ return(u.inp_ctr); }
int resolve_mnemonic(ref ud u) { /* resolve 3dnow weirdness. */ if (u.mnemonic == ud_mnemonic_code.UD_I3dnow) { u.mnemonic = InstructionTables.ud_itab[u.le.Table[inp_curr(ref u)]].Mnemonic; } /* SWAPGS is only valid in 64bits mode */ if (u.mnemonic == ud_mnemonic_code.UD_Iswapgs && u.dis_mode != 64) { u.error = 1; u.errorMessage = "swapgs invalid in 64bits mode\n"; return(-1); } if (u.mnemonic == ud_mnemonic_code.UD_Ixchg) { if ((u.operand[0].type == ud_type.UD_OP_REG && u.operand[0].@base == ud_type.UD_R_AX && u.operand[1].type == ud_type.UD_OP_REG && u.operand[1].@base == ud_type.UD_R_AX) || (u.operand[0].type == ud_type.UD_OP_REG && u.operand[0].@base == ud_type.UD_R_EAX && u.operand[1].type == ud_type.UD_OP_REG && u.operand[1].@base == ud_type.UD_R_EAX)) { u.operand[0].type = ud_type.UD_NONE; u.operand[1].type = ud_type.UD_NONE; u.mnemonic = ud_mnemonic_code.UD_Inop; } } if (u.mnemonic == ud_mnemonic_code.UD_Inop && u.pfx_repe != 0) { u.pfx_repe = 0; u.mnemonic = ud_mnemonic_code.UD_Ipause; } return(0); }
unsafe int inp_peek(ref ud u) { if (u.inp_end == 0) { if (u.inp_buf != null) { if (u.inp_buf_index < u.inp_buf_size) { return u.inp_buf[u.inp_buf_index]; } } else if (u.inp_peek != UD_EOI) { return u.inp_peek; } else { int c; if ((c = u.inp_hook(ref u)) != UD_EOI) { u.inp_peek = c; return u.inp_peek; } } } u.inp_end = 1; u.error = 1; u.errorMessage = "byte expected, eoi received"; return 0; }
unsafe byte inp_next(ref ud u) { if (u.inp_end == 0) { //if (u.inp_buf != null) //{ if (u.inp_buf_index < u.inp_buf_size) { u.inp_ctr++; return(u.inp_curr = u.inp_buf[u.inp_buf_index++]); } //} //else //{ // int c = u.inp_peek; // if ((c = u.inp_hook(ref u)) != UD_EOI) // { // u.inp_peek = UD_EOI; // u.inp_curr = (byte)c; // u.inp_sess[u.inp_ctr++] = u.inp_curr; // return u.inp_curr; // } //} } u.inp_end = 1; u.error = 1; u.errorMessage = "byte expected, eoi received\n"; return(0); }
/* ============================================================================= * ud_decode() - Instruction decoder. Returns the number of bytes decoded. * ============================================================================= */ public int ud_decode(ref ud u) { inp_start(ref u); clear_insn(ref u); u.le = InstructionTables.ud_lookup_table_list[0]; u.error = (byte)((decode_prefixes(ref u) == -1 || decode_opcode(ref u) == -1 || u.error == 1) ? 1 : 0); /* Handle decode error. */ if (u.error == 1) { /* clear out the decode data. */ clear_insn(ref u); /* mark the sequence of bytes as invalid. */ u.itab_entry = InstructionTables.ud_itab[0]; /* entry 0 is invalid */ u.mnemonic = u.itab_entry.Mnemonic; } /* maybe this stray segment override byte * should be spewed out? */ if (BitOps.P_SEG(u.itab_entry.Prefix) == 0 && u.operand[0].type != ud_type.UD_OP_MEM && u.operand[1].type != ud_type.UD_OP_MEM) u.pfx_seg = 0; u.insn_offset = u.pc; /* set offset of instruction */ u.asm_buf_fill = 0; /* set translation buffer index to 0 */ u.pc += (uint)u.inp_ctr; /* move program counter by bytes decoded */ /* return number of bytes disassembled. */ return u.inp_ctr; }
decode_vex_vvvv(ref ud u, ref ud_operand opr, ud_operand_size size) { byte vvvv; Debug.Assert(u.vex_op != 0); vvvv = (byte)(((u.vex_op == 0xc4 ? u.vex_b2 : u.vex_b1) >> 3) & 0xf); decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(0xf & ~vvvv), size); }
ushort inp_uint16(ref ud u) { ushort r, ret; ret = (ushort)inp_next(ref u); r = (ushort)inp_next(ref u); return((ushort)(ret | (r << 8))); }
decode_moffset(ref ud u, ud_operand_size size, ref ud_operand opr) { opr.type = ud_type.UD_OP_MEM; opr.@base = ud_type.UD_NONE; opr.index = ud_type.UD_NONE; opr.scale = 0; opr.size = (byte)resolve_operand_size(ref u, size); decode_mem_disp(ref u, u.adr_mode, ref opr); }
/* * decode_modrm_reg * * Decodes reg field of mod/rm byte * */ void decode_modrm_reg(ref ud u, ref ud_operand operand, reg_class type, ud_operand_size size) { byte reg = (byte)((BitOps.REX_R(u._rex) << 3) | BitOps.MODRM_REG(modrm(ref u))); decode_reg(ref u, ref operand, type, reg, size); }
ud_inp_init(ref ud u) { //u.inp_buf = null; //u.inp_buf_index = 0; u.inp_curr = 0; u.inp_ctr = 0; u.inp_end = 0; u.inp_peek = Decode.UD_EOI; //UD_NON_STANDALONE(u.inp_file = NULL); }
byte modrm(ref ud u) { if (u.have_modrm == 0) { u.modrm = inp_next(ref u); u.modrm_offset = (byte)(u.inp_ctr - 1); u.have_modrm = 1; } return(u.modrm); }
int decode_insn(ref ud u, ushort ptr) { Debug.Assert((ptr & 0x8000) == 0); u.itab_entry = InstructionTables.ud_itab[ptr]; u.mnemonic = u.itab_entry.Mnemonic; return((resolve_pfx_str(ref u) == 0 && resolve_mode(ref u) == 0 && decode_operands(ref u) == 0 && resolve_mnemonic(ref u) == 0) ? 0 : -1); }
ud_insn_opr(ref ud u, int n, out ud_operand?op) { if (n > 3 || u.operand[n].type == ud_type.UD_NONE) { op = null; } else { op = u.operand[n]; } }
/* ============================================================================= * ud_set_mode() - Set Disassemly Mode. * ============================================================================= */ /// <summary> /// Set Disassembly mode /// </summary> /// <param name="u"></param> /// <param name="m"></param> public static void ud_set_mode(ref ud u, byte m) { switch (m) { case 16: case 32: case 64: u.dis_mode = m; return; default: u.dis_mode = 16; return; } }
ud_init(ref ud u) { u = new ud(); ud_set_mode(ref u, 16); u.mnemonic = ud_mnemonic_code.UD_Iinvalid; ud_set_pc(ref u, 0); //#ifndef __UD_STANDALONE__ // ud_set_input_file(u, stdin); //#endif /* __UD_STANDALONE__ */ ud_set_asm_buffer(ref u, u.asm_buf_int, u.asm_buf_int.Length); }
/* ============================================================================= * ud_set_asm_buffer * Allow the user to set an assembler output buffer. If `buf` is NULL, * we switch back to the internal buffer. * ============================================================================= */ static void ud_set_asm_buffer(ref ud u, char[] buf, int size) { if (buf == null) { ud_set_asm_buffer(ref u, u.asm_buf_int, u.asm_buf_int.Length); } else { u.asm_buf = buf; u.asm_buf_size = size; } }
decode_opcode(ref ud u) { ushort ptr; Debug.Assert(u.le.Type == ud_table_type.UD_TAB__OPC_TABLE); if (u.error != 0) { return(u.error); } ptr = u.le.Table[inp_curr(ref u)]; return(decode_ext(ref u, ptr)); }
inp_uint32(ref ud u) { UInt32 r, ret; ret = (UInt32)inp_next(ref u); r = (UInt32)inp_next(ref u); ret = ret | (r << 8); r = (UInt32)inp_next(ref u); ret = ret | (r << 16); r = (UInt32)inp_next(ref u); return(ret | (r << 24)); }
ud_init(ref ud u) { u = new ud(); ud_set_mode(ref u, 16); u.mnemonic = ud_mnemonic_code.UD_Iinvalid; ud_set_pc(ref u, 0); //#ifndef __UD_STANDALONE__ // ud_set_input_file(u, stdin); //#endif /* __UD_STANDALONE__ */ ud_set_asm_buffer(ref u, u.asm_buf_int, u.asm_buf_int.Length); }
decode_vex_immreg(ref ud u, ref ud_operand opr, ud_operand_size size) { byte imm = (byte)inp_next(ref u); byte mask = (byte)(u.dis_mode == 64 ? 0xf : 0x7); if (u.error != 0) { return(u.error); } Debug.Assert(u.vex_op != 0); decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(mask & (imm >> 4)), size); return(0); }
decode_vex(ref ud u) { byte index; if (u.dis_mode != 64 && BitOps.MODRM_MOD((byte)inp_peek(ref u)) != 0x3) { index = 0; } else { u.vex_op = (byte)inp_curr(ref u); u.vex_b1 = (byte)inp_next(ref u); if (u.vex_op == 0xc4) { byte pp, m; /* 3-byte vex */ u.vex_b2 = inp_next(ref u); if (u.error != 0) { return(u.error); } m = (byte)(u.vex_b1 & 0x1f); if (m == 0 || m > 3) { u.error = 1; u.errorMessage = "decode-error: reserved vex.m-mmmm value"; } pp = (byte)(u.vex_b2 & 0x3); index = (byte)((pp << 2) | m); } else { /* 2-byte vex */ Debug.Assert(u.vex_op == 0xc5); index = (byte)(0x1 | ((u.vex_b1 & 0x3) << 2)); } } if (u.le.Table.Length > index) { return(decode_ext(ref u, u.le.Table[index])); } else { u.error = 1; u.errorMessage = string.Format("decoding vex error: index value {0} of 'u.le.Table' is out of range {1}", index, u.le.Table.Length); return(-1); } }
unsafe int inp_peek(ref ud u) { if (u.inp_end == 0) { if (u.inp_buf_index < u.inp_buf_size) { return(u.inp_buf[u.inp_buf_index]); } } u.inp_end = 1; u.error = 1; u.errorMessage = "byte expected, eoi received"; return(0); }
unsafe byte inp_next(ref ud u) { if (u.inp_end == 0) { if (u.inp_buf_index < u.inp_buf_size) { u.inp_ctr++; return(u.inp_curr = u.inp_buf[u.inp_buf_index++]); } } u.inp_end = 1; u.error = 1; u.errorMessage = "byte expected, eoi received\n"; return(0); }
decode_opcode(ref ud u) { ushort ptr; Debug.Assert(u.le.Type == ud_table_type.UD_TAB__OPC_TABLE); if (u.error != 0) { return(u.error); } //if (u.inp_buf_index >= 0x2df7 ) //{ // bool stop = true; //} ptr = u.le.Table[inp_curr(ref u)]; return(decode_ext(ref u, ptr)); }
public ulong ud_syn_rel_target(ref ud u, ref ud_operand opr) { ulong trunc_mask = 0xffffffffffffffff >> (64 - u.opr_mode); switch (opr.size) { case 8: return((u.pc + (ulong)opr.lval.@sbyte) & trunc_mask); case 16: return((u.pc + (ulong)opr.lval.sword) & trunc_mask); case 32: return((u.pc + (ulong)opr.lval.sdword) & trunc_mask); default: Debug.Assert(false, "invalid relative offset size."); return(0); } }
decode_reg(ref ud u, ref ud_operand opr, reg_class type, byte num, ud_operand_size size) { int reg; size = resolve_operand_size(ref u, size); switch (type) { case reg_class.REGCLASS_GPR: reg = (int)decode_gpr(ref u, size, (byte)num); break; case reg_class.REGCLASS_MMX: reg = (int)ud_type.UD_R_MM0 + (num & 7); break; case reg_class.REGCLASS_XMM: reg = num + (int)(size == ud_operand_size.SZ_QQ ? ud_type.UD_R_YMM0 : ud_type.UD_R_XMM0); break; case reg_class.REGCLASS_CR: reg = (int)ud_type.UD_R_CR0 + num; break; case reg_class.REGCLASS_DB: reg = (int)ud_type.UD_R_DR0 + num; break; case reg_class.REGCLASS_SEG: { /* * Only 6 segment registers, anything else is an error. */ if ((num & 7) > 5) { u.error = 1; u.errorMessage = "invalid segment register value\n"; return; } else { reg = (int)ud_type.UD_R_ES + (num & 7); } break; } default: Debug.Assert(false, "invalid register type"); return; } opr.type = ud_type.UD_OP_REG; opr.@base = (ud_type)reg; opr.size = (byte)size; }
/* ============================================================================= * ud_disassemble * Disassembles one instruction and returns the number of * bytes disassembled. A zero means end of disassembly. * ============================================================================= */ /// <summary> /// Disassembles one instruction and returns the number of bytes disassembled. A zero means end of disassembly. /// </summary> /// <param name="u"></param> /// <returns></returns> public static int ud_disassemble(ref ud u) { int len; if (u.inp_end > 0) { return 0; } if ((len = decode.ud_decode(ref u)) > 0) { if (u.translator != null) { for (var i = 0; i < u.asm_buf.Length; i++) u.asm_buf[i] = '\0'; u.translator(ref u); } } return len; }
//#endif /* __UD_STANDALONE__ */ /* ============================================================================= * ud_input_skip * Skip n input bytes. * ============================================================================ */ static void ud_input_skip(ref ud u, int n) { if (u.inp_end > 0) { return; } if (u.inp_buf == null) { while (n-- > 0) { int c = u.inp_hook(ref u); if (c == Decode.UD_EOI) { goto eoi; } } return; } else { if (n > u.inp_buf_size || u.inp_buf_index > u.inp_buf_size - n) { u.inp_buf_index = u.inp_buf_size; goto eoi; } u.inp_buf_index += n; return; } eoi: u.inp_end = 1; u.error = 1; u.errorMessage = "cannot skip, eoi received\b"; return; }
decode_vex_vvvv(ref ud u, ref ud_operand opr, ud_operand_size size) { byte vvvv; Debug.Assert(u.vex_op != 0); vvvv = (byte)(((u.vex_op == 0xc4 ? u.vex_b2 : u.vex_b1) >> 3) & 0xf); decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(0xf & ~vvvv), size); }
/* ============================================================================= * ud_input_end * Returns non-zero on end-of-input. * ============================================================================= */ static int ud_input_end(ref ud u) { return u.inp_end; }
/* ============================================================================= * ud_inp_set_hook * Sets input hook. * ============================================================================= */ static void ud_set_input_hook(ref ud u, UdInputCallback hook) { ud_inp_init(ref u); u.inp_hook = hook; }
/* ============================================================================= * ud_set_user_opaque_data * ud_get_user_opaque_data * Get/set user opaqute data pointer * ============================================================================= */ static void ud_set_user_opaque_data(ref ud u, IntPtr opaque) { u.user_opaque_data = opaque; }
/* ============================================================================= * ud_insn_mnemonic * Return the current instruction mnemonic. * ============================================================================= */ static ud_mnemonic_code ud_insn_mnemonic(ref ud u) { return u.mnemonic; }
/* ============================================================================= * ud_insn_ptr * Returns a pointer to buffer containing the bytes that were * disassembled. * ============================================================================= */ /// <summary> /// Returns a pointer to buffer containing the bytes that were disassembled. /// </summary> /// <param name="u"></param> /// <returns></returns> static unsafe IntPtr ud_insn_ptr(ref ud u) { return (u.inp_buf == null) ? u._inputSessionPinner : new IntPtr(u.inp_buf + u.inp_buf_index - u.inp_ctr); }
/// <summary> /// Set file as input for disassembly. /// </summary> /// <param name="u"></param> /// <param name="file">File stream that will be read from. The stream must support reading.</param> public static void ud_set_input_file(ref ud u, System.IO.FileStream file) { ud_inp_init(ref u); u.inp_hook = inp_file_hook; u.inp_file = file; }
/* ============================================================================= * ud_set_mode() - Set Disassemly Mode. * ============================================================================= */ /// <summary> /// Set Disassembly mode /// </summary> /// <param name="u"></param> /// <param name="m"></param> public static void ud_set_mode(ref ud u, byte m) { switch (m) { case 16: case 32: case 64: u.dis_mode = m; return; default: u.dis_mode = 16; return; } }
/* ============================================================================= * ud_insn_get_opr * Return the operand struct representing the nth operand of * the currently disassembled instruction. Returns NULL if * there's no such operand. * ============================================================================= */ /// <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"></param> /// <param name="n"></param> /// <param name="op"></param> public static void ud_insn_opr(ref ud u, int n, out ud_operand? op) { if (n > 3 || u.operand[n].type == ud_type.UD_NONE) { op = null; } else { op = u.operand[n]; } }
/* ============================================================================= * ud_inp_set_buffer * Set buffer as input. * ============================================================================= */ /// <summary> /// Set the buffer as input /// </summary> /// <param name="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 ud_set_input_buffer(ref ud u, IntPtr buf, int len) { ud_inp_init(ref u); u.inp_buf = (byte*)buf.ToPointer(); u.inp_buf_size = len; u.inp_buf_index = 0; }
/* ============================================================================= * ud_insn_len * Returns the count of bytes disassembled. * ============================================================================= */ /// <summary> /// Returns the count of bytes disassembled. /// </summary> /// <param name="u"></param> /// <returns></returns> public static int ud_insn_len(ref ud u) { return u.inp_ctr; }
/* ============================================================================= * ud_insn() - returns the disassembled instruction * ============================================================================= */ /// <summary> /// returns the disassembled instruction /// </summary> /// <param name="u"></param> /// <returns></returns> public static string ud_insn_asm(ref ud u) { if (u.asm_buf == null || u.asm_buf.Length == 0) return String.Empty; int count = Array.IndexOf<char>(u.asm_buf, '\0', 0); if (count < 0) count = u.asm_buf.Length; char[] c = new char[count]; Array.Copy(u.asm_buf, c, count); return new String(c); }
decode_operand(ref ud u, ref ud_operand operand, ud_operand_code type, ud_operand_size size) { operand.type = ud_type.UD_NONE; operand._oprcode = type; switch (type) { case ud_operand_code.OP_A: decode_a(ref u, ref operand); break; case ud_operand_code.OP_MR: decode_modrm_rm(ref u, ref operand, (byte)reg_class.REGCLASS_GPR, BitOps.MODRM_MOD(modrm(ref u)) == 3 ? size.Mx_reg_size() : size.Mx_mem_size()); break; case ud_operand_code.OP_F: u.br_far = 1; if (BitOps.MODRM_MOD(modrm(ref u)) == 3) { u.error = 1; u.errorMessage = "expected modrm.mod != 3\n"; } decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size); break; case ud_operand_code.OP_M: if (BitOps.MODRM_MOD(modrm(ref u)) == 3) { u.error = 1; u.errorMessage = "expected modrm.mod != 3\n"; } decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size); break; case ud_operand_code.OP_E: decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size); break; case ud_operand_code.OP_G: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_GPR, size); break; case ud_operand_code.OP_sI: case ud_operand_code.OP_I: decode_imm(ref u, size, ref operand); break; case ud_operand_code.OP_I1: operand.type = ud_type.UD_OP_CONST; operand.lval.udword = 1; break; case ud_operand_code.OP_N: if (BitOps.MODRM_MOD(modrm(ref u)) != 3) { u.error = 1; u.errorMessage = "expected modrm.mod == 3\n"; } decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size); break; case ud_operand_code.OP_Q: decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size); break; case ud_operand_code.OP_P: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_MMX, size); break; case ud_operand_code.OP_U: if (BitOps.MODRM_MOD(modrm(ref u)) != 3) { u.error = 1; u.errorMessage = "expected modrm.mod == 3\n"; } decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size); break; case ud_operand_code.OP_W: decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size); break; case ud_operand_code.OP_V: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_XMM, size); break; case ud_operand_code.OP_H: decode_vex_vvvv(ref u, ref operand, size); break; case ud_operand_code.OP_MU: decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, BitOps.MODRM_MOD(modrm(ref u)) == 3 ? size.Mx_reg_size() : size.Mx_mem_size()); break; case ud_operand_code.OP_S: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_SEG, size); break; case ud_operand_code.OP_O: decode_moffset(ref u, size, ref operand); break; case ud_operand_code.OP_R0: case ud_operand_code.OP_R1: case ud_operand_code.OP_R2: case ud_operand_code.OP_R3: case ud_operand_code.OP_R4: case ud_operand_code.OP_R5: case ud_operand_code.OP_R6: case ud_operand_code.OP_R7: decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, (byte)((BitOps.REX_B(u._rex) << 3) | (type - ud_operand_code.OP_R0)), size); break; case ud_operand_code.OP_AL: case ud_operand_code.OP_AX: case ud_operand_code.OP_eAX: case ud_operand_code.OP_rAX: decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 0, size); break; case ud_operand_code.OP_CL: case ud_operand_code.OP_CX: case ud_operand_code.OP_eCX: decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 1, size); break; case ud_operand_code.OP_DL: case ud_operand_code.OP_DX: case ud_operand_code.OP_eDX: decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 2, size); break; case ud_operand_code.OP_ES: case ud_operand_code.OP_CS: case ud_operand_code.OP_DS: case ud_operand_code.OP_SS: case ud_operand_code.OP_FS: case ud_operand_code.OP_GS: /* in 64bits mode, only fs and gs are allowed */ if (u.dis_mode == 64) { if (type != ud_operand_code.OP_FS && type != ud_operand_code.OP_GS) { u.error = 1; u.errorMessage = "invalid segment register in 64bits\n"; } } operand.type = ud_type.UD_OP_REG; operand.@base = (type - ud_operand_code.OP_ES) + ud_type.UD_R_ES; operand.size = 16; break; case ud_operand_code.OP_J: decode_imm(ref u, size, ref operand); operand.type = ud_type.UD_OP_JIMM; break; case ud_operand_code.OP_R: if (BitOps.MODRM_MOD(modrm(ref u)) != 3) { u.error = 1; u.errorMessage = "expected modrm.mod == 3\n"; } decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size); break; case ud_operand_code.OP_C: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_CR, size); break; case ud_operand_code.OP_D: decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_DB, size); break; case ud_operand_code.OP_I3: operand.type = ud_type.UD_OP_CONST; operand.lval.@sbyte = 3; break; case ud_operand_code.OP_ST0: case ud_operand_code.OP_ST1: case ud_operand_code.OP_ST2: case ud_operand_code.OP_ST3: case ud_operand_code.OP_ST4: case ud_operand_code.OP_ST5: case ud_operand_code.OP_ST6: case ud_operand_code.OP_ST7: operand.type = ud_type.UD_OP_REG; operand.@base = (type - ud_operand_code.OP_ST0) + ud_type.UD_R_ST0; operand.size = 80; break; case ud_operand_code.OP_L: decode_vex_immreg(ref u, ref operand, size); break; default: operand.type = ud_type.UD_NONE; break; } return operand.type; }
/* * ud_inp_init * Initializes the input system. */ static void ud_inp_init(ref ud u) { u.inp_hook = null; u.inp_buf = null; u.inp_buf_size = 0; u.inp_buf_index = 0; u.inp_curr = 0; u.inp_ctr = 0; u.inp_end = 0; u.inp_peek = Decode.UD_EOI; //UD_NON_STANDALONE(u.inp_file = NULL); }
decode_operands(ref ud u) { if (decode_operand(ref u, ref u.operand[0], u.itab_entry.Operand1.type, u.itab_entry.Operand1.size) != ud_type.UD_NONE) { if (decode_operand(ref u, ref u.operand[1], u.itab_entry.Operand2.type, u.itab_entry.Operand2.size) != ud_type.UD_NONE) { if (decode_operand(ref u, ref u.operand[2], u.itab_entry.Operand3.type, u.itab_entry.Operand3.size) != ud_type.UD_NONE) { decode_operand(ref u, ref u.operand[3], u.itab_entry.Operand4.type, u.itab_entry.Operand4.size); } } } return 0; }
/* ============================================================================= * ud_insn_hex() - Returns hex form of disassembled instruction. * ============================================================================= */ static string ud_insn_hex(ref ud u) { //u.insn_hexcode[0] = '\0'; StringBuilder src_hex = new StringBuilder(); if (u.error == 0) { uint i; IntPtr src_ptr = ud_insn_ptr(ref u); unsafe { byte* src = (byte*)src_ptr.ToPointer(); for (i = 0; i < ud_insn_len(ref u); i++) { src_hex.AppendFormat("{0:2X", src[i]); } } //byte[] src_ptr = ud_insn_ptr(ref u); // //char[] src_hex; // /* for each byte used to decode instruction */ //for (i = 0; i < src_ptr.Length; // && i < u.insn_hexcode.Length / 2; // ++i) //{ // src_hex.Append(String.Format("{0:2x}", src_ptr[i] & 0xFF)); //} } return src_hex.ToString(); }
/* ============================================================================= * ud_set_syntax() - Sets the output syntax. * ============================================================================= */ /// <summary> /// Sets the output syntax /// </summary> /// <param name="u"></param> /// <param name="t"></param> public static void ud_set_syntax(ref ud u, UdTranslatorDelegate t) { u.translator = t; }
/* ============================================================================= * ud_insn_offset() - Returns the offset. * ============================================================================= */ static ulong ud_insn_off(ref ud u) { return u.insn_offset; }
/* ============================================================================= * ud_set_vendor() - Set vendor. * ============================================================================= */ /// <summary> /// Set vendor. /// </summary> /// <param name="u"></param> /// <param name="v"></param> public static void ud_set_vendor(ref ud u, int v) { switch (v) { case Decode.UD_VENDOR_INTEL: u.vendor = Decode.UD_VENDOR_INTEL; break; case Decode.UD_VENDOR_ANY: u.vendor = Decode.UD_VENDOR_ANY; break; default: u.vendor = Decode.UD_VENDOR_AMD; break; } }
/* ============================================================================= * ud_set_asm_buffer * Allow the user to set an assembler output buffer. If `buf` is NULL, * we switch back to the internal buffer. * ============================================================================= */ static void ud_set_asm_buffer(ref ud u, char[] buf, int size) { if (buf == null) { ud_set_asm_buffer(ref u, u.asm_buf_int, u.asm_buf_int.Length); } else { u.asm_buf = buf; u.asm_buf_size = size; } }
//#ifndef __UD_STANDALONE__ /* ============================================================================= * ud_input_set_file * Set FILE as input. * ============================================================================= */ static int inp_file_hook(ref ud u) { return u.inp_file.ReadByte();// fgetc(u.inp_file); }
/* ============================================================================= * ud_set_sym_resolver * 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. * * The function pointer maybe NULL which resets symbol resolution. * ============================================================================= */ static void ud_set_sym_resolver(ref ud u, UdSymbolResolverDelegate resolver) { u.sym_resolver = resolver; }
static IntPtr ud_get_user_opaque_data(ref ud u) { return u.user_opaque_data; }
/* ============================================================================= * ud_set_pc() - Sets code origin. * ============================================================================= */ /// <summary> /// Set code origin address /// </summary> /// <param name="u"></param> /// <param name="o"></param> public static void ud_set_pc(ref ud u, ulong o) { u.pc = o; }
decode_vex_immreg(ref ud u, ref ud_operand opr, ud_operand_size size) { byte imm = (byte)inp_next(ref u); byte mask = (byte)(u.dis_mode == 64 ? 0xf : 0x7); if (u.error != 0) return u.error; Debug.Assert(u.vex_op != 0); decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(mask & (imm >> 4)), size); return 0; }