void *decode_instructions( void *buf, void *buf_limit, void *(*putxml_fptr)(void *putxml_data, const char *element_format, void *element_data), void *putxml_data, void *(*printf_fptr)(void *printf_data, const char *format, ...), void *printf_data, const char *config_string) { #define PUTXML(efmt, edata) (*putxml_fptr)(putxml_data, (const char*)(efmt), (void*)(edata)) #define PRINTF(fmt, x) (*printf_fptr)(printf_data, (const char*)(fmt), x) #define PRINTF2(fmt, x, y) (*printf_fptr)(printf_data, (const char*)(fmt), x, y) size_t buf_size = (char*)buf_limit - (char*)buf; unsigned char *uc_buf = (unsigned char*) buf; int have_opnd, which; x86_insn_t insn; x86_op_t *opnd; intptr_t addr; char sbuf[MAX_OP_STRING * 2]; size_t pos, size; if (!putxml_fptr) { putxml_fptr = empty_putxml; } if (!printf_fptr) { intptr_t stdio_fprintf_addr = (intptr_t) &fprintf; printf_fptr = (void * (*)(void *, const char *, ...)) stdio_fprintf_addr; if (!printf_data) printf_data = stdout; } x86_init(0, 0, 0); PUTXML("insns", buf); PUTXML("mach name='%s'/", "i386(base-hsdis)"); PUTXML("format bytes-per-line='%p'/", (intptr_t)FORMAT_BYTES_PER_LINE); for (pos = 0; pos < buf_size; pos += size) { size = x86_disasm(uc_buf, buf_size, (intptr_t) buf, pos, &insn); PUTXML("insn", (char*)buf + pos); if (size == 0) { PRINTF("invalid\t0x%02x", uc_buf[pos]); size = 1; /* to make progress */ } else { PRINTF2("%s%s", insn.prefix_string, insn.mnemonic); have_opnd = 0; for (which = 0; which < 3; which++) { /* dest comes first, then src and/or imm */ switch (which) { case 0: opnd = x86_operand_1st(&insn); break; case 1: opnd = x86_operand_2nd(&insn); break; default: opnd = x86_operand_3rd(&insn); break; } if (!opnd) continue; if (opnd->flags & op_implied) continue; if (!have_opnd++) PRINTF("\t", 0); else PRINTF(", ", 0); addr = addr_from_operand(opnd); if (!(addr && PUTXML("addr/", addr))) { x86_format_operand(opnd, sbuf, sizeof(sbuf), intel_syntax); PRINTF("%s", sbuf); } } } PUTXML("/insn", (char*)buf + pos + size); PRINTF("\n", 0); } PUTXML("/insns", (char*)buf + pos); x86_cleanup(); return (char*)buf + pos; }
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%08X\" ", insn->addr, len ); STRNCATF( buf, "offset=\"0x%08X\" ", 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_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, "%08X\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 ) ); }
int x86_format_insn( x86_insn_t *insn, char *buf, int len, enum x86_asm_format format ) { char str[MAX_OP_STRING]; 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 ( x86_operand_1st( insn ) ) { x86_format_operand( x86_operand_1st( insn ), insn, str, MAX_OP_STRING, format); STRNCAT( buf, str, len ); } /* src */ if ( x86_operand_2nd( insn ) ) { STRNCAT( buf, ", ", len ); x86_format_operand(x86_operand_2nd( insn ), insn, 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 ), 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); /* src */ if ( x86_operand_2nd( insn ) ) { x86_format_operand(x86_operand_2nd( insn ), insn, str, MAX_OP_STRING, format); STRNCAT( buf, str, len ); /* there is always 'dest' operand if there is 'src' */ STRNCAT( buf, ", ", len ); } /* dest */ if ( x86_operand_1st( insn ) ) { x86_format_operand( x86_operand_1st( insn ), insn, 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 ), insn, 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, "%08lX\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 ), 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 ), 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 ), insn, str, MAX_OP_STRING, format); STRNCAT( buf, str, len ); } } return( strlen( buf ) ); }