12b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <stdio.h>
22b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <stdlib.h>
32b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
42b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "libdis.h"
52b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
62b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#ifdef _MSC_VER
72b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        #define snprintf        _snprintf
82b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        #define inline          __inline
92b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#endif
102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgint x86_insn_is_valid( x86_insn_t *insn ) {
122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if ( insn && insn->type != insn_invalid && insn->size > 0 ) {
132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		return 1;
142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return 0;
172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orguint32_t x86_get_address( x86_insn_t *insn ) {
202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x86_oplist_t *op_lst;
212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (! insn || ! insn->operands ) {
222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        	return 0;
232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		if ( op_lst->op.type == op_offset ) {
272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return op_lst->op.data.offset;
282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		} else if ( op_lst->op.type == op_absolute ) {
292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			if ( op_lst->op.datatype == op_descr16 ) {
302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				return (uint32_t)
312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org					op_lst->op.data.absolute.offset.off16;
322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			}
332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return op_lst->op.data.absolute.offset.off32;
342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return 0;
382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgint32_t x86_get_rel_offset( x86_insn_t *insn ) {
412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x86_oplist_t *op_lst;
422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (! insn || ! insn->operands ) {
432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        	return 0;
442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		if ( op_lst->op.type == op_relative_near ) {
482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return (int32_t) op_lst->op.data.relative_near;
492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		} else if ( op_lst->op.type == op_relative_far ) {
502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return op_lst->op.data.relative_far;
512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return 0;
552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgx86_op_t * x86_get_branch_target( x86_insn_t *insn ) {
582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x86_oplist_t *op_lst;
592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (! insn || ! insn->operands ) {
602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        	return NULL;
612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		if ( op_lst->op.access & op_execute ) {
652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return &(op_lst->op);
662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return NULL;
702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgx86_op_t * x86_get_imm( x86_insn_t *insn ) {
722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x86_oplist_t *op_lst;
732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (! insn || ! insn->operands ) {
742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        	return NULL;
752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		if ( op_lst->op.type == op_immediate ) {
792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			return &(op_lst->op);
802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
832b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return NULL;
842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
862b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#define IS_PROPER_IMM( x ) \
872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x->op.type == op_immediate && ! (x->op.flags & op_hardcode)
882b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org/* if there is an immediate value in the instruction, return a pointer to
912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org * it */
922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgunsigned char * x86_get_raw_imm( x86_insn_t *insn ) {
932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        int size, offset;
942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        x86_op_t *op  = NULL;
952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (! insn || ! insn->operands ) {
972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        	return(NULL);
982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* a bit inelegant, but oh well... */
1012b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if ( IS_PROPER_IMM( insn->operands ) ) {
1022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		op = &insn->operands->op;
1032b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	} else if ( insn->operands->next ) {
1042b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		if ( IS_PROPER_IMM( insn->operands->next ) ) {
1052b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op = &insn->operands->next->op;
1062b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		} else if ( insn->operands->next->next &&
1072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			    IS_PROPER_IMM( insn->operands->next->next ) ) {
1082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op = &insn->operands->next->next->op;
1092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
1102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
1112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if (! op ) {
1132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		return( NULL );
1142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
1152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* immediate data is at the end of the insn */
1172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	size = x86_operand_size( op );
1182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	offset = insn->size - size;
1192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return( &insn->bytes[offset] );
1202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgunsigned int x86_operand_size( x86_op_t *op ) {
1242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        switch (op->datatype ) {
1252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_byte:    return 1;
1262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_word:    return 2;
1272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_dword:   return 4;
1282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_qword:   return 8;
1292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_dqword:  return 16;
1302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_sreal:   return 4;
1312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_dreal:   return 8;
1322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_extreal: return 10;
1332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_bcd:     return 10;
1342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_ssimd:   return 16;
1352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_dsimd:   return 16;
1362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_sssimd:  return 4;
1372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_sdsimd:  return 8;
1382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_descr32: return 6;
1392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_descr16: return 4;
1402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_pdescr32: return 6;
1412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_pdescr16: return 6;
1422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case op_bounds16: return 4;
1432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case op_bounds32: return 8;
1442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_fpuenv16:  return 14;
1452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_fpuenv32:  return 28;
1462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_fpustate16:  return 94;
1472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_fpustate32:  return 108;
1482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case op_fpregset: return 512;
1492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case op_fpreg: return 10;
1502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case op_none: return 0;
1512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
1522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        return(4);      /* default size */
1532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) {
1562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->addr = addr;
1572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){
1602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->offset = offset;
1612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_set_insn_function( x86_insn_t *insn, void * func ){
1642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->function = func;
1652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_set_insn_block( x86_insn_t *insn, void * block ){
1682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->block = block;
1692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_tag_insn( x86_insn_t *insn ){
1722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->tag = 1;
1732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgvoid x86_untag_insn( x86_insn_t *insn ){
1762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if ( insn ) insn->tag = 0;
1772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgint x86_insn_is_tagged( x86_insn_t *insn ){
1802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        return insn->tag;
1812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
1822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
183