michael@0: #include michael@0: #include michael@0: michael@0: #include "libdis.h" michael@0: michael@0: #ifdef _MSC_VER michael@0: #define snprintf _snprintf michael@0: #define inline __inline michael@0: #endif michael@0: michael@0: int x86_insn_is_valid( x86_insn_t *insn ) { michael@0: if ( insn && insn->type != insn_invalid && insn->size > 0 ) { michael@0: return 1; michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: uint32_t x86_get_address( x86_insn_t *insn ) { michael@0: x86_oplist_t *op_lst; michael@0: if (! insn || ! insn->operands ) { michael@0: return 0; michael@0: } michael@0: michael@0: for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) { michael@0: if ( op_lst->op.type == op_offset ) { michael@0: return op_lst->op.data.offset; michael@0: } else if ( op_lst->op.type == op_absolute ) { michael@0: if ( op_lst->op.datatype == op_descr16 ) { michael@0: return (uint32_t) michael@0: op_lst->op.data.absolute.offset.off16; michael@0: } michael@0: return op_lst->op.data.absolute.offset.off32; michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: int32_t x86_get_rel_offset( x86_insn_t *insn ) { michael@0: x86_oplist_t *op_lst; michael@0: if (! insn || ! insn->operands ) { michael@0: return 0; michael@0: } michael@0: michael@0: for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) { michael@0: if ( op_lst->op.type == op_relative_near ) { michael@0: return (int32_t) op_lst->op.data.relative_near; michael@0: } else if ( op_lst->op.type == op_relative_far ) { michael@0: return op_lst->op.data.relative_far; michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: x86_op_t * x86_get_branch_target( x86_insn_t *insn ) { michael@0: x86_oplist_t *op_lst; michael@0: if (! insn || ! insn->operands ) { michael@0: return NULL; michael@0: } michael@0: michael@0: for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) { michael@0: if ( op_lst->op.access & op_execute ) { michael@0: return &(op_lst->op); michael@0: } michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: x86_op_t * x86_get_imm( x86_insn_t *insn ) { michael@0: x86_oplist_t *op_lst; michael@0: if (! insn || ! insn->operands ) { michael@0: return NULL; michael@0: } michael@0: michael@0: for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) { michael@0: if ( op_lst->op.type == op_immediate ) { michael@0: return &(op_lst->op); michael@0: } michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: michael@0: #define IS_PROPER_IMM( x ) \ michael@0: x->op.type == op_immediate && ! (x->op.flags & op_hardcode) michael@0: michael@0: michael@0: /* if there is an immediate value in the instruction, return a pointer to michael@0: * it */ michael@0: unsigned char * x86_get_raw_imm( x86_insn_t *insn ) { michael@0: int size, offset; michael@0: x86_op_t *op = NULL; michael@0: michael@0: if (! insn || ! insn->operands ) { michael@0: return(NULL); michael@0: } michael@0: michael@0: /* a bit inelegant, but oh well... */ michael@0: if ( IS_PROPER_IMM( insn->operands ) ) { michael@0: op = &insn->operands->op; michael@0: } else if ( insn->operands->next ) { michael@0: if ( IS_PROPER_IMM( insn->operands->next ) ) { michael@0: op = &insn->operands->next->op; michael@0: } else if ( insn->operands->next->next && michael@0: IS_PROPER_IMM( insn->operands->next->next ) ) { michael@0: op = &insn->operands->next->next->op; michael@0: } michael@0: } michael@0: michael@0: if (! op ) { michael@0: return( NULL ); michael@0: } michael@0: michael@0: /* immediate data is at the end of the insn */ michael@0: size = x86_operand_size( op ); michael@0: offset = insn->size - size; michael@0: return( &insn->bytes[offset] ); michael@0: } michael@0: michael@0: michael@0: unsigned int x86_operand_size( x86_op_t *op ) { michael@0: switch (op->datatype ) { michael@0: case op_byte: return 1; michael@0: case op_word: return 2; michael@0: case op_dword: return 4; michael@0: case op_qword: return 8; michael@0: case op_dqword: return 16; michael@0: case op_sreal: return 4; michael@0: case op_dreal: return 8; michael@0: case op_extreal: return 10; michael@0: case op_bcd: return 10; michael@0: case op_ssimd: return 16; michael@0: case op_dsimd: return 16; michael@0: case op_sssimd: return 4; michael@0: case op_sdsimd: return 8; michael@0: case op_descr32: return 6; michael@0: case op_descr16: return 4; michael@0: case op_pdescr32: return 6; michael@0: case op_pdescr16: return 6; michael@0: case op_bounds16: return 4; michael@0: case op_bounds32: return 8; michael@0: case op_fpuenv16: return 14; michael@0: case op_fpuenv32: return 28; michael@0: case op_fpustate16: return 94; michael@0: case op_fpustate32: return 108; michael@0: case op_fpregset: return 512; michael@0: case op_fpreg: return 10; michael@0: case op_none: return 0; michael@0: } michael@0: return(4); /* default size */ michael@0: } michael@0: michael@0: void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) { michael@0: if ( insn ) insn->addr = addr; michael@0: } michael@0: michael@0: void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){ michael@0: if ( insn ) insn->offset = offset; michael@0: } michael@0: michael@0: void x86_set_insn_function( x86_insn_t *insn, void * func ){ michael@0: if ( insn ) insn->function = func; michael@0: } michael@0: michael@0: void x86_set_insn_block( x86_insn_t *insn, void * block ){ michael@0: if ( insn ) insn->block = block; michael@0: } michael@0: michael@0: void x86_tag_insn( x86_insn_t *insn ){ michael@0: if ( insn ) insn->tag = 1; michael@0: } michael@0: michael@0: void x86_untag_insn( x86_insn_t *insn ){ michael@0: if ( insn ) insn->tag = 0; michael@0: } michael@0: michael@0: int x86_insn_is_tagged( x86_insn_t *insn ){ michael@0: return insn->tag; michael@0: } michael@0: