extern uint16_t ud_inp_uint16(struct ud* u) { uint16_t r, ret; ret = ud_inp_next(u); r = ud_inp_next(u); return ret | (r << 8); }
extern uint32_t ud_inp_uint32(struct ud* u) { uint32_t r, ret; ret = ud_inp_next(u); r = ud_inp_next(u); ret = ret | (r << 8); r = ud_inp_next(u); ret = ret | (r << 16); r = ud_inp_next(u); return ret | (r << 24); }
/* ----------------------------------------------------------------------------- * ud_inp_peek() - Peek into the next byte in source. * ----------------------------------------------------------------------------- */ extern uint8_t ud_inp_peek(struct ud* u) { uint8_t r = ud_inp_next(u); if ( !u->error ) ud_inp_back(u); /* Don't backup if there was an error */ return r; }
static inline unsigned int modrm( struct ud * u ) { if ( !u->have_modrm ) { u->modrm = ud_inp_next( u ); u->have_modrm = 1; } return u->modrm; }
/* * decode_3dnow() * * Decoding 3dnow is a little tricky because of its strange opcode * structure. The final opcode disambiguation depends on the last * byte that comes after the operands have been decoded. Fortunately, * all 3dnow instructions have the same set of operand types. So we * go ahead and decode the instruction by picking an arbitrarily chosen * valid entry in the table, decode the operands, and read the final * byte to resolve the menmonic. */ static inline int decode_3dnow(struct ud* u) { uint16_t ptr; UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); UD_ASSERT(u->le->table[0xc] != 0); decode_insn(u, u->le->table[0xc]); ud_inp_next(u); if (u->error) { return -1; } ptr = u->le->table[inp_curr(u)]; UD_ASSERT((ptr & 0x8000) == 0); u->mnemonic = ud_itab[ptr].mnemonic; return 0; }
extern uint64_t ud_inp_uint64(struct ud* u) { uint64_t r, ret; ret = ud_inp_next(u); r = ud_inp_next(u); ret = ret | (r << 8); r = ud_inp_next(u); ret = ret | (r << 16); r = ud_inp_next(u); ret = ret | (r << 24); r = ud_inp_next(u); ret = ret | (r << 32); r = ud_inp_next(u); ret = ret | (r << 40); r = ud_inp_next(u); ret = ret | (r << 48); r = ud_inp_next(u); return ret | (r << 56); }
static int decode_opcode(struct ud *u) { uint16_t ptr; UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); ud_inp_next(u); if (u->error) { return -1; } u->primary_opcode = inp_curr(u); ptr = u->le->table[inp_curr(u)]; if (ptr & 0x8000) { u->le = &ud_lookup_table_list[ptr & ~0x8000]; if (u->le->type == UD_TAB__OPC_TABLE) { return decode_opcode(u); } } return decode_ext(u, ptr); }
/*------------------------------------------------------------------------------ * ud_inp_uintN() - return uintN from source. *------------------------------------------------------------------------------ */ extern uint8_t ud_inp_uint8(struct ud* u) { return ud_inp_next(u); }
/* ----------------------------------------------------------------------------- * ud_inp_move() - Move ahead n input bytes. * ----------------------------------------------------------------------------- */ extern void ud_inp_move(struct ud* u, size_t n) { while (n--) ud_inp_next(u); }
/* * inp_uint8 * int_uint16 * int_uint32 * int_uint64 * Load little-endian values from input */ static uint8_t inp_uint8(struct ud* u) { return ud_inp_next(u); }
/* * decode_modrm_rm * * Decodes rm field of mod/rm byte * */ static void decode_modrm_rm(struct ud *u, struct ud_operand *op, unsigned char type, /* register type */ unsigned int size) /* operand size */ { size_t offset = 0; unsigned char mod, rm; /* get mod, r/m and reg fields */ mod = MODRM_MOD(modrm(u)); rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); /* * If mod is 11b, then the modrm.rm specifies a register. * */ if (mod == 3) { decode_reg(u, op, type, rm, size); return; } /* * !11b => Memory Address */ op->type = UD_OP_MEM; op->size = resolve_operand_size(u, size); if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; offset = 32; } else { offset = 0; } /* * Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { ud_inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else if (u->adr_mode == 32) { op->base = UD_R_EAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && rm == 5) { op->base = UD_NONE; offset = 32; } else { offset = 0; } /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { ud_inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; op->scale = UD_NONE; } /* special condition for base reference */ if (op->base == UD_R_EBP) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else { const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, UD_NONE, UD_NONE, UD_NONE, UD_NONE }; op->base = bases[rm & 7]; op->index = indices[rm & 7]; if (mod == 0 && rm == 6) { offset = 16; op->base = UD_NONE; } else if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 16; } } if (offset) { decode_mem_disp(u, (unsigned int)offset, op); } }
/* * decode_prefixes * * Extracts instruction prefixes. */ static int decode_prefixes(struct ud *u) { int done = 0; uint8_t curr; UD_RETURN_ON_ERROR(u); do { ud_inp_next(u); UD_RETURN_ON_ERROR(u); if (inp_len(u) == MAX_INSN_LENGTH) { UD_RETURN_WITH_ERROR(u, "max instruction length"); } curr = inp_curr(u); switch (curr) { case 0x2E : u->pfx_seg = UD_R_CS; break; case 0x36 : u->pfx_seg = UD_R_SS; break; case 0x3E : u->pfx_seg = UD_R_DS; break; case 0x26 : u->pfx_seg = UD_R_ES; break; case 0x64 : u->pfx_seg = UD_R_FS; break; case 0x65 : u->pfx_seg = UD_R_GS; break; case 0x67 : /* adress-size override prefix */ u->pfx_adr = 0x67; break; case 0xF0 : u->pfx_lock = 0xF0; break; case 0x66: u->pfx_opr = 0x66; break; case 0xF2: u->pfx_str = 0xf2; break; case 0xF3: u->pfx_str = 0xf3; break; default: done = 1; break; } } while (!done); if (u->dis_mode == 64 && (curr & 0xF0) == 0x40) { /* rex prefixes in 64bit mode, must be the last prefix */ u->pfx_rex = curr; } else { /* rewind back one byte in stream, since the above loop * stops with a non-prefix byte. */ inp_back(u); } return 0; }