udis86: update to current version.

This commit is contained in:
Jérôme Duval 2018-01-13 15:11:21 +01:00
parent 9409021432
commit 0291f00909
11 changed files with 5455 additions and 7445 deletions

View File

@ -27,38 +27,45 @@
#define UD_DECODE_H
#include "types.h"
#include "udint.h"
#include "itab.h"
#define MAX_INSN_LENGTH 15
/* itab prefix bits */
#define P_none ( 0 )
#define P_cast ( 1 << 0 )
#define P_CAST(n) ( ( n >> 0 ) & 1 )
#define P_rexb ( 1 << 1 )
#define P_REXB(n) ( ( n >> 1 ) & 1 )
#define P_inv64 ( 1 << 4 )
#define P_INV64(n) ( ( n >> 4 ) & 1 )
#define P_inv64 ( 1 << 0 )
#define P_INV64(n) ( ( n >> 0 ) & 1 )
#define P_def64 ( 1 << 1 )
#define P_DEF64(n) ( ( n >> 1 ) & 1 )
#define P_oso ( 1 << 2 )
#define P_OSO(n) ( ( n >> 2 ) & 1 )
#define P_aso ( 1 << 3 )
#define P_ASO(n) ( ( n >> 3 ) & 1 )
#define P_rexb ( 1 << 4 )
#define P_REXB(n) ( ( n >> 4 ) & 1 )
#define P_rexw ( 1 << 5 )
#define P_REXW(n) ( ( n >> 5 ) & 1 )
#define P_def64 ( 1 << 7 )
#define P_DEF64(n) ( ( n >> 7 ) & 1 )
#define P_rexr ( 1 << 8 )
#define P_REXR(n) ( ( n >> 8 ) & 1 )
#define P_oso ( 1 << 9 )
#define P_OSO(n) ( ( n >> 9 ) & 1 )
#define P_aso ( 1 << 10 )
#define P_ASO(n) ( ( n >> 10 ) & 1 )
#define P_rexx ( 1 << 11 )
#define P_REXX(n) ( ( n >> 11 ) & 1 )
#define P_ImpAddr ( 1 << 12 )
#define P_IMPADDR(n) ( ( n >> 12 ) & 1 )
#define P_seg ( 1 << 13 )
#define P_SEG(n) ( ( n >> 13 ) & 1 )
#define P_str ( 1 << 14 )
#define P_STR(n) ( ( n >> 14 ) & 1 )
#define P_strz ( 1 << 15 )
#define P_STR_ZF(n) ( ( n >> 15 ) & 1 )
#define P_rexr ( 1 << 6 )
#define P_REXR(n) ( ( n >> 6 ) & 1 )
#define P_rexx ( 1 << 7 )
#define P_REXX(n) ( ( n >> 7 ) & 1 )
#define P_seg ( 1 << 8 )
#define P_SEG(n) ( ( n >> 8 ) & 1 )
#define P_vexl ( 1 << 9 )
#define P_VEXL(n) ( ( n >> 9 ) & 1 )
#define P_vexw ( 1 << 10 )
#define P_VEXW(n) ( ( n >> 10 ) & 1 )
#define P_str ( 1 << 11 )
#define P_STR(n) ( ( n >> 11 ) & 1 )
#define P_strz ( 1 << 12 )
#define P_STR_ZF(n) ( ( n >> 12 ) & 1 )
/* operand type constants -- order is important! */
@ -86,7 +93,8 @@ enum ud_operand_code {
OP_I1, OP_I3, OP_sI,
OP_V, OP_W, OP_Q, OP_P,
OP_U, OP_N, OP_MU,
OP_U, OP_N, OP_MU, OP_H,
OP_L,
OP_R, OP_C, OP_D,
@ -94,57 +102,58 @@ enum ud_operand_code {
} UD_ATTR_PACKED;
/* operand size constants */
/*
* Operand size constants
*
* Symbolic constants for various operand sizes. Some of these constants
* are given a value equal to the width of the data (SZ_B == 8), such
* that they maybe used interchangeably in the internals. Modifying them
* will most certainly break things!
*/
typedef uint16_t ud_operand_size_t;
enum ud_operand_size {
SZ_NA = 0,
SZ_Z = 1,
SZ_V = 2,
SZ_RDQ = 7,
#define SZ_NA 0
#define SZ_Z 1
#define SZ_V 2
#define SZ_Y 3
#define SZ_X 4
#define SZ_RDQ 7
#define SZ_B 8
#define SZ_W 16
#define SZ_D 32
#define SZ_Q 64
#define SZ_T 80
#define SZ_O 12
#define SZ_DQ 128 /* double quad */
#define SZ_QQ 256 /* quad quad */
/* the following values are used as is,
* and thus hard-coded. changing them
* will break internals
*/
SZ_B = 8,
SZ_W = 16,
SZ_D = 32,
SZ_Q = 64,
SZ_T = 80,
SZ_O = 128,
SZ_Y = 17,
/*
* complex size types, that encode sizes for operands
* of type MR (memory or register), for internal use
* only. Id space 256 and above.
*/
SZ_BD = (SZ_B << 8) | SZ_D,
SZ_BV = (SZ_B << 8) | SZ_V,
SZ_WD = (SZ_W << 8) | SZ_D,
SZ_WV = (SZ_W << 8) | SZ_V,
SZ_WY = (SZ_W << 8) | SZ_Y,
SZ_DY = (SZ_D << 8) | SZ_Y,
SZ_WO = (SZ_W << 8) | SZ_O,
SZ_DO = (SZ_D << 8) | SZ_O,
SZ_QO = (SZ_Q << 8) | SZ_O,
} UD_ATTR_PACKED;
/*
* Complex size types; that encode sizes for operands of type MR (memory or
* register); for internal use only. Id space above 256.
*/
#define SZ_BD ((SZ_B << 8) | SZ_D)
#define SZ_BV ((SZ_B << 8) | SZ_V)
#define SZ_WD ((SZ_W << 8) | SZ_D)
#define SZ_WV ((SZ_W << 8) | SZ_V)
#define SZ_WY ((SZ_W << 8) | SZ_Y)
#define SZ_DY ((SZ_D << 8) | SZ_Y)
#define SZ_WO ((SZ_W << 8) | SZ_O)
#define SZ_DO ((SZ_D << 8) | SZ_O)
#define SZ_QO ((SZ_Q << 8) | SZ_O)
/* resolve complex size type.
*/
static inline enum ud_operand_size
Mx_mem_size(enum ud_operand_size size)
static UD_INLINE ud_operand_size_t
Mx_mem_size(ud_operand_size_t size)
{
return (size >> 8) & 0xff;
return (size >> 8) & 0xff;
}
static inline enum ud_operand_size
Mx_reg_size(enum ud_operand_size size)
static UD_INLINE ud_operand_size_t
Mx_reg_size(ud_operand_size_t size)
{
return size & 0xff;
return size & 0xff;
}
/* A single operand of an entry in the instruction table.
@ -153,7 +162,7 @@ Mx_reg_size(enum ud_operand_size size)
struct ud_itab_entry_operand
{
enum ud_operand_code type;
enum ud_operand_size size;
ud_operand_size_t size;
};
@ -166,6 +175,7 @@ struct ud_itab_entry
struct ud_itab_entry_operand operand1;
struct ud_itab_entry_operand operand2;
struct ud_itab_entry_operand operand3;
struct ud_itab_entry_operand operand4;
uint32_t prefix;
};
@ -175,14 +185,6 @@ struct ud_lookup_table_list_entry {
const char *meta;
};
static inline int
ud_opcode_field_sext(uint8_t primary_opcode)
{
return (primary_opcode & 0x02) != 0;
}
extern struct ud_itab_entry ud_itab[];
extern struct ud_lookup_table_list_entry ud_lookup_table_list[];

View File

@ -32,67 +32,75 @@ extern "C" {
#include "types.h"
#if defined(_MSC_VER) && defined(_USRDLL)
# ifdef LIBUDIS86_EXPORTS
# define LIBUDIS86_DLLEXTERN __declspec(dllexport)
# else
# define LIBUDIS86_DLLEXTERN __declspec(dllimport)
# endif
#else
# define LIBUDIS86_DLLEXTERN
#endif
/* ============================= PUBLIC API ================================= */
extern void ud_init(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*);
extern void ud_set_mode(struct ud*, uint8_t);
extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t);
extern void ud_set_pc(struct ud*, uint64_t);
extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t);
extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern void ud_set_input_file(struct ud*, FILE*);
extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern void ud_set_vendor(struct ud*, unsigned);
extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned);
extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern void ud_input_skip(struct ud*, size_t);
extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t);
extern int ud_input_end(const struct ud*);
extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*);
extern unsigned int ud_decode(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*);
extern unsigned int ud_disassemble(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*);
extern void ud_translate_intel(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*);
extern void ud_translate_att(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*);
extern const char* ud_insn_asm(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u);
extern const uint8_t* ud_insn_ptr(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u);
extern uint64_t ud_insn_off(const struct ud*);
extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*);
extern const char* ud_insn_hex(struct ud*);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*);
extern unsigned int ud_insn_len(const struct ud* u);
extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u);
extern const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
extern int ud_opr_is_sreg(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr);
extern int ud_opr_is_gpr(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr);
extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
extern void ud_set_user_opaque_data(struct ud*, void*);
extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*);
extern void* ud_get_user_opaque_data(const struct ud*);
extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*);
extern uint64_t ud_insn_sext_imm(const struct ud*, const struct ud_operand*);
extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
extern void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
extern void ud_set_sym_resolver(struct ud *u,
extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u,
const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset));

File diff suppressed because it is too large Load Diff

View File

@ -27,27 +27,25 @@
#define UD_TYPES_H
#ifdef __KERNEL__
/* -D__KERNEL__ is automatically passed on the command line when
building something as part of the Linux kernel */
/*
* -D__KERNEL__ is automatically passed on the command line when
* building something as part of the Linux kernel. Assume standalone
* mode.
*/
# include <linux/kernel.h>
# include <linux/string.h>
# ifndef __UD_STANDALONE__
# define __UD_STANDALONE__ 1
#endif
# endif
#endif /* __KERNEL__ */
#if defined(_MSC_VER) || defined(__BORLANDC__)
#if !defined(__UD_STANDALONE__) || defined(__HAIKU__)
# include <stdint.h>
# include <stdio.h>
# define inline __inline /* MS Visual Studio requires __inline
instead of inline for C code */
#elif !defined(__UD_STANDALONE__) || defined(__HAIKU__)
# include <stdio.h>
# include <inttypes.h>
#endif /* !__UD_STANDALONE__ */
#endif
/* gcc specific extensions */
#if defined(__GNUC__) && __GNUC__ > 2
#ifdef __GNUC__
# define UD_ATTR_PACKED __attribute__((packed))
#else
# define UD_ATTR_PACKED
@ -117,6 +115,12 @@ enum ud_type
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
/* 256B multimedia registers */
UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3,
UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7,
UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11,
UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15,
UD_R_RIP,
/* Operand Types */
@ -147,7 +151,7 @@ union ud_lval {
*/
struct ud_operand {
enum ud_type type;
uint8_t size;
uint16_t size;
enum ud_type base;
enum ud_type index;
uint8_t scale;
@ -180,6 +184,7 @@ struct ud
size_t inp_ctr;
uint8_t inp_sess[64];
int inp_end;
int inp_peek;
void (*translator)(struct ud*);
uint64_t insn_offset;
@ -202,8 +207,9 @@ struct ud
uint64_t pc;
uint8_t vendor;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[3];
struct ud_operand operand[4];
uint8_t error;
uint8_t _rex;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
@ -219,6 +225,10 @@ struct ud
uint8_t br_near;
uint8_t have_modrm;
uint8_t modrm;
uint8_t modrm_offset;
uint8_t vex_op;
uint8_t vex_b1;
uint8_t vex_b2;
uint8_t primary_opcode;
void * user_opaque_data;
struct ud_itab_entry * itab_entry;

View File

@ -26,6 +26,8 @@
#ifndef _UDINT_H_
#define _UDINT_H_
#include "types.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
@ -86,4 +88,12 @@
# endif /* !x64 */
#endif
/* define an inline macro */
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define UD_INLINE __inline /* MS Visual Studio requires __inline
instead of inline for C code */
#else
# define UD_INLINE inline
#endif
#endif /* _UDINT_H_ */

View File

@ -56,6 +56,7 @@
#define MODRM_RM(b) ( ( b ) & 7 )
static int decode_ext(struct ud *u, uint16_t ptr);
static int decode_opcode(struct ud *u);
enum reg_class { /* register classes */
REGCLASS_GPR,
@ -76,6 +77,28 @@ inp_start(struct ud *u)
u->inp_ctr = 0;
}
static uint8_t
inp_peek(struct 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(u)) != UD_EOI) {
u->inp_peek = c;
return u->inp_peek;
}
}
}
u->inp_end = 1;
UDERR(u, "byte expected, eoi received\n");
return 0;
}
static uint8_t
inp_next(struct ud *u)
@ -87,8 +110,9 @@ inp_next(struct ud *u)
return (u->inp_curr = u->inp_buf[u->inp_buf_index++]);
}
} else {
int c;
if ((c = u->inp_hook(u)) != UD_EOI) {
int c = u->inp_peek;
if (c != UD_EOI || (c = u->inp_hook(u)) != UD_EOI) {
u->inp_peek = UD_EOI;
u->inp_curr = c;
u->inp_sess[u->inp_ctr++] = u->inp_curr;
return u->inp_curr;
@ -167,7 +191,7 @@ inp_uint64(struct ud* u)
}
static inline int
static UD_INLINE int
eff_opr_mode(int dis_mode, int rex_w, int pfx_opr)
{
if (dis_mode == 64) {
@ -181,7 +205,7 @@ eff_opr_mode(int dis_mode, int rex_w, int pfx_opr)
}
static inline int
static UD_INLINE int
eff_adr_mode(int dis_mode, int pfx_adr)
{
if (dis_mode == 64) {
@ -204,7 +228,7 @@ static int
decode_prefixes(struct ud *u)
{
int done = 0;
uint8_t curr, last = 0;
uint8_t curr = 0, last = 0;
UD_RETURN_ON_ERROR(u);
do {
@ -264,10 +288,31 @@ decode_prefixes(struct ud *u)
}
static inline unsigned int modrm( struct ud * u )
/*
* vex_l, vex_w
* Return the vex.L and vex.W bits
*/
static UD_INLINE uint8_t
vex_l(const struct ud *u)
{
UD_ASSERT(u->vex_op != 0);
return ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 2) & 1;
}
static UD_INLINE uint8_t
vex_w(const struct ud *u)
{
UD_ASSERT(u->vex_op != 0);
return u->vex_op == 0xc4 ? ((u->vex_b2 >> 7) & 1) : 0;
}
static UD_INLINE uint8_t
modrm(struct ud * u)
{
if ( !u->have_modrm ) {
u->modrm = inp_next( u );
u->modrm_offset = (uint8_t) (u->inp_ctr - 1);
u->have_modrm = 1;
}
return u->modrm;
@ -275,21 +320,23 @@ static inline unsigned int modrm( struct ud * u )
static unsigned int
resolve_operand_size( const struct ud * u, unsigned int s )
resolve_operand_size(const struct ud* u, ud_operand_size_t osize)
{
switch ( s )
{
case SZ_V:
return ( u->opr_mode );
case SZ_Z:
return ( u->opr_mode == 16 ) ? 16 : 32;
case SZ_Y:
return ( u->opr_mode == 16 ) ? 32 : u->opr_mode;
case SZ_RDQ:
return ( u->dis_mode == 64 ) ? 64 : 32;
default:
return s;
}
switch (osize) {
case SZ_V:
return u->opr_mode;
case SZ_Z:
return u->opr_mode == 16 ? 16 : 32;
case SZ_Y:
return u->opr_mode == 16 ? 32 : u->opr_mode;
case SZ_RDQ:
return u->dis_mode == 64 ? 64 : 32;
case SZ_X:
UD_ASSERT(u->vex_op != 0);
return (P_VEXL(u->itab_entry->prefix) && vex_l(u)) ? SZ_QQ : SZ_DQ;
default:
return osize;
}
}
@ -388,7 +435,9 @@ decode_reg(struct ud *u,
switch (type) {
case REGCLASS_GPR : reg = decode_gpr(u, size, num); break;
case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break;
case REGCLASS_XMM : reg = UD_R_XMM0 + num; break;
case REGCLASS_XMM :
reg = num + (size == SZ_QQ ? UD_R_YMM0 : UD_R_XMM0);
break;
case REGCLASS_CR : reg = UD_R_CR0 + num; break;
case REGCLASS_DB : reg = UD_R_DR0 + num; break;
case REGCLASS_SEG : {
@ -471,13 +520,13 @@ decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op)
* Decodes reg field of mod/rm byte
*
*/
static inline void
static UD_INLINE void
decode_modrm_reg(struct ud *u,
struct ud_operand *operand,
unsigned int type,
unsigned int size)
{
uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u));
uint8_t reg = (REX_R(u->_rex) << 3) | MODRM_REG(modrm(u));
decode_reg(u, operand, type, reg, size);
}
@ -500,7 +549,7 @@ decode_modrm_rm(struct ud *u,
/* get mod, r/m and reg fields */
mod = MODRM_MOD(modrm(u));
rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u));
rm = (REX_B(u->_rex) << 3) | MODRM_RM(modrm(u));
/*
* If mod is 11b, then the modrm.rm specifies a register.
@ -535,14 +584,14 @@ decode_modrm_rm(struct ud *u,
if ((rm & 7) == 4) {
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));
op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->_rex) << 3));
op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->_rex) << 3));
/* special conditions for base reference */
if (op->index == UD_R_RSP) {
op->index = UD_NONE;
op->scale = UD_NONE;
} else {
op->scale = (1 << SIB_S(inp_curr(u))) & ~1;
}
if (op->base == UD_R_RBP || op->base == UD_R_R13) {
@ -555,6 +604,9 @@ decode_modrm_rm(struct ud *u,
offset = 32;
}
}
} else {
op->scale = UD_NONE;
op->index = UD_NONE;
}
} else if (u->adr_mode == 32) {
op->base = UD_R_EAX + rm;
@ -593,6 +645,9 @@ decode_modrm_rm(struct ud *u,
offset = 32;
}
}
} else {
op->scale = UD_NONE;
op->index = UD_NONE;
}
} else {
const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP,
@ -601,6 +656,7 @@ decode_modrm_rm(struct ud *u,
UD_NONE, UD_NONE, UD_NONE, UD_NONE };
op->base = bases[rm & 7];
op->index = indices[rm & 7];
op->scale = UD_NONE;
if (mod == 0 && rm == 6) {
offset = 16;
op->base = UD_NONE;
@ -613,6 +669,8 @@ decode_modrm_rm(struct ud *u,
if (offset) {
decode_mem_disp(u, offset, op);
} else {
op->offset = 0;
}
}
@ -624,15 +682,46 @@ decode_modrm_rm(struct ud *u,
static void
decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr)
{
opr->type = UD_OP_MEM;
opr->size = resolve_operand_size(u, size);
opr->type = UD_OP_MEM;
opr->base = UD_NONE;
opr->index = UD_NONE;
opr->scale = UD_NONE;
opr->size = resolve_operand_size(u, size);
decode_mem_disp(u, u->adr_mode, opr);
}
/* -----------------------------------------------------------------------------
* decode_operands() - Disassembles Operands.
* -----------------------------------------------------------------------------
static void
decode_vex_vvvv(struct ud *u, struct ud_operand *opr, unsigned size)
{
uint8_t vvvv;
UD_ASSERT(u->vex_op != 0);
vvvv = ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 3) & 0xf;
decode_reg(u, opr, REGCLASS_XMM, (0xf & ~vvvv), size);
}
/*
* decode_vex_immreg
* Decode source operand encoded in immediate byte [7:4]
*/
static int
decode_vex_immreg(struct ud *u, struct ud_operand *opr, unsigned size)
{
uint8_t imm = inp_next(u);
uint8_t mask = u->dis_mode == 64 ? 0xf : 0x7;
UD_RETURN_ON_ERROR(u);
UD_ASSERT(u->vex_op != 0);
decode_reg(u, opr, REGCLASS_XMM, mask & (imm >> 4), size);
return 0;
}
/*
* decode_operand
*
* Decodes a single operand.
* Returns the type of the operand (UD_NONE if none)
*/
static int
decode_operand(struct ud *u,
@ -640,6 +729,7 @@ decode_operand(struct ud *u,
enum ud_operand_code type,
unsigned int size)
{
operand->type = UD_NONE;
operand->_oprcode = type;
switch (type) {
@ -695,6 +785,9 @@ decode_operand(struct ud *u,
case OP_V:
decode_modrm_reg(u, operand, REGCLASS_XMM, size);
break;
case OP_H:
decode_vex_vvvv(u, operand, size);
break;
case OP_MU:
decode_modrm_rm(u, operand, REGCLASS_XMM,
MODRM_MOD(modrm(u)) == 3 ?
@ -715,7 +808,7 @@ decode_operand(struct ud *u,
case OP_R6:
case OP_R7:
decode_reg(u, operand, REGCLASS_GPR,
(REX_B(u->pfx_rex) << 3) | (type - OP_R0), size);
(REX_B(u->_rex) << 3) | (type - OP_R0), size);
break;
case OP_AL:
case OP_AX:
@ -781,10 +874,14 @@ decode_operand(struct ud *u,
operand->base = (type - OP_ST0) + UD_R_ST0;
operand->size = 80;
break;
case OP_L:
decode_vex_immreg(u, operand, size);
break;
default :
operand->type = UD_NONE;
break;
}
return 0;
return operand->type;
}
@ -801,12 +898,21 @@ decode_operands(struct ud* u)
decode_operand(u, &u->operand[0],
u->itab_entry->operand1.type,
u->itab_entry->operand1.size);
decode_operand(u, &u->operand[1],
u->itab_entry->operand2.type,
u->itab_entry->operand2.size);
decode_operand(u, &u->operand[2],
u->itab_entry->operand3.type,
u->itab_entry->operand3.size);
if (u->operand[0].type != UD_NONE) {
decode_operand(u, &u->operand[1],
u->itab_entry->operand2.type,
u->itab_entry->operand2.size);
}
if (u->operand[1].type != UD_NONE) {
decode_operand(u, &u->operand[2],
u->itab_entry->operand3.type,
u->itab_entry->operand3.size);
}
if (u->operand[2].type != UD_NONE) {
decode_operand(u, &u->operand[3],
u->itab_entry->operand4.type,
u->itab_entry->operand4.size);
}
return 0;
}
@ -831,14 +937,16 @@ clear_insn(register struct ud* u)
u->itab_entry = NULL;
u->have_modrm = 0;
u->br_far = 0;
memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) );
memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) );
memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) );
u->vex_op = 0;
u->_rex = 0;
u->operand[0].type = UD_NONE;
u->operand[1].type = UD_NONE;
u->operand[2].type = UD_NONE;
u->operand[3].type = UD_NONE;
}
static inline int
static UD_INLINE int
resolve_pfx_str(struct ud* u)
{
if (u->pfx_str == 0xf3) {
@ -870,18 +978,30 @@ resolve_mode( struct ud* u )
return -1;
}
/* effective rex prefix is the effective mask for the
* instruction hard-coded in the opcode map.
/* compute effective rex based on,
* - vex prefix (if any)
* - rex prefix (if any, and not vex)
* - allowed prefixes specified by the opcode map
*/
u->pfx_rex = ( u->pfx_rex & 0x40 ) |
( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) );
if (u->vex_op == 0xc4) {
/* vex has rex.rxb in 1's complement */
u->_rex = ((~(u->vex_b1 >> 5) & 0x7) /* rex.0rxb */ |
((u->vex_b2 >> 4) & 0x8) /* rex.w000 */);
} else if (u->vex_op == 0xc5) {
/* vex has rex.r in 1's complement */
u->_rex = (~(u->vex_b1 >> 5)) & 4;
} else {
UD_ASSERT(u->vex_op == 0);
u->_rex = u->pfx_rex;
}
u->_rex &= REX_PFX_MASK(u->itab_entry->prefix);
/* whether this instruction has a default operand size of
* 64bit, also hardcoded into the opcode map.
*/
default64 = P_DEF64( u->itab_entry->prefix );
/* calculate effective operand size */
if ( REX_W( u->pfx_rex ) ) {
if (REX_W(u->_rex)) {
u->opr_mode = 64;
} else if ( u->pfx_opr ) {
u->opr_mode = 16;
@ -907,7 +1027,7 @@ resolve_mode( struct ud* u )
}
static inline int
static UD_INLINE int
decode_insn(struct ud *u, uint16_t ptr)
{
UD_ASSERT((ptr & 0x8000) == 0);
@ -931,7 +1051,7 @@ decode_insn(struct ud *u, uint16_t ptr)
* valid entry in the table, decode the operands, and read the final
* byte to resolve the menmonic.
*/
static inline int
static UD_INLINE int
decode_3dnow(struct ud* u)
{
uint16_t ptr;
@ -986,6 +1106,36 @@ decode_ssepfx(struct ud *u)
}
static int
decode_vex(struct ud *u)
{
uint8_t index;
if (u->dis_mode != 64 && MODRM_MOD(inp_peek(u)) != 0x3) {
index = 0;
} else {
u->vex_op = inp_curr(u);
u->vex_b1 = inp_next(u);
if (u->vex_op == 0xc4) {
uint8_t pp, m;
/* 3-byte vex */
u->vex_b2 = inp_next(u);
UD_RETURN_ON_ERROR(u);
m = u->vex_b1 & 0x1f;
if (m == 0 || m > 3) {
UD_RETURN_WITH_ERROR(u, "reserved vex.m-mmmm value");
}
pp = u->vex_b2 & 0x3;
index = (pp << 2) | m;
} else {
/* 2-byte vex */
UD_ASSERT(u->vex_op == 0xc5);
index = 0x1 | ((u->vex_b1 & 0x3) << 2);
}
}
return decode_ext(u, u->le->table[index]);
}
/*
* decode_ext()
*
@ -1041,6 +1191,17 @@ decode_ext(struct ud *u, uint16_t ptr)
break;
case UD_TAB__OPC_SSE:
return decode_ssepfx(u);
case UD_TAB__OPC_VEX:
return decode_vex(u);
case UD_TAB__OPC_VEX_W:
idx = vex_w(u);
break;
case UD_TAB__OPC_VEX_L:
idx = vex_l(u);
break;
case UD_TAB__OPC_TABLE:
inp_next(u);
return decode_opcode(u);
default:
UD_ASSERT(!"not reached");
break;
@ -1056,15 +1217,7 @@ decode_opcode(struct ud *u)
uint16_t ptr;
UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE);
UD_RETURN_ON_ERROR(u);
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) {
inp_next(u);
return decode_opcode(u);
}
}
return decode_ext(u, ptr);
}

File diff suppressed because it is too large Load Diff

View File

@ -157,7 +157,7 @@ ud_translate_att(struct ud *u)
ud_asmprintf(u, "lock ");
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_rep) {
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
@ -192,12 +192,13 @@ ud_translate_att(struct ud *u)
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
if (size == 8)
ud_asmprintf(u, "b");
else if (size == 16)
ud_asmprintf(u, "w");
else if (size == 64)
ud_asmprintf(u, "q");
if (size == 8) {
ud_asmprintf(u, "b");
} else if (size == 16) {
ud_asmprintf(u, "w");
} else if (size == 64) {
ud_asmprintf(u, "q");
}
if (star) {
ud_asmprintf(u, " *");
@ -205,18 +206,21 @@ ud_translate_att(struct ud *u)
ud_asmprintf(u, " ");
}
if (u->operand[3].type != UD_NONE) {
gen_operand(u, &u->operand[3]);
ud_asmprintf(u, ", ");
}
if (u->operand[2].type != UD_NONE) {
gen_operand(u, &u->operand[2]);
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[2]);
ud_asmprintf(u, ", ");
}
if (u->operand[1].type != UD_NONE) {
gen_operand(u, &u->operand[1]);
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[1]);
ud_asmprintf(u, ", ");
}
if (u->operand[0].type != UD_NONE) {
gen_operand(u, &u->operand[0]);
}
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
}
/*

View File

@ -41,11 +41,13 @@ opr_cast(struct ud* u, struct ud_operand* op)
ud_asmprintf(u, "far ");
}
switch(op->size) {
case 8: ud_asmprintf(u, "byte " ); break;
case 16: ud_asmprintf(u, "word " ); break;
case 32: ud_asmprintf(u, "dword "); break;
case 64: ud_asmprintf(u, "qword "); break;
case 80: ud_asmprintf(u, "tword "); break;
case 8: ud_asmprintf(u, "byte " ); break;
case 16: ud_asmprintf(u, "word " ); break;
case 32: ud_asmprintf(u, "dword "); break;
case 64: ud_asmprintf(u, "qword "); break;
case 80: ud_asmprintf(u, "tword "); break;
case 128: ud_asmprintf(u, "oword "); break;
case 256: ud_asmprintf(u, "yword "); break;
default: break;
}
}
@ -169,8 +171,7 @@ ud_translate_intel(struct ud* u)
if (u->operand[1].type == UD_OP_IMM ||
u->operand[1].type == UD_OP_CONST ||
u->operand[1].type == UD_NONE ||
(u->operand[0].size != u->operand[1].size &&
u->operand[1].type != UD_OP_REG)) {
(u->operand[0].size != u->operand[1].size)) {
cast = 1;
} else if (u->operand[1].type == UD_OP_REG &&
u->operand[1].base == UD_R_CL) {
@ -203,8 +204,18 @@ ud_translate_intel(struct ud* u)
}
if (u->operand[2].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[2], 0);
if (u->operand[2].type == UD_OP_MEM &&
u->operand[2].size != u->operand[1].size) {
cast = 1;
}
gen_operand(u, &u->operand[2], cast);
}
if (u->operand[3].type != UD_NONE) {
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[3], 0);
}
}

View File

@ -28,56 +28,61 @@
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* Intel Register Table - Order Matters (types.h)!
* -----------------------------------------------------------------------------
/*
* Register Table - Order Matters (types.h)!
*
*/
const char* ud_reg_tab[] =
{
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w" , "r14w", "r15w",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w", "r14w", "r15w",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"es", "cs", "ss", "ds",
"fs", "gs",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"ymm0", "ymm1", "ymm2", "ymm3",
"ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11",
"ymm12", "ymm13", "ymm14", "ymm15",
"rip"
};

View File

@ -214,7 +214,7 @@ ud_insn_len(const struct ud* u)
const struct ud_operand*
ud_insn_opr(const struct ud *u, unsigned int n)
{
if (n > 2 || u->operand[n].type == UD_NONE) {
if (n > 3 || u->operand[n].type == UD_NONE) {
return NULL;
} else {
return &u->operand[n];
@ -355,6 +355,7 @@ ud_inp_init(struct ud *u)
u->inp_curr = 0;
u->inp_ctr = 0;
u->inp_end = 0;
u->inp_peek = UD_EOI;
UD_NON_STANDALONE(u->inp_file = NULL);
}