| Index: src/third_party/libdisasm/x86_format.c
|
| diff --git a/src/third_party/libdisasm/x86_format.c b/src/third_party/libdisasm/x86_format.c
|
| deleted file mode 100644
|
| index 0ec960dc8f06df2b6c36134d916eb9f7a9310774..0000000000000000000000000000000000000000
|
| --- a/src/third_party/libdisasm/x86_format.c
|
| +++ /dev/null
|
| @@ -1,1430 +0,0 @@
|
| -#include <stdio.h>
|
| -#include <stdlib.h>
|
| -#include <string.h>
|
| -
|
| -#include "libdis.h"
|
| -#include <inttypes.h>
|
| -
|
| -#ifdef _MSC_VER
|
| - #define snprintf _snprintf
|
| - #define inline __inline
|
| -#endif
|
| -
|
| -
|
| -/*
|
| - * concatenation macros. STRNCATF concatenates a format string, buf
|
| - * only with one argument.
|
| - */
|
| -#define STRNCAT( buf, str, len ) do { \
|
| - int _i = strlen(str), _blen = strlen(buf), _len = len - 1; \
|
| - if ( len ) { \
|
| - strncat( buf, str, _len ); \
|
| - if ( _len <= _i ) { \
|
| - buf[_blen+_len] = '\0'; \
|
| - len = 0; \
|
| - } else { \
|
| - len -= _i; \
|
| - } \
|
| - } \
|
| -} while( 0 )
|
| -
|
| -#define STRNCATF( buf, fmt, data, len ) do { \
|
| - char _tmp[MAX_OP_STRING]; \
|
| - \
|
| - snprintf( _tmp, sizeof _tmp, fmt, data ); \
|
| - STRNCAT( buf, _tmp, len ); \
|
| -} while( 0 )
|
| -
|
| -
|
| -#define PRINT_DISPLACEMENT( ea ) do { \
|
| - if ( ea->disp_size && ea->disp ) { \
|
| - if ( ea->disp_sign ) { \
|
| - STRNCATF( buf, "-0x%" PRIX32, -ea->disp, len ); \
|
| - } else { \
|
| - STRNCATF( buf, "0x%" PRIX32, ea->disp, len ); \
|
| - } \
|
| - } \
|
| -} while( 0 )
|
| -
|
| -static const char *prefix_strings[] = {
|
| - "", /* no prefix */
|
| - "repz ", /* the trailing spaces make it easy to prepend to mnemonic */
|
| - "repnz ",
|
| - "lock ",
|
| - "branch delay " /* unused in x86 */
|
| -};
|
| -
|
| -static int format_insn_prefix_str( enum x86_insn_prefix prefix, char *buf,
|
| - int len ) {
|
| -
|
| - int len_orig = len;
|
| -
|
| - /* concat all prefix strings */
|
| - if ( prefix & 1 ) { STRNCAT( buf, prefix_strings[1], len ); }
|
| - if ( prefix & 2 ) { STRNCAT( buf, prefix_strings[2], len ); }
|
| - if ( prefix & 4 ) { STRNCAT( buf, prefix_strings[3], len ); }
|
| - if ( prefix & 8 ) { STRNCAT( buf, prefix_strings[4], len ); }
|
| -
|
| - /* return the number of characters added */
|
| - return (len_orig - len);
|
| -}
|
| -
|
| -/*
|
| - * sprint's an operand's data to string str.
|
| - */
|
| -static void get_operand_data_str( x86_op_t *op, char *str, int len ){
|
| -
|
| - if ( op->flags & op_signed ) {
|
| - switch ( op->datatype ) {
|
| - case op_byte:
|
| - snprintf( str, len, "%" PRId8, op->data.sbyte );
|
| - return;
|
| - case op_word:
|
| - snprintf( str, len, "%" PRId16, op->data.sword );
|
| - return;
|
| - case op_qword:
|
| - snprintf( str, len, "%" PRId64, op->data.sqword );
|
| - return;
|
| - default:
|
| - snprintf( str, len, "%" PRId32, op->data.sdword );
|
| - return;
|
| - }
|
| - }
|
| -
|
| - //else
|
| - switch ( op->datatype ) {
|
| - case op_byte:
|
| - snprintf( str, len, "0x%02" PRIX8, op->data.byte );
|
| - return;
|
| - case op_word:
|
| - snprintf( str, len, "0x%04" PRIX16, op->data.word );
|
| - return;
|
| - case op_qword:
|
| - snprintf( str, len, "0x%08" PRIX64,op->data.sqword );
|
| - return;
|
| - default:
|
| - snprintf( str, len, "0x%08" PRIX32, op->data.dword );
|
| - return;
|
| - }
|
| -}
|
| -
|
| -/*
|
| - * sprints register types to a string. the register types can be ORed
|
| - * together.
|
| - */
|
| -static void get_operand_regtype_str( int regtype, char *str, int len )
|
| -{
|
| - static struct {
|
| - const char *name;
|
| - int value;
|
| - } operand_regtypes[] = {
|
| - {"reg_gen" , 0x00001},
|
| - {"reg_in" , 0x00002},
|
| - {"reg_out" , 0x00004},
|
| - {"reg_local" , 0x00008},
|
| - {"reg_fpu" , 0x00010},
|
| - {"reg_seg" , 0x00020},
|
| - {"reg_simd" , 0x00040},
|
| - {"reg_sys" , 0x00080},
|
| - {"reg_sp" , 0x00100},
|
| - {"reg_fp" , 0x00200},
|
| - {"reg_pc" , 0x00400},
|
| - {"reg_retaddr", 0x00800},
|
| - {"reg_cond" , 0x01000},
|
| - {"reg_zero" , 0x02000},
|
| - {"reg_ret" , 0x04000},
|
| - {"reg_src" , 0x10000},
|
| - {"reg_dest" , 0x20000},
|
| - {"reg_count" , 0x40000},
|
| - {NULL, 0}, //end
|
| - };
|
| -
|
| - unsigned int i;
|
| -
|
| - memset( str, 0, len );
|
| -
|
| - //go thru every type in the enum
|
| - for ( i = 0; operand_regtypes[i].name; i++ ) {
|
| - //skip if type is not set
|
| - if(! (regtype & operand_regtypes[i].value) )
|
| - continue;
|
| -
|
| - //not the first time around
|
| - if( str[0] ) {
|
| - STRNCAT( str, " ", len );
|
| - }
|
| -
|
| - STRNCAT(str, operand_regtypes[i].name, len );
|
| - }
|
| -}
|
| -
|
| -static int format_expr( x86_ea_t *ea, char *buf, int len,
|
| - enum x86_asm_format format ) {
|
| - char str[MAX_OP_STRING];
|
| -
|
| - if ( format == att_syntax ) {
|
| - if (ea->base.name[0] || ea->index.name[0] || ea->scale) {
|
| - PRINT_DISPLACEMENT(ea);
|
| - STRNCAT( buf, "(", len );
|
| -
|
| - if ( ea->base.name[0]) {
|
| - STRNCATF( buf, "%%%s", ea->base.name, len );
|
| - }
|
| - if ( ea->index.name[0]) {
|
| - STRNCATF( buf, ",%%%s", ea->index.name, len );
|
| - if ( ea->scale > 1 ) {
|
| - STRNCATF( buf, ",%d", ea->scale, len );
|
| - }
|
| - }
|
| - /* handle the syntactic exception */
|
| - if ( ! ea->base.name[0] &&
|
| - ! ea->index.name[0] ) {
|
| - STRNCATF( buf, ",%d", ea->scale, len );
|
| - }
|
| -
|
| - STRNCAT( buf, ")", len );
|
| - } else
|
| - STRNCATF( buf, "0x%" PRIX32, ea->disp, len );
|
| -
|
| - } else if ( format == xml_syntax ){
|
| -
|
| - if ( ea->base.name[0]) {
|
| - STRNCAT (buf, "\t\t\t<base>\n", len);
|
| -
|
| - get_operand_regtype_str (ea->base.type, str,
|
| - sizeof str);
|
| - STRNCAT (buf, "\t\t\t\t<register ", len);
|
| - STRNCATF (buf, "name=\"%s\" ", ea->base.name, len);
|
| - STRNCATF (buf, "type=\"%s\" ", str, len);
|
| - STRNCATF (buf, "size=%d/>\n", ea->base.size, len);
|
| -
|
| - STRNCAT (buf, "\t\t\t</base>\n", len);
|
| - }
|
| -
|
| - if ( ea->index.name[0]) {
|
| - STRNCAT (buf, "\t\t\t<index>\n", len);
|
| -
|
| - get_operand_regtype_str (ea->index.type, str,
|
| - sizeof str);
|
| -
|
| - STRNCAT (buf, "\t\t\t\t<register ", len);
|
| - STRNCATF (buf, "name=\"%s\" ", ea->index.name, len);
|
| - STRNCATF (buf, "type=\"%s\" ", str, len);
|
| - STRNCATF (buf, "size=%d/>\n", ea->index.size, len);
|
| -
|
| - STRNCAT (buf, "\t\t\t</index>\n", len);
|
| - }
|
| -
|
| - //scale
|
| - STRNCAT (buf, "\t\t\t<scale>\n", len);
|
| - STRNCAT (buf, "\t\t\t\t<immediate ", len);
|
| - STRNCATF (buf, "value=\"%d\"/>\n", ea->scale, len);
|
| - STRNCAT (buf, "\t\t\t</scale>\n", len);
|
| -
|
| - if ( ea->disp_size ) {
|
| -
|
| - STRNCAT (buf, "\t\t\t<displacement>\n", len);
|
| -
|
| - if ( ea->disp_size > 1 && ! ea->disp_sign ) {
|
| - STRNCAT (buf, "\t\t\t\t<address ", len);
|
| - STRNCATF (buf, "value=\"0x%" PRIX32 "\"/>\n", ea->disp,
|
| - len);
|
| - } else {
|
| - STRNCAT (buf, "\t\t\t\t<immediate ", len);
|
| - STRNCATF (buf, "value=%" PRId32 "/>\n", ea->disp, len);
|
| - }
|
| -
|
| - STRNCAT (buf, "\t\t\t</displacement>\n", len);
|
| - }
|
| -
|
| - } else if ( format == raw_syntax ) {
|
| -
|
| - PRINT_DISPLACEMENT(ea);
|
| - STRNCAT( buf, "(", len );
|
| -
|
| - STRNCATF( buf, "%s,", ea->base.name, len );
|
| - STRNCATF( buf, "%s,", ea->index.name, len );
|
| - STRNCATF( buf, "%d", ea->scale, len );
|
| - STRNCAT( buf, ")", len );
|
| -
|
| - } else {
|
| -
|
| - STRNCAT( buf, "[", len );
|
| -
|
| - if ( ea->base.name[0] ) {
|
| - STRNCAT( buf, ea->base.name, len );
|
| - if ( ea->index.name[0] ||
|
| - (ea->disp_size && ! ea->disp_sign) ) {
|
| - STRNCAT( buf, "+", len );
|
| - }
|
| - }
|
| - if ( ea->index.name[0] ) {
|
| - STRNCAT( buf, ea->index.name, len );
|
| - if ( ea->scale > 1 )
|
| - {
|
| - STRNCATF( buf, "*%" PRId32, ea->scale, len );
|
| - }
|
| - if ( ea->disp_size && ! ea->disp_sign )
|
| - {
|
| - STRNCAT( buf, "+", len );
|
| - }
|
| - }
|
| -
|
| - if ( ea->disp_size || (! ea->index.name[0] &&
|
| - ! ea->base.name[0] ) )
|
| - {
|
| - PRINT_DISPLACEMENT(ea);
|
| - }
|
| -
|
| - STRNCAT( buf, "]", len );
|
| - }
|
| -
|
| - return( strlen(buf) );
|
| -}
|
| -
|
| -static int format_seg( x86_op_t *op, char *buf, int len,
|
| - enum x86_asm_format format ) {
|
| - int len_orig = len;
|
| - const char *reg = "";
|
| -
|
| - if (! op || ! buf || ! len || ! op->flags) {
|
| - return(0);
|
| - }
|
| - if ( op->type != op_offset && op->type != op_expression ){
|
| - return(0);
|
| - }
|
| - if (! ((int) op->flags & 0xF00) ) {
|
| - return(0);
|
| - }
|
| -
|
| - switch (op->flags & 0xF00) {
|
| - case op_es_seg: reg = "es"; break;
|
| - case op_cs_seg: reg = "cs"; break;
|
| - case op_ss_seg: reg = "ss"; break;
|
| - case op_ds_seg: reg = "ds"; break;
|
| - case op_fs_seg: reg = "fs"; break;
|
| - case op_gs_seg: reg = "gs"; break;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - if (! reg[0] ) {
|
| - return( 0 );
|
| - }
|
| -
|
| - switch( format ) {
|
| - case xml_syntax:
|
| - STRNCAT( buf, "\t\t\t<segment ", len );
|
| - STRNCATF( buf, "value=\"%s\"/>\n", reg, len );
|
| - break;
|
| - case att_syntax:
|
| - STRNCATF( buf, "%%%s:", reg, len );
|
| - break;
|
| -
|
| - default:
|
| - STRNCATF( buf, "%s:", reg, len );
|
| - break;
|
| - }
|
| -
|
| - return( len_orig - len ); /* return length of appended string */
|
| -}
|
| -
|
| -static const char *get_operand_datatype_str( x86_op_t *op ){
|
| -
|
| - static const char *types[] = {
|
| - "sbyte", /* 0 */
|
| - "sword",
|
| - "sqword",
|
| - "sdword",
|
| - "sdqword", /* 4 */
|
| - "byte",
|
| - "word",
|
| - "qword",
|
| - "dword", /* 8 */
|
| - "dqword",
|
| - "sreal",
|
| - "dreal",
|
| - "extreal", /* 12 */
|
| - "bcd",
|
| - "ssimd",
|
| - "dsimd",
|
| - "sssimd", /* 16 */
|
| - "sdsimd",
|
| - "descr32",
|
| - "descr16",
|
| - "pdescr32", /* 20 */
|
| - "pdescr16",
|
| - "bounds16",
|
| - "bounds32",
|
| - "fpu_env16",
|
| - "fpu_env32", /* 25 */
|
| - "fpu_state16",
|
| - "fpu_state32",
|
| - "fp_reg_set"
|
| - };
|
| -
|
| - /* handle signed values first */
|
| - if ( op->flags & op_signed ) {
|
| - switch (op->datatype) {
|
| - case op_byte: return types[0];
|
| - case op_word: return types[1];
|
| - case op_qword: return types[2];
|
| - case op_dqword: return types[4];
|
| - default: return types[3];
|
| - }
|
| - }
|
| -
|
| - switch (op->datatype) {
|
| - case op_byte: return types[5];
|
| - case op_word: return types[6];
|
| - case op_qword: return types[7];
|
| - case op_dqword: return types[9];
|
| - case op_sreal: return types[10];
|
| - case op_dreal: return types[11];
|
| - case op_extreal: return types[12];
|
| - case op_bcd: return types[13];
|
| - case op_ssimd: return types[14];
|
| - case op_dsimd: return types[15];
|
| - case op_sssimd: return types[16];
|
| - case op_sdsimd: return types[17];
|
| - case op_descr32: return types[18];
|
| - case op_descr16: return types[19];
|
| - case op_pdescr32: return types[20];
|
| - case op_pdescr16: return types[21];
|
| - case op_bounds16: return types[22];
|
| - case op_bounds32: return types[23];
|
| - case op_fpustate16: return types[24];
|
| - case op_fpustate32: return types[25];
|
| - case op_fpuenv16: return types[26];
|
| - case op_fpuenv32: return types[27];
|
| - case op_fpregset: return types[28];
|
| - default: return types[8];
|
| - }
|
| -}
|
| -
|
| -static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
| - int len) {
|
| -
|
| - static struct {
|
| - const char *name;
|
| - int value;
|
| - } insn_flags[] = {
|
| - { "carry_set ", 0x0001 },
|
| - { "zero_set ", 0x0002 },
|
| - { "oflow_set ", 0x0004 },
|
| - { "dir_set ", 0x0008 },
|
| - { "sign_set ", 0x0010 },
|
| - { "parity_set ", 0x0020 },
|
| - { "carry_or_zero_set ", 0x0040 },
|
| - { "zero_set_or_sign_ne_oflow ", 0x0080 },
|
| - { "carry_clear ", 0x0100 },
|
| - { "zero_clear ", 0x0200 },
|
| - { "oflow_clear ", 0x0400 },
|
| - { "dir_clear ", 0x0800 },
|
| - { "sign_clear ", 0x1000 },
|
| - { "parity_clear ", 0x2000 },
|
| - { "sign_eq_oflow ", 0x4000 },
|
| - { "sign_ne_oflow ", 0x8000 },
|
| - { NULL, 0x0000 }, //end
|
| - };
|
| -
|
| - unsigned int i;
|
| - int len_orig = len;
|
| -
|
| - for (i = 0; insn_flags[i].name; i++) {
|
| - if (! (flags & insn_flags[i].value) )
|
| - continue;
|
| -
|
| - STRNCAT( buf, insn_flags[i].name, len );
|
| - }
|
| -
|
| - return( len_orig - len );
|
| -}
|
| -
|
| -static const char *get_insn_group_str( enum x86_insn_group gp ) {
|
| -
|
| - static const char *types[] = {
|
| - "", // 0
|
| - "controlflow",// 1
|
| - "arithmetic", // 2
|
| - "logic", // 3
|
| - "stack", // 4
|
| - "comparison", // 5
|
| - "move", // 6
|
| - "string", // 7
|
| - "bit_manip", // 8
|
| - "flag_manip", // 9
|
| - "fpu", // 10
|
| - "", // 11
|
| - "", // 12
|
| - "interrupt", // 13
|
| - "system", // 14
|
| - "other", // 15
|
| - };
|
| -
|
| - if ( gp > sizeof (types)/sizeof(types[0]) )
|
| - return "";
|
| -
|
| - return types[gp];
|
| -}
|
| -
|
| -static const char *get_insn_type_str( enum x86_insn_type type ) {
|
| -
|
| - static struct {
|
| - const char *name;
|
| - int value;
|
| - } types[] = {
|
| - /* insn_controlflow */
|
| - { "jmp", 0x1001 },
|
| - { "jcc", 0x1002 },
|
| - { "call", 0x1003 },
|
| - { "callcc", 0x1004 },
|
| - { "return", 0x1005 },
|
| - { "loop", 0x1006 },
|
| - /* insn_arithmetic */
|
| - { "add", 0x2001 },
|
| - { "sub", 0x2002 },
|
| - { "mul", 0x2003 },
|
| - { "div", 0x2004 },
|
| - { "inc", 0x2005 },
|
| - { "dec", 0x2006 },
|
| - { "shl", 0x2007 },
|
| - { "shr", 0x2008 },
|
| - { "rol", 0x2009 },
|
| - { "ror", 0x200A },
|
| - /* insn_logic */
|
| - { "and", 0x3001 },
|
| - { "or", 0x3002 },
|
| - { "xor", 0x3003 },
|
| - { "not", 0x3004 },
|
| - { "neg", 0x3005 },
|
| - /* insn_stack */
|
| - { "push", 0x4001 },
|
| - { "pop", 0x4002 },
|
| - { "pushregs", 0x4003 },
|
| - { "popregs", 0x4004 },
|
| - { "pushflags", 0x4005 },
|
| - { "popflags", 0x4006 },
|
| - { "enter", 0x4007 },
|
| - { "leave", 0x4008 },
|
| - /* insn_comparison */
|
| - { "test", 0x5001 },
|
| - { "cmp", 0x5002 },
|
| - /* insn_move */
|
| - { "mov", 0x6001 }, /* move */
|
| - { "movcc", 0x6002 }, /* conditional move */
|
| - { "xchg", 0x6003 }, /* exchange */
|
| - { "xchgcc", 0x6004 }, /* conditional exchange */
|
| - /* insn_string */
|
| - { "strcmp", 0x7001 },
|
| - { "strload", 0x7002 },
|
| - { "strmov", 0x7003 },
|
| - { "strstore", 0x7004 },
|
| - { "translate", 0x7005 }, /* xlat */
|
| - /* insn_bit_manip */
|
| - { "bittest", 0x8001 },
|
| - { "bitset", 0x8002 },
|
| - { "bitclear", 0x8003 },
|
| - /* insn_flag_manip */
|
| - { "clear_carry", 0x9001 },
|
| - { "clear_zero", 0x9002 },
|
| - { "clear_oflow", 0x9003 },
|
| - { "clear_dir", 0x9004 },
|
| - { "clear_sign", 0x9005 },
|
| - { "clear_parity", 0x9006 },
|
| - { "set_carry", 0x9007 },
|
| - { "set_zero", 0x9008 },
|
| - { "set_oflow", 0x9009 },
|
| - { "set_dir", 0x900A },
|
| - { "set_sign", 0x900B },
|
| - { "set_parity", 0x900C },
|
| - { "tog_carry", 0x9010 },
|
| - { "tog_zero", 0x9020 },
|
| - { "tog_oflow", 0x9030 },
|
| - { "tog_dir", 0x9040 },
|
| - { "tog_sign", 0x9050 },
|
| - { "tog_parity", 0x9060 },
|
| - /* insn_fpu */
|
| - { "fmov", 0xA001 },
|
| - { "fmovcc", 0xA002 },
|
| - { "fneg", 0xA003 },
|
| - { "fabs", 0xA004 },
|
| - { "fadd", 0xA005 },
|
| - { "fsub", 0xA006 },
|
| - { "fmul", 0xA007 },
|
| - { "fdiv", 0xA008 },
|
| - { "fsqrt", 0xA009 },
|
| - { "fcmp", 0xA00A },
|
| - { "fcos", 0xA00C },
|
| - { "fldpi", 0xA00D },
|
| - { "fldz", 0xA00E },
|
| - { "ftan", 0xA00F },
|
| - { "fsine", 0xA010 },
|
| - { "fsys", 0xA020 },
|
| - /* insn_interrupt */
|
| - { "int", 0xD001 },
|
| - { "intcc", 0xD002 }, /* not present in x86 ISA */
|
| - { "iret", 0xD003 },
|
| - { "bound", 0xD004 },
|
| - { "debug", 0xD005 },
|
| - { "trace", 0xD006 },
|
| - { "invalid_op", 0xD007 },
|
| - { "oflow", 0xD008 },
|
| - /* insn_system */
|
| - { "halt", 0xE001 },
|
| - { "in", 0xE002 }, /* input from port/bus */
|
| - { "out", 0xE003 }, /* output to port/bus */
|
| - { "cpuid", 0xE004 },
|
| - /* insn_other */
|
| - { "nop", 0xF001 },
|
| - { "bcdconv", 0xF002 }, /* convert to or from BCD */
|
| - { "szconv", 0xF003 }, /* change size of operand */
|
| - { NULL, 0 }, //end
|
| - };
|
| -
|
| - unsigned int i;
|
| -
|
| - //go thru every type in the enum
|
| - for ( i = 0; types[i].name; i++ ) {
|
| - if ( types[i].value == type )
|
| - return types[i].name;
|
| - }
|
| -
|
| - return "";
|
| -}
|
| -
|
| -static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
| - static const char *intel[] = {
|
| - "", // 0
|
| - "8086", // 1
|
| - "80286", // 2
|
| - "80386", // 3
|
| - "80387", // 4
|
| - "80486", // 5
|
| - "Pentium", // 6
|
| - "Pentium Pro", // 7
|
| - "Pentium 2", // 8
|
| - "Pentium 3", // 9
|
| - "Pentium 4" // 10
|
| - };
|
| -
|
| - if ( cpu < sizeof(intel)/sizeof(intel[0]) ) {
|
| - return intel[cpu];
|
| - } else if ( cpu == 16 ) {
|
| - return "K6";
|
| - } else if ( cpu == 32 ) {
|
| - return "K7";
|
| - } else if ( cpu == 48 ) {
|
| - return "Athlon";
|
| - }
|
| -
|
| - return "";
|
| -}
|
| -
|
| -static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
| - static const char *subset[] = {
|
| - NULL, // 0
|
| - "General Purpose", // 1
|
| - "Floating Point", // 2
|
| - "FPU Management", // 3
|
| - "MMX", // 4
|
| - "SSE", // 5
|
| - "SSE2", // 6
|
| - "SSE3", // 7
|
| - "3DNow!", // 8
|
| - "System" // 9
|
| - };
|
| -
|
| - if ( isa > sizeof (subset)/sizeof(subset[0]) ) {
|
| - return "";
|
| - }
|
| -
|
| - return subset[isa];
|
| -}
|
| -
|
| -static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf,
|
| - int len){
|
| -
|
| - char str[MAX_OP_STRING];
|
| -
|
| - memset (str, 0, sizeof str);
|
| -
|
| - switch ( op->type ) {
|
| - case op_register:
|
| - STRNCATF( buf, "%%%s", op->data.reg.name, len );
|
| - break;
|
| -
|
| - case op_immediate:
|
| - get_operand_data_str( op, str, sizeof str );
|
| - STRNCATF( buf, "$%s", str, len );
|
| - break;
|
| -
|
| - case op_relative_near:
|
| - STRNCATF( buf, "0x%08X",
|
| - (unsigned int)(op->data.sbyte +
|
| - insn->addr + insn->size), len );
|
| - break;
|
| -
|
| - case op_relative_far:
|
| - if (op->datatype == op_word) {
|
| - STRNCATF( buf, "0x%08X",
|
| - (unsigned int)(op->data.sword +
|
| - insn->addr + insn->size), len );
|
| - } else {
|
| - STRNCATF( buf, "0x%08X",
|
| - (unsigned int)(op->data.sdword +
|
| - insn->addr + insn->size), len );
|
| - }
|
| - break;
|
| -
|
| - case op_absolute:
|
| - /* ATT uses the syntax $section, $offset */
|
| - STRNCATF( buf, "$0x%04" PRIX16 ", ", op->data.absolute.segment,
|
| - len );
|
| - if (op->datatype == op_descr16) {
|
| - STRNCATF( buf, "$0x%04" PRIX16,
|
| - op->data.absolute.offset.off16, len );
|
| - } else {
|
| - STRNCATF( buf, "$0x%08" PRIX32,
|
| - op->data.absolute.offset.off32, len );
|
| - }
|
| - break;
|
| - case op_offset:
|
| - /* ATT requires a '*' before JMP/CALL ops */
|
| - if (insn->type == insn_jmp || insn->type == insn_call)
|
| - STRNCAT( buf, "*", len );
|
| -
|
| - len -= format_seg( op, buf, len, att_syntax );
|
| - STRNCATF( buf, "0x%08" PRIX32, op->data.sdword, len );
|
| - break;
|
| -
|
| - case op_expression:
|
| - /* ATT requires a '*' before JMP/CALL ops */
|
| - if (insn->type == insn_jmp || insn->type == insn_call)
|
| - STRNCAT( buf, "*", len );
|
| -
|
| - len -= format_seg( op, buf, len, att_syntax );
|
| - len -= format_expr( &op->data.expression, buf, len,
|
| - att_syntax );
|
| - break;
|
| - case op_unused:
|
| - case op_unknown:
|
| - /* return 0-truncated buffer */
|
| - break;
|
| - }
|
| -
|
| - return ( strlen( buf ) );
|
| -}
|
| -
|
| -static int format_operand_native( x86_op_t *op, x86_insn_t *insn, char *buf,
|
| - int len){
|
| -
|
| - char str[MAX_OP_STRING];
|
| -
|
| - switch (op->type) {
|
| - case op_register:
|
| - STRNCAT( buf, op->data.reg.name, len );
|
| - break;
|
| -
|
| - case op_immediate:
|
| - get_operand_data_str( op, str, sizeof str );
|
| - STRNCAT( buf, str, len );
|
| - break;
|
| -
|
| - case op_relative_near:
|
| - STRNCATF( buf, "0x%08" PRIX32,
|
| - (unsigned int)(op->data.sbyte +
|
| - insn->addr + insn->size), len );
|
| - break;
|
| -
|
| - case op_relative_far:
|
| - if ( op->datatype == op_word ) {
|
| - STRNCATF( buf, "0x%08" PRIX32,
|
| - (unsigned int)(op->data.sword +
|
| - insn->addr + insn->size), len );
|
| - break;
|
| - } else {
|
| - STRNCATF( buf, "0x%08" PRIX32, op->data.sdword +
|
| - insn->addr + insn->size, len );
|
| - }
|
| - break;
|
| -
|
| - case op_absolute:
|
| - STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
|
| - len );
|
| - if (op->datatype == op_descr16) {
|
| - STRNCATF( buf, "0x%04" PRIX16,
|
| - op->data.absolute.offset.off16, len );
|
| - } else {
|
| - STRNCATF( buf, "0x%08" PRIX32,
|
| - op->data.absolute.offset.off32, len );
|
| - }
|
| - break;
|
| -
|
| - case op_offset:
|
| - len -= format_seg( op, buf, len, native_syntax );
|
| - STRNCATF( buf, "[0x%08" PRIX32 "]", op->data.sdword, len );
|
| - break;
|
| -
|
| - case op_expression:
|
| - len -= format_seg( op, buf, len, native_syntax );
|
| - len -= format_expr( &op->data.expression, buf, len,
|
| - native_syntax );
|
| - break;
|
| - case op_unused:
|
| - case op_unknown:
|
| - /* return 0-truncated buffer */
|
| - break;
|
| - }
|
| -
|
| - return( strlen( buf ) );
|
| -}
|
| -
|
| -static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
|
| - int len){
|
| -
|
| - char str[MAX_OP_STRING] = "\0";
|
| -
|
| - switch (op->type) {
|
| - case op_register:
|
| -
|
| - get_operand_regtype_str( op->data.reg.type, str,
|
| - sizeof str );
|
| -
|
| - STRNCAT( buf, "\t\t<register ", len );
|
| - STRNCATF( buf, "name=\"%s\" ", op->data.reg.name, len );
|
| - STRNCATF( buf, "type=\"%s\" ", str, len );
|
| - STRNCATF( buf, "size=%d/>\n", op->data.reg.size, len );
|
| - break;
|
| -
|
| - case op_immediate:
|
| -
|
| - get_operand_data_str( op, str, sizeof str );
|
| -
|
| - STRNCAT( buf, "\t\t<immediate ", len );
|
| - STRNCATF( buf, "type=\"%s\" ",
|
| - get_operand_datatype_str (op), len );
|
| - STRNCATF( buf, "value=\"%s\"/>\n", str, len );
|
| - break;
|
| -
|
| - case op_relative_near:
|
| - STRNCAT( buf, "\t\t<relative_offset ", len );
|
| -
|
| - STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
|
| - (unsigned int)(op->data.sbyte +
|
| - insn->addr + insn->size), len );
|
| - break;
|
| -
|
| - case op_relative_far:
|
| - STRNCAT( buf, "\t\t<relative_offset ", len );
|
| -
|
| - if (op->datatype == op_word) {
|
| - STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
|
| - (unsigned int)(op->data.sword +
|
| - insn->addr + insn->size), len);
|
| - break;
|
| - } else {
|
| -
|
| - STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
|
| - op->data.sdword + insn->addr + insn->size,
|
| - len );
|
| - }
|
| - break;
|
| -
|
| - case op_absolute:
|
| -
|
| - STRNCATF( buf,
|
| - "\t\t<absolute_address segment=\"0x%04" PRIX16 "\"",
|
| - op->data.absolute.segment, len );
|
| -
|
| - if (op->datatype == op_descr16) {
|
| - STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">",
|
| - op->data.absolute.offset.off16, len );
|
| - } else {
|
| - STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">",
|
| - op->data.absolute.offset.off32, len );
|
| - }
|
| -
|
| - STRNCAT( buf, "\t\t</absolute_address>\n", len );
|
| - break;
|
| -
|
| - case op_expression:
|
| -
|
| -
|
| - STRNCAT( buf, "\t\t<address_expression>\n", len );
|
| -
|
| - len -= format_seg( op, buf, len, xml_syntax );
|
| - len -= format_expr( &op->data.expression, buf, len,
|
| - xml_syntax );
|
| -
|
| - STRNCAT( buf, "\t\t</address_expression>\n", len );
|
| - break;
|
| -
|
| - case op_offset:
|
| -
|
| - STRNCAT( buf, "\t\t<segment_offset>\n", len );
|
| -
|
| - len -= format_seg( op, buf, len, xml_syntax );
|
| -
|
| - STRNCAT( buf, "\t\t\t<address ", len);
|
| - STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
|
| - op->data.sdword, len );
|
| - STRNCAT( buf, "\t\t</segment_offset>\n", len );
|
| - break;
|
| -
|
| - case op_unused:
|
| - case op_unknown:
|
| - /* return 0-truncated buffer */
|
| - break;
|
| - }
|
| -
|
| - return( strlen( buf ) );
|
| -}
|
| -
|
| -static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
|
| - int len){
|
| -
|
| - char str[MAX_OP_RAW_STRING];
|
| - const char *datatype = get_operand_datatype_str(op);
|
| -
|
| - switch (op->type) {
|
| - case op_register:
|
| -
|
| - get_operand_regtype_str( op->data.reg.type, str,
|
| - sizeof str );
|
| -
|
| - STRNCAT( buf, "reg|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| - STRNCATF( buf, "%s:", op->data.reg.name, len );
|
| - STRNCATF( buf, "%s:", str, len );
|
| - STRNCATF( buf, "%d|", op->data.reg.size, len );
|
| - break;
|
| -
|
| - case op_immediate:
|
| -
|
| - get_operand_data_str( op, str, sizeof str );
|
| -
|
| - STRNCAT( buf, "immediate|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| - STRNCATF( buf, "%s|", str, len );
|
| - break;
|
| -
|
| - case op_relative_near:
|
| - /* NOTE: in raw format, we print the
|
| - * relative offset, not the actual
|
| - * address of the jump target */
|
| -
|
| - STRNCAT( buf, "relative|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| - STRNCATF( buf, "%" PRId8 "|", op->data.sbyte, len );
|
| - break;
|
| -
|
| - case op_relative_far:
|
| -
|
| - STRNCAT( buf, "relative|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| -
|
| - if (op->datatype == op_word) {
|
| - STRNCATF( buf, "%" PRId16 "|", op->data.sword, len);
|
| - break;
|
| - } else {
|
| - STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len );
|
| - }
|
| - break;
|
| -
|
| - case op_absolute:
|
| -
|
| - STRNCAT( buf, "absolute_address|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| -
|
| - STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
|
| - len );
|
| - if (op->datatype == op_descr16) {
|
| - STRNCATF( buf, "0x%04" PRIX16 "|",
|
| - op->data.absolute.offset.off16, len );
|
| - } else {
|
| - STRNCATF( buf, "0x%08" PRIX32 "|",
|
| - op->data.absolute.offset.off32, len );
|
| - }
|
| -
|
| - break;
|
| -
|
| - case op_expression:
|
| -
|
| - STRNCAT( buf, "address_expression|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| -
|
| - len -= format_seg( op, buf, len, native_syntax );
|
| - len -= format_expr( &op->data.expression, buf, len,
|
| - raw_syntax );
|
| -
|
| - STRNCAT( buf, "|", len );
|
| - break;
|
| -
|
| - case op_offset:
|
| -
|
| - STRNCAT( buf, "segment_offset|", len );
|
| - STRNCATF( buf, "%s|", datatype, len );
|
| -
|
| - len -= format_seg( op, buf, len, xml_syntax );
|
| -
|
| - STRNCATF( buf, "%08" PRIX32 "|", op->data.sdword, len );
|
| - break;
|
| -
|
| - case op_unused:
|
| - case op_unknown:
|
| - /* return 0-truncated buffer */
|
| - break;
|
| - }
|
| -
|
| - return( strlen( buf ) );
|
| -}
|
| -
|
| -int x86_format_operand( x86_op_t *op, char *buf, int len,
|
| - enum x86_asm_format format ){
|
| - x86_insn_t *insn;
|
| -
|
| - if ( ! op || ! buf || len < 1 ) {
|
| - return(0);
|
| - }
|
| -
|
| - /* insn is stored in x86_op_t since .21-pre3 */
|
| - insn = (x86_insn_t *) op->insn;
|
| -
|
| - memset( buf, 0, len );
|
| -
|
| - switch ( format ) {
|
| - case att_syntax:
|
| - return format_operand_att( op, insn, buf, len );
|
| - case xml_syntax:
|
| - return format_operand_xml( op, insn, buf, len );
|
| - case raw_syntax:
|
| - return format_operand_raw( op, insn, buf, len );
|
| - case native_syntax:
|
| - case intel_syntax:
|
| - default:
|
| - return format_operand_native( op, insn, buf, len );
|
| - }
|
| -}
|
| -
|
| -#define is_imm_jmp(op) (op->type == op_absolute || \
|
| - op->type == op_immediate || \
|
| - op->type == op_offset)
|
| -#define is_memory_op(op) (op->type == op_absolute || \
|
| - op->type == op_expression || \
|
| - op->type == op_offset)
|
| -
|
| -static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
| - int size = 0;
|
| - const char *suffix;
|
| -
|
| - if (! insn || ! buf || ! len )
|
| - return(0);
|
| -
|
| - memset( buf, 0, len );
|
| -
|
| - /* do long jump/call prefix */
|
| - if ( insn->type == insn_jmp || insn->type == insn_call ) {
|
| - if (! is_imm_jmp( x86_operand_1st(insn) ) ||
|
| - (x86_operand_1st(insn))->datatype != op_byte ) {
|
| - /* far jump/call, use "l" prefix */
|
| - STRNCAT( buf, "l", len );
|
| - }
|
| - STRNCAT( buf, insn->mnemonic, len );
|
| -
|
| - return ( strlen( buf ) );
|
| - }
|
| -
|
| - /* do mnemonic */
|
| - STRNCAT( buf, insn->mnemonic, len );
|
| -
|
| - /* do suffixes for memory operands */
|
| - if (!(insn->note & insn_note_nosuffix) &&
|
| - (insn->group == insn_arithmetic ||
|
| - insn->group == insn_logic ||
|
| - insn->group == insn_move ||
|
| - insn->group == insn_stack ||
|
| - insn->group == insn_string ||
|
| - insn->group == insn_comparison ||
|
| - insn->type == insn_in ||
|
| - insn->type == insn_out
|
| - )) {
|
| - if ( x86_operand_count( insn, op_explicit ) > 0 &&
|
| - is_memory_op( x86_operand_1st(insn) ) ){
|
| - size = x86_operand_size( x86_operand_1st( insn ) );
|
| - } else if ( x86_operand_count( insn, op_explicit ) > 1 &&
|
| - is_memory_op( x86_operand_2nd(insn) ) ){
|
| - size = x86_operand_size( x86_operand_2nd( insn ) );
|
| - }
|
| - }
|
| -
|
| - if ( size == 1 ) suffix = "b";
|
| - else if ( size == 2 ) suffix = "w";
|
| - else if ( size == 4 ) suffix = "l";
|
| - else if ( size == 8 ) suffix = "q";
|
| - else suffix = "";
|
| -
|
| - STRNCAT( buf, suffix, len );
|
| - return ( strlen( buf ) );
|
| -}
|
| -
|
| -int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
|
| - enum x86_asm_format format){
|
| - char str[MAX_OP_STRING];
|
| -
|
| - memset( buf, 0, len );
|
| - STRNCAT( buf, insn->prefix_string, len );
|
| - if ( format == att_syntax ) {
|
| - format_att_mnemonic( insn, str, sizeof str );
|
| - STRNCAT( buf, str, len );
|
| - } else {
|
| - STRNCAT( buf, insn->mnemonic, len );
|
| - }
|
| -
|
| - return( strlen( buf ) );
|
| -}
|
| -
|
| -struct op_string { char *buf; size_t len; };
|
| -
|
| -static void format_op_raw( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
| - struct op_string * opstr = (struct op_string *) arg;
|
| -
|
| - format_operand_raw(op, insn, opstr->buf, opstr->len);
|
| -}
|
| -
|
| -static int format_insn_note(x86_insn_t *insn, char *buf, int len){
|
| - char note[32] = {0};
|
| - int len_orig = len, note_len = 32;
|
| -
|
| - if ( insn->note & insn_note_ring0 ) {
|
| - STRNCATF( note, "%s", "Ring0 ", note_len );
|
| - }
|
| - if ( insn->note & insn_note_smm ) {
|
| - STRNCATF( note, "%s", "SMM ", note_len );
|
| - }
|
| - if ( insn->note & insn_note_serial ) {
|
| - STRNCATF(note, "%s", "Serialize ", note_len );
|
| - }
|
| - STRNCATF( buf, "%s|", note, len );
|
| -
|
| - return( len_orig - len );
|
| -}
|
| -
|
| -static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
|
| - struct op_string opstr = { buf, len };
|
| - int i;
|
| -
|
| - /* RAW style:
|
| - * ADDRESS|OFFSET|SIZE|BYTES|
|
| - * PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|
|
| - * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|
|
| - * STACK_MOD|STACK_MOD_VAL
|
| - * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*
|
| - *
|
| - * Register values are encoded as:
|
| - * NAME:TYPE:SIZE
|
| - *
|
| - * Effective addresses are encoded as:
|
| - * disp(base_reg,index_reg,scale)
|
| - */
|
| - STRNCATF( buf, "0x%08" PRIX32 "|", insn->addr , len );
|
| - STRNCATF( buf, "0x%08" PRIX32 "|", insn->offset, len );
|
| - STRNCATF( buf, "%d|" , insn->size , len );
|
| -
|
| - /* print bytes */
|
| - for ( i = 0; i < insn->size; i++ ) {
|
| - STRNCATF( buf, "%02X ", insn->bytes[i], len );
|
| - }
|
| - STRNCAT( buf, "|", len );
|
| -
|
| - len -= format_insn_prefix_str( insn->prefix, buf, len );
|
| - STRNCATF( buf, "|%s|", insn->prefix_string , len );
|
| - STRNCATF( buf, "%s|", get_insn_group_str( insn->group ), len );
|
| - STRNCATF( buf, "%s|", get_insn_type_str( insn->type ) , len );
|
| - STRNCATF( buf, "%s|", insn->mnemonic , len );
|
| - STRNCATF( buf, "%s|", get_insn_cpu_str( insn->cpu ) , len );
|
| - STRNCATF( buf, "%s|", get_insn_isa_str( insn->isa ) , len );
|
| -
|
| - /* insn note */
|
| - len -= format_insn_note( insn, buf, len );
|
| -
|
| - len -= format_insn_eflags_str( insn->flags_set, buf, len );
|
| - STRNCAT( buf, "|", len );
|
| - len -= format_insn_eflags_str( insn->flags_tested, buf, len );
|
| - STRNCAT( buf, "|", len );
|
| - STRNCATF( buf, "%d|", insn->stack_mod, len );
|
| - STRNCATF( buf, "%" PRId32 "|", insn->stack_mod_val, len );
|
| -
|
| - opstr.len = len;
|
| - x86_operand_foreach( insn, format_op_raw, &opstr, op_any );
|
| -
|
| - return( strlen (buf) );
|
| -}
|
| -
|
| -static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
|
| - char str[MAX_OP_XML_STRING];
|
| - int i;
|
| -
|
| - STRNCAT( buf, "<x86_insn>\n", len );
|
| -
|
| - STRNCATF( buf, "\t<address rva=\"0x%08" PRIX32 "\" ", insn->addr, len );
|
| - STRNCATF( buf, "offset=\"0x%08" PRIX32 "\" ", insn->offset, len );
|
| - STRNCATF( buf, "size=%d bytes=\"", insn->size, len );
|
| -
|
| - for ( i = 0; i < insn->size; i++ ) {
|
| - STRNCATF( buf, "%02X ", insn->bytes[i], len );
|
| - }
|
| - STRNCAT( buf, "\"/>\n", len );
|
| -
|
| - STRNCAT( buf, "\t<prefix type=\"", len );
|
| - len -= format_insn_prefix_str( insn->prefix, buf, len );
|
| - STRNCATF( buf, "\" string=\"%s\"/>\n", insn->prefix_string, len );
|
| -
|
| - STRNCATF( buf, "\t<mnemonic group=\"%s\" ",
|
| - get_insn_group_str (insn->group), len );
|
| - STRNCATF( buf, "type=\"%s\" ", get_insn_type_str (insn->type), len );
|
| - STRNCATF( buf, "string=\"%s\"/>\n", insn->mnemonic, len );
|
| -
|
| - STRNCAT( buf, "\t<flags type=set>\n", len );
|
| - STRNCAT( buf, "\t\t<flag name=\"", len );
|
| - len -= format_insn_eflags_str( insn->flags_set, buf, len );
|
| - STRNCAT( buf, "\"/>\n\t</flags>\n", len );
|
| -
|
| -
|
| - STRNCAT( buf, "\t<flags type=tested>\n", len );
|
| - STRNCAT( buf, "\t\t<flag name=\"", len );
|
| - len -= format_insn_eflags_str( insn->flags_tested, buf, len );
|
| - STRNCAT( buf, "\"/>\n\t</flags>\n", len );
|
| -
|
| - if ( x86_operand_1st( insn ) ) {
|
| - x86_format_operand( x86_operand_1st(insn), str,
|
| - sizeof str, xml_syntax);
|
| - STRNCAT( buf, "\t<operand name=dest>\n", len );
|
| - STRNCAT( buf, str, len );
|
| - STRNCAT( buf, "\t</operand>\n", len );
|
| - }
|
| -
|
| - if ( x86_operand_2nd( insn ) ) {
|
| - x86_format_operand( x86_operand_2nd( insn ), str,
|
| - sizeof str, xml_syntax);
|
| - STRNCAT( buf, "\t<operand name=src>\n", len );
|
| - STRNCAT( buf, str, len );
|
| - STRNCAT( buf, "\t</operand>\n", len );
|
| - }
|
| -
|
| - if ( x86_operand_3rd( insn ) ) {
|
| - x86_format_operand( x86_operand_3rd(insn), str,
|
| - sizeof str, xml_syntax);
|
| - STRNCAT( buf, "\t<operand name=imm>\n", len );
|
| - STRNCAT( buf, str, len );
|
| - STRNCAT( buf, "\t</operand>\n", len );
|
| - }
|
| -
|
| - STRNCAT( buf, "</x86_insn>\n", len );
|
| -
|
| - return strlen (buf);
|
| -}
|
| -
|
| -int x86_format_header( char *buf, int len, enum x86_asm_format format ) {
|
| - switch (format) {
|
| - case att_syntax:
|
| - snprintf( buf, len, "MNEMONIC\tSRC, DEST, IMM" );
|
| - break;
|
| - case intel_syntax:
|
| - snprintf( buf, len, "MNEMONIC\tDEST, SRC, IMM" );
|
| - break;
|
| - case native_syntax:
|
| - snprintf( buf, len, "ADDRESS\tBYTES\tMNEMONIC\t"
|
| - "DEST\tSRC\tIMM" );
|
| - break;
|
| - case raw_syntax:
|
| - snprintf( buf, len, "ADDRESS|OFFSET|SIZE|BYTES|"
|
| - "PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|"
|
| - "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|"
|
| - "STACK_MOD|STACK_MOD_VAL"
|
| - "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*"
|
| - );
|
| - break;
|
| - case xml_syntax:
|
| - snprintf( buf, len,
|
| - "<x86_insn>"
|
| - "<address rva= offset= size= bytes=/>"
|
| - "<prefix type= string=/>"
|
| - "<mnemonic group= type= string= "
|
| - "cpu= isa= note= />"
|
| - "<flags type=set>"
|
| - "<flag name=>"
|
| - "</flags>"
|
| - "<stack_mod val= >"
|
| - "<flags type=tested>"
|
| - "<flag name=>"
|
| - "</flags>"
|
| - "<operand name=>"
|
| - "<register name= type= size=/>"
|
| - "<immediate type= value=/>"
|
| - "<relative_offset value=/>"
|
| - "<absolute_address value=>"
|
| - "<segment value=/>"
|
| - "</absolute_address>"
|
| - "<address_expression>"
|
| - "<segment value=/>"
|
| - "<base>"
|
| - "<register name= type= size=/>"
|
| - "</base>"
|
| - "<index>"
|
| - "<register name= type= size=/>"
|
| - "</index>"
|
| - "<scale>"
|
| - "<immediate value=/>"
|
| - "</scale>"
|
| - "<displacement>"
|
| - "<immediate value=/>"
|
| - "<address value=/>"
|
| - "</displacement>"
|
| - "</address_expression>"
|
| - "<segment_offset>"
|
| - "<address value=/>"
|
| - "</segment_offset>"
|
| - "</operand>"
|
| - "</x86_insn>"
|
| - );
|
| - break;
|
| - case unknown_syntax:
|
| - if ( len ) {
|
| - buf[0] = '\0';
|
| - }
|
| - break;
|
| - }
|
| -
|
| - return( strlen(buf) );
|
| -}
|
| -
|
| -int x86_format_insn( x86_insn_t *insn, char *buf, int len,
|
| - enum x86_asm_format format ){
|
| - char str[MAX_OP_STRING];
|
| - x86_op_t *src, *dst;
|
| - int i;
|
| -
|
| - memset(buf, 0, len);
|
| - if ( format == intel_syntax ) {
|
| - /* INTEL STYLE: mnemonic dest, src, imm */
|
| - STRNCAT( buf, insn->prefix_string, len );
|
| - STRNCAT( buf, insn->mnemonic, len );
|
| - STRNCAT( buf, "\t", len );
|
| -
|
| - /* dest */
|
| - if ( (dst = x86_operand_1st( insn )) && !(dst->flags & op_implied) ) {
|
| - x86_format_operand( dst, str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - }
|
| -
|
| - /* src */
|
| - if ( (src = x86_operand_2nd( insn )) ) {
|
| - if ( !(dst->flags & op_implied) ) {
|
| - STRNCAT( buf, ", ", len );
|
| - }
|
| - x86_format_operand( src, str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - }
|
| -
|
| - /* imm */
|
| - if ( x86_operand_3rd( insn )) {
|
| - STRNCAT( buf, ", ", len );
|
| - x86_format_operand( x86_operand_3rd( insn ),
|
| - str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - }
|
| -
|
| - } else if ( format == att_syntax ) {
|
| - /* ATT STYLE: mnemonic src, dest, imm */
|
| - STRNCAT( buf, insn->prefix_string, len );
|
| - format_att_mnemonic(insn, str, MAX_OP_STRING);
|
| - STRNCATF( buf, "%s\t", str, len);
|
| -
|
| -
|
| - /* not sure which is correct? sometimes GNU as requires
|
| - * an imm as the first operand, sometimes as the third... */
|
| - /* imm */
|
| - if ( x86_operand_3rd( insn ) ) {
|
| - x86_format_operand(x86_operand_3rd( insn ),
|
| - str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - /* there is always 'dest' operand if there is 'src' */
|
| - STRNCAT( buf, ", ", len );
|
| - }
|
| -
|
| - if ( (insn->note & insn_note_nonswap ) == 0 ) {
|
| - /* regular AT&T style swap */
|
| - src = x86_operand_2nd( insn );
|
| - dst = x86_operand_1st( insn );
|
| - }
|
| - else {
|
| - /* special-case instructions */
|
| - src = x86_operand_1st( insn );
|
| - dst = x86_operand_2nd( insn );
|
| - }
|
| -
|
| - /* src */
|
| - if ( src ) {
|
| - x86_format_operand(src, str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - /* there is always 'dest' operand if there is 'src' */
|
| - if ( dst && !(dst->flags & op_implied) ) {
|
| - STRNCAT( buf, ", ", len );
|
| - }
|
| - }
|
| -
|
| - /* dest */
|
| - if ( dst && !(dst->flags & op_implied) ) {
|
| - x86_format_operand( dst, str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - }
|
| -
|
| -
|
| - } else if ( format == raw_syntax ) {
|
| - format_raw_insn( insn, buf, len );
|
| - } else if ( format == xml_syntax ) {
|
| - format_xml_insn( insn, buf, len );
|
| - } else { /* default to native */
|
| - /* NATIVE style: RVA\tBYTES\tMNEMONIC\tOPERANDS */
|
| - /* print address */
|
| - STRNCATF( buf, "%08" PRIX32 "\t", insn->addr, len );
|
| -
|
| - /* print bytes */
|
| - for ( i = 0; i < insn->size; i++ ) {
|
| - STRNCATF( buf, "%02X ", insn->bytes[i], len );
|
| - }
|
| -
|
| - STRNCAT( buf, "\t", len );
|
| -
|
| - /* print mnemonic */
|
| - STRNCAT( buf, insn->prefix_string, len );
|
| - STRNCAT( buf, insn->mnemonic, len );
|
| - STRNCAT( buf, "\t", len );
|
| -
|
| - /* print operands */
|
| - /* dest */
|
| - if ( x86_operand_1st( insn ) ) {
|
| - x86_format_operand( x86_operand_1st( insn ),
|
| - str, MAX_OP_STRING, format);
|
| - STRNCATF( buf, "%s\t", str, len );
|
| - }
|
| -
|
| - /* src */
|
| - if ( x86_operand_2nd( insn ) ) {
|
| - x86_format_operand(x86_operand_2nd( insn ),
|
| - str, MAX_OP_STRING, format);
|
| - STRNCATF( buf, "%s\t", str, len );
|
| - }
|
| -
|
| - /* imm */
|
| - if ( x86_operand_3rd( insn )) {
|
| - x86_format_operand( x86_operand_3rd( insn ),
|
| - str, MAX_OP_STRING, format);
|
| - STRNCAT( buf, str, len );
|
| - }
|
| - }
|
| -
|
| - return( strlen( buf ) );
|
| -}
|
| -
|
|
|