int main(int argc, char** argv) { xed_machine_mode_enum_t mmode; xed_bool_t long_mode = 1; xed_ild_t ild; xed_uint_t length = 0; xed_uint_t i; #define NTIMES 100 xed_uint64_t t1,t2,delta[NTIMES],tot; unsigned char itext[15] = { 0xf2, 0x2e, 0x4f, 0x0F, 0x85, 0x99, 0x00, 0x00, 0x00 }; // initialize the XED tables -- one time. xed_tables_init(); // The state of the machine -- required for decoding if (long_mode) { mmode=XED_MACHINE_MODE_LONG_64; } else { mmode=XED_MACHINE_MODE_LEGACY_32; } for(i=0;i<NTIMES;i++) { t1 = xed_get_time(); xed_ild_init(&ild, mmode, XED_CHIP_INVALID, itext, 15); length = xed_instruction_length_decode(&ild); t2 = xed_get_time(); delta[i] = t2-t1; } tot = 0; for(i=0;i<NTIMES;i++) { printf("Decode time[%3d] = " XED_FMT_LU "\n", i,delta[i]); if (i>0) tot += delta[i]; } printf("Avg time = " XED_FMT_LU "\n", tot/(NTIMES-1)); print_ild(&ild); printf("length = %d\n",length); return 0; (void) argc; (void) argv; //pacify compiler }
int main(int argc, char** argv) { xed_ild_t ild; xed_uint_t uargc = (xed_uint_t)argc; xed_uint_t length = 0; xed_uint_t dlen = 0; xed_uint_t i,j,input_nibbles=0; xed_uint8_t itext[XED_MAX_INSTRUCTION_BYTES]; char src[MAX_INPUT_NIBBLES+1]; xed_state_t dstate; xed_decoded_inst_t xedd; xed_uint_t first_argv; xed_uint_t bytes; xed_error_enum_t xed_error; xed_chip_enum_t chip = XED_CHIP_INVALID; int already_set_mode = 0; // initialize the XED tables -- one time. xed_tables_init(); xed_state_zero(&dstate); first_argv = 1; dstate.mmode=XED_MACHINE_MODE_LEGACY_32; dstate.stack_addr_width=XED_ADDRESS_WIDTH_32b; for(i=1;i< uargc;i++) { if (strcmp(argv[i], "-64") == 0) { assert(already_set_mode == 0); already_set_mode = 1; dstate.mmode=XED_MACHINE_MODE_LONG_64; first_argv++; } else if (strcmp(argv[i], "-16") == 0) { assert(already_set_mode == 0); already_set_mode = 1; dstate.mmode=XED_MACHINE_MODE_LEGACY_16; dstate.stack_addr_width=XED_ADDRESS_WIDTH_16b; first_argv++; } else if (strcmp(argv[i], "-s16") == 0) { already_set_mode = 1; dstate.stack_addr_width=XED_ADDRESS_WIDTH_16b; first_argv++; } else if (strcmp(argv[i], "-chip") == 0) { assert(i+1 < uargc); chip = str2xed_chip_enum_t(argv[i+1]); printf("Setting chip to %s\n", xed_chip_enum_t2str(chip)); assert(chip != XED_CHIP_INVALID); first_argv+=2; } } assert(first_argv < uargc); xed_decoded_inst_zero_set_mode(&xedd, &dstate); if (first_argv >= uargc) { printf("Need some hex instruction nibbles"); exit(1); } for(i=first_argv;i<uargc;i++) { for(j=0;argv[i][j];j++) { assert(input_nibbles < MAX_INPUT_NIBBLES); src[input_nibbles] = argv[i][j]; input_nibbles++; } } src[input_nibbles] = 0; if (input_nibbles & 1) { printf("Need an even number of nibbles"); exit(1); } bytes = xed_convert_ascii_to_hex(src, itext, XED_MAX_INSTRUCTION_BYTES); printf("Attempting to decode: "); for(i=0;i<bytes;i++) { printf("%02x", itext[i]); } printf("\n"); xed_ild_init(&ild, dstate.mmode, chip, itext, XED_MAX_INSTRUCTION_BYTES); length = xed_instruction_length_decode(&ild); print_ild(&ild); printf("ILD length = %d\n",length); xed_decoded_inst_set_input_chip(&xedd, chip); xed_error = xed_decode(&xedd, XED_REINTERPRET_CAST(const xed_uint8_t*,itext), bytes); switch(xed_error) { case XED_ERROR_NONE: break; case XED_ERROR_BUFFER_TOO_SHORT: printf("Not enough bytes provided\n"); exit(1); case XED_ERROR_INVALID_FOR_CHIP: printf("The instruction was not valid for the specified chip.\n"); exit(1); case XED_ERROR_GENERAL_ERROR: printf("Could not decode given input.\n"); exit(1); default: printf("Unhandled error code %s\n",xed_error_enum_t2str(xed_error)); exit(1); } dlen = xed_decoded_inst_get_length(&xedd); printf ("Traditional length = %d\n", dlen); if (dlen != length) { printf ("Length error\n"); exit(1); } printf ("Length matched\n"); return 0; }
void xed_disas_test(xed_disas_info_t di) { static int first = 1; #if !defined(XED_ILD_ONLY) xed_uint64_t errors = 0; #endif unsigned int m; unsigned char* z; unsigned char* zlimit; unsigned int length; int skipping; int last_all_zeros; unsigned int i; int okay; //for ILD comparing perf measurements #if defined(XED_ILD_ONLY) && defined(XED_ILD) #include "xed-ild.h" xed_ild_t ild_data = {0}; #endif //For XED_ILD_ONLY we want to run only ILD decoding to get //better timing precision. That means, that we don't run xed_decode //and don't use xedd at all #if !defined(XED_ILD_ONLY) xed_decoded_inst_t xedd; #endif xed_uint64_t runtime_instruction_address; xed_dot_graph_supp_t* gs = 0; xed_bool_t graph_empty = 1; //#define XED_USE_DECODE_CACHE #if defined(XED_USE_DECODE_CACHE) xed_decode_cache_t cache; xed_uint32_t n_cache_entries = 16*1024; xed_decode_cache_entry_t* cache_entries = (xed_decode_cache_entry_t*) malloc(n_cache_entries * sizeof(xed_decode_cache_entry_t)); xed_decode_cache_initialize(&cache, cache_entries, n_cache_entries); #endif if (di.dot_graph_output) { xed_syntax_enum_t syntax = XED_SYNTAX_INTEL; gs = xed_dot_graph_supp_create(syntax); } if (first) { xed_decode_stats_zero(&xed_stats, &di); #if defined(XED_ILD_ONLY) && defined(XED_ILD) //for ILD comparing xed_decode_stats_zero(&ild_stats, &di); #endif first = 0; } m = di.ninst; // number of things to decode z = di.a; if (di.runtime_vaddr_disas_start) if (di.runtime_vaddr_disas_start > di.runtime_vaddr) z = (di.runtime_vaddr_disas_start - di.runtime_vaddr) + di.a; zlimit = 0; if (di.runtime_vaddr_disas_end) { if (di.runtime_vaddr_disas_end > di.runtime_vaddr) zlimit = (di.runtime_vaddr_disas_end - di.runtime_vaddr) + di.a; else /* end address is before start of this region -- skip it */ goto finish; } if (z >= di.q) /* start pointer is after end of section */ goto finish; // for skipping long strings of zeros skipping = 0; last_all_zeros = 0; for( i=0; i<m;i++) { int ilim,elim; if (zlimit && z >= zlimit) { if (di.xml_format == 0) printf("# end of range.\n"); break; } if (z >= di.q) { if (di.xml_format == 0) #if !defined(XED_ILD_ONLY) printf("# end of text section.\n"); #endif break; } /* if we get near the end of the section, clip the itext length */ ilim = 15; elim = di.q - z; if (elim < ilim) ilim = elim; if (CLIENT_VERBOSE3) { printf("\n==============================================\n"); printf("Decoding instruction " XED_FMT_U "\n", i); printf("==============================================\n"); } // if we get two full things of 0's in a row, start skipping. if (all_zeros((xed_uint8_t*) z, ilim)) { if (skipping) { z = z + ilim; continue; } else if (last_all_zeros) { #if !defined(XED_ILD_ONLY) printf("...\n"); #endif z = z + ilim; skipping = 1; continue; } else last_all_zeros = 1; } else { skipping = 0; last_all_zeros = 0; } runtime_instruction_address = ((xed_uint64_t)(z-di.a)) + di.runtime_vaddr; if (CLIENT_VERBOSE3) { char tbuf[XED_HEX_BUFLEN]; printf("Runtime Address " XED_FMT_LX ,runtime_instruction_address); xed_print_hex_line(tbuf, (xed_uint8_t*) z, ilim,XED_HEX_BUFLEN); printf(" [%s]\n", tbuf); } okay = 0; length = 0; //For XED_ILD_ONLY we want to run only ILD decoding to get //better timing precision. That means, that we don't run xed_decode //and won't use xedd at all #if !defined(XED_ILD_ONLY) xed_decoded_inst_zero_set_mode(&xedd, di.dstate); if (di.late_init) (*di.late_init)(&xedd); #endif if ( di.decode_only ) { xed_uint64_t t1; xed_uint64_t t2; xed_error_enum_t xed_error = XED_ERROR_NONE; #if !defined(XED_ILD_ONLY) t1 = xed_get_time(); #if defined(XED_USE_DECODE_CACHE) xed_error = xed_decode_cache(&xedd, XED_REINTERPRET_CAST(const xed_uint8_t*,z), ilim, &cache); #else xed_error = xed_decode(&xedd, XED_REINTERPRET_CAST(const xed_uint8_t*,z), ilim); #endif t2 = xed_get_time(); okay = (xed_error == XED_ERROR_NONE); xed_decode_stats_reset(&xed_stats, t1, t2); length = xed_decoded_inst_get_length(&xedd); #else //defined(XED_ILD_ONLY) xed_machine_mode_enum_t mmode; const xed_uint8_t* itext = z; okay = 1; mmode = xed_state_get_machine_mode(di.dstate); xed_ild_init(&ild_data, mmode, xed_decoded_inst_get_input_chip(&xedd), itext, ILD_ITEXT_MAX_BYTES); t1 = xed_get_time(); xed_instruction_length_decode(&ild_data); t2 = xed_get_time(); xed_decode_stats_reset(&ild_stats, t1, t2); length = ild_data.length; #endif //defined(XED_ILD_ONLY) if (okay && length == 0) { printf("Zero length on decoded instruction!\n"); xed_decode_error( runtime_instruction_address, z-di.a, z, xed_error); xedex_derror("Dieing"); } if (di.resync && di.symfn) { xed_bool_t resync = 0; unsigned int x; for(x=1;x<length;x++) { char* name = (*di.symfn)(runtime_instruction_address+x, di.caller_symbol_data); if (name) { char buf[XED_HEX_BUFLEN]; /* bad news. We found a symbol in the middle of an * instruction. That probably means decoding is * messed up. This usually happens because of * data-in the code/text section. We should reject * the current instruction and pick up at the * symbol address. */ printf("ERROR: found symbol in the middle of" " an instruction. Resynchronizing...\n"); printf("ERROR: Rejecting: ["); xed_print_hex_line(buf, z, x, XED_HEX_BUFLEN); printf("%s]\n",buf); z += x; resync = 1; break; } } if (resync) continue; } xed_stats.total_ilen += length; //we don't want to print out disassembly with ILD perf #if !defined(XED_ILD_ONLY) if (okay) { if (CLIENT_VERBOSE1) { char tbuf[XED_TMP_BUF_LEN]; xed_decoded_inst_dump(&xedd,tbuf, XED_TMP_BUF_LEN); printf("%s\n",tbuf); } if (CLIENT_VERBOSE) { char buffer[XED_TMP_BUF_LEN]; unsigned int dec_len; unsigned int sp; if (di.symfn) { char* name = (*di.symfn)(runtime_instruction_address, di.caller_symbol_data); if (name) { if (di.xml_format) printf("\n<SYM>%s</SYM>\n", name); else printf("\nSYM %s:\n", name); } } if (di.xml_format) { printf("<ASMLINE>\n"); printf(" <ADDR>" XED_FMT_LX "</ADDR>\n", runtime_instruction_address); printf(" <CATEGORY>%s</CATEGORY>\n", xed_category_enum_t2str( xed_decoded_inst_get_category(&xedd))); printf(" <EXTENSION>%s</EXTENSION>\n", xed_extension_enum_t2str( xed_decoded_inst_get_extension(&xedd))); printf(" <ITEXT>"); dec_len = xed_decoded_inst_get_length(&xedd); xed_print_hex_line(buffer, (xed_uint8_t*) z, dec_len, XED_TMP_BUF_LEN); printf("%s</ITEXT>\n",buffer); buffer[0]=0; disassemble(buffer,XED_TMP_BUF_LEN, &xedd, runtime_instruction_address, di.caller_symbol_data); printf( " %s\n",buffer); printf("</ASMLINE>\n"); } else { printf("XDIS " XED_FMT_LX ": ", runtime_instruction_address); printf("%-9s ", xed_category_enum_t2str( xed_decoded_inst_get_category(&xedd))); printf("%-6s ", xed_extension_enum_t2str( xed_decoded_inst_get_extension(&xedd))); dec_len = xed_decoded_inst_get_length(&xedd); xed_print_hex_line(buffer, (xed_uint8_t*) z, dec_len, XED_HEX_BUFLEN); printf("%s",buffer); // pad out the instruction bytes for ( sp=dec_len; sp < 12; sp++) printf(" "); printf(" "); buffer[0]=0; disassemble(buffer,XED_TMP_BUF_LEN, &xedd, runtime_instruction_address, di.caller_symbol_data); printf( "%s",buffer); if (gs) { graph_empty = 0; xed_dot_graph_add_instruction( gs, &xedd, runtime_instruction_address, di.caller_symbol_data); } if (di.line_number_info_fn) (*di.line_number_info_fn)(runtime_instruction_address); printf( "\n"); } } } else { errors++; xed_decode_error( runtime_instruction_address, z-di.a, z, xed_error); // just give a length of 1B to see if we can restart decode... length = 1; } } #if defined(XED_ENCODER) else {