X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=misc%2Fdecoder_test%2FXED2%2Fexamples%2Fxed-examples-util.c;fp=misc%2Fdecoder_test%2FXED2%2Fexamples%2Fxed-examples-util.c;h=a5a4be40da6f5c5f331331804720f7e34075b32a;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/misc/decoder_test/XED2/examples/xed-examples-util.c b/misc/decoder_test/XED2/examples/xed-examples-util.c new file mode 100644 index 0000000..a5a4be4 --- /dev/null +++ b/misc/decoder_test/XED2/examples/xed-examples-util.c @@ -0,0 +1,960 @@ +/*BEGIN_LEGAL +Intel Open Source License + +Copyright (c) 2002-2007 Intel Corporation +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. Redistributions +in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. Neither the name of +the Intel Corporation nor the names of its contributors may be used to +endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR +ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +END_LEGAL */ +/// @file xed-examples-util.cpp +/// @author Mark Charney + +#include "xed-interface.h" +#include "xed-examples-util.h" +#include //strlen, memcmp, memset +#if defined(__APPLE__) || defined(__linux__) || defined(__linux) +# include +# include +# include +# include +# include +#endif +#include +#include +#include "xed-portability.h" +#include "xed-util.h" + + +void xed_decode_file_info_init(xed_decode_file_info_t* p, + const xed_state_t* arg_dstate, + int arg_ninst, + int arg_decode_only) { + p->dstate = *arg_dstate; + p->ninst = arg_ninst; + p->decode_only = arg_decode_only; +} + +typedef struct { + xed_uint64_t total_time ; + xed_uint64_t total_insts ; + xed_uint64_t total_ilen ; + xed_uint64_t total_olen ; + xed_uint64_t total_shorter ; + xed_uint64_t total_longer ; + xed_uint64_t bad_times ; + xed_uint64_t reset_counter; +} xed_decode_stats_t; + +void xed_decode_stats_reset(xed_decode_stats_t* p, xed_uint64_t t1, xed_uint64_t t2) { + if (t2 > t1) + p->total_time += (t2-t1); + else + p->bad_times++; + p->total_insts++; + p->reset_counter++; + if (p->reset_counter == 50) { + if (CLIENT_VERBOSE1) + printf("\n\nRESETTING STATS\n\n"); + // to ignore startup transients paging everything in. + p->total_insts=0; + p->total_time=0; + } +} + +void xed_decode_stats_zero(xed_decode_stats_t* p) { + p->total_time = 0; + p->total_insts = 0; + p->total_ilen = 0; + p->total_olen = 0; + p->total_shorter = 0; + p->total_longer = 0; + p->bad_times = 0; + p->reset_counter = 0; +} + +static xed_decode_stats_t xed_stats; +int xed_syntax = 0; +int intel_syntax = 1; +int att_syntax = 0; +int client_verbose=0; + +//////////////////////////////////////////////////////////////////////////// + +static char xed_toupper(char c) { + if (c >= 'a' && c <= 'z') + return c-'a'+'A'; + return c; +} + +char* xed_upcase_buf(char* s) { + xed_uint_t len = STATIC_CAST(xed_uint_t,strlen(s)); + xed_uint_t i; + for(i=0 ; i < len ; i++ ) + s[i] = STATIC_CAST(char,xed_toupper(s[i])); + return s; +} + +static xed_uint8_t convert_nibble(xed_uint8_t x) { + // convert ascii nibble to hex + xed_uint8_t rv = 0; + if (x >= '0' && x <= '9') + rv = x - '0'; + else if (x >= 'A' && x <= 'F') + rv = x - 'A' + 10; + else if (x >= 'a' && x <= 'f') + rv = x - 'a' + 10; + else { + printf("Error converting hex digit. Nibble value 0x%x\n", x); + exit(1); + } + return rv; +} + + +xed_int64_t xed_atoi_hex(char* buf) { + xed_int64_t o=0; + xed_uint_t i; + xed_uint_t len = STATIC_CAST(xed_uint_t,strlen(buf)); + for(i=0; i>4); + buf[2*i+1] = nibble_to_ascii_hex(array[i]&0xF); + } + buf[2*i]=0; +} + +void xed_print_hex_lines(char* buf, const xed_uint8_t* array, const int length) { + int n = length; + int i=0,j=0; + char* b = buf; + for( i=0 ; i< n; i++) { + *b++ = nibble_to_ascii_hex(array[i]>>4); + *b++ = nibble_to_ascii_hex(array[i]&0xF); + j++; + if (j == 16) { + j = 0; + *b++ = '\n'; + } + } + *b++ = '\n'; + *b = '0'; +} + + + + +void xedex_derror(const char* s) { + printf("[XED CLIENT ERROR] %s\n",s); + exit(1); +} + +void xedex_dwarn(const char* s) { + printf("[XED CLIENT WARNING] %s\n",s); +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + + + + +void xed_print_decode_stats() +{ + double cpi; + xed_int64_t growth; + printf("#Total decode cycles: " XED_FMT_LU "\n", xed_stats.total_time); + printf("#Total instructions decoded: " XED_FMT_LU "\n", xed_stats.total_insts); +#if defined(_MSC_VER) +# if _MSC_VER==1200 +# define XCAST(x) STATIC_CAST(xed_int64_t,x) +# else +# define XCAST(x) (x) +# endif +#else +# define XCAST(x) (x) +#endif + cpi = 1.0 * XCAST(xed_stats.total_time) / XCAST(xed_stats.total_insts); + printf("#Total cycles/instructions decoded: %f\n" , cpi); + + printf("#Bad times: " XED_FMT_LU "\n", xed_stats.bad_times); + printf("#Total input length bytes: " XED_FMT_LU "\n", xed_stats.total_ilen ); + printf("#Total output length bytes: " XED_FMT_LU "\n", xed_stats.total_olen ); + printf("#Growth bytes: " XED_FMT_LU "\n", xed_stats.total_longer ); + printf("#Shrinkage bytes: " XED_FMT_LU "\n", xed_stats.total_shorter ); + growth = xed_stats.total_olen - xed_stats.total_ilen; + printf("#Growth/Shrinkage bytes: " XED_FMT_LD "\n", growth ); + if (xed_stats.total_ilen) { + double pct_growth = 100.0 * growth / (double) XCAST(xed_stats.total_ilen); + printf("#Code size growth percent: %f\n", pct_growth); + } +} + + +void +xed_map_region(const char* path, + void** start, + unsigned int* length) +{ +#if defined(_WIN32) + FILE* f; + size_t t,ilen; + xed_uint8_t* p; +#if defined(XED_MSVC8) + errno_t err; + fprintf(stderr,"#Opening %s\n", path); + err = fopen_s(&f,path,"rb"); +#else + int err=0; + fprintf(stderr,"#Opening %s\n", path); + f = fopen(path,"rb"); + err = (f==0); +#endif + if (err != 0) { + fprintf(stderr,"ERROR: Could not open %s\n", path); + exit(1); + } + err = fseek(f, 0, SEEK_END); + if (err != 0) { + fprintf(stderr,"ERROR: Could not fseek %s\n", path); + exit(1); + } + ilen = ftell(f); + fprintf(stderr,"#Trying to read " XED_FMT_SIZET "\n", ilen); + p = (xed_uint8_t*)malloc(ilen); + t=0; + err = fseek(f,0, SEEK_SET); + if (err != 0) { + fprintf(stderr,"ERROR: Could not fseek to start of file %s\n", path); + exit(1); + } + + while(t < ilen) { + size_t n; + if (feof(f)) { + fprintf(stderr, "#Read EOF. Stopping.\n"); + break; + } + n = fread(p+t, 1, ilen-t,f); + t = t+n; + fprintf(stderr,"#Read " XED_FMT_SIZET " of %d bytes\n", t, ilen); + if (ferror(f)) { + fprintf(stderr, "Error in file read. Stopping.\n"); + break; + } + } + fclose(f); + *start = p; + *length = (unsigned int)ilen; + +#else + int ilen,fd; + fd = open(path, O_RDONLY); + if (fd == -1) { + printf("Could not open file: %s\n" , path); + exit(1); + } + ilen = lseek(fd, 0, SEEK_END); // find the size. + if (ilen == -1) + xedex_derror("lseek failed"); + else + *length = (unsigned int) ilen; + + lseek(fd, 0, SEEK_SET); // go to the beginning + *start = mmap(0, + *length, + PROT_READ|PROT_WRITE, + MAP_PRIVATE, + fd, + 0); + if (*start == (void*) -1) + xedex_derror("could not map region"); +#endif + if (CLIENT_VERBOSE1) + printf("Mapped " XED_FMT_U " bytes!\n", *length); +} + + +//////////////////////////////////////////////////////////////////////////// + +static int all_zeros(xed_uint8_t* p, unsigned int len) { + unsigned int i; + for( i=0;i 1024 ) + // tlen = 1024; + //xed_print_hex_line(p,tlen); + + m = ninst; // number of things to decode + z = a; + len = 15; //FIXME + + // for skipping long strings of zeros + skipping = 0; + last_all_zeros = 0; + for( i=0; i= q) { + printf("# end of text section.\n"); + break; + } + 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, 15)) + { + if (skipping) { + z = z + 15; + continue; + } + else if (last_all_zeros) { + printf("...\n"); + z = z + 15; + skipping = 1; + continue; + } + else + last_all_zeros = 1; + } + else + { + skipping = 0; + last_all_zeros = 0; + } + + runtime_instruction_address = ((xed_uint64_t)(z-a)) + runtime_vaddr; + + if (CLIENT_VERBOSE3) { + char tbuf[200]; + printf("Runtime Address " XED_FMT_LX ,runtime_instruction_address); + xed_print_hex_line(tbuf, (xed_uint8_t*) z, 15); + printf(" [%s]\n", tbuf); + } + okay = 0; + xed_decoded_inst_zero_set_mode(&xedd, dstate); + length = 0; + if ( decode_only ) + { + xed_uint64_t t1 = get_time(); + xed_uint64_t t2; + + xed_error_enum_t xed_error = xed_decode(&xedd, + REINTERPRET_CAST(const xed_uint8_t*,z), + len); + t2 = get_time(); + okay = (xed_error == XED_ERROR_NONE); + xed_decode_stats_reset(&xed_stats, t1, t2); + + length = xed_decoded_inst_get_length(&xedd); + if (okay && length == 0) { + printf("Zero length on decoded instruction!\n"); + xed_decode_error( z-a, z, xed_error); + xedex_derror("Dieing"); + } + xed_stats.total_ilen += length; + + if (okay) { + if (CLIENT_VERBOSE1) { + char tbuf[1024*3]; + xed_decoded_inst_dump(&xedd,tbuf, 1024*3); + printf("%s\n",tbuf); + } + if (CLIENT_VERBOSE) { + char buffer[200]; + unsigned int dec_len; + unsigned int sp; + if (symfn) { + char* name = (*symfn)(runtime_instruction_address); + if (name) + printf("\nSYM %s:\n", name); + } + printf("XDIS " XED_FMT_LX ": ", runtime_instruction_address); + printf("%-8s ", xed_category_enum_t2str(xed_decoded_inst_get_category(&xedd))); + printf("%-4s ", 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); + printf("%s",buffer); + // pad out the instruction bytes + for ( sp=dec_len; sp < 12; sp++) { + printf(" "); + } + printf(" "); + memset(buffer,0,200); + disassemble(buffer,200, &xedd, runtime_instruction_address); + printf( "%s\n",buffer); + } + } + else { + errors++; + xed_decode_error( z-a, z, xed_error); + // just give a length of 1B to see if we can restart decode... + length = 1; + } + } + else + { + xed_uint64_t t1 = get_time(); + xed_uint64_t t2; + unsigned int olen = 0; + olen = disas_decode_encode_binary(dstate, + REINTERPRET_CAST(const xed_uint8_t*,z), + len, + &xedd); + t2=get_time(); + okay = (olen != 0); + xed_decode_stats_reset(&xed_stats, t1, t2); + if (!okay) { + errors++; + printf("-- Could not decode/encode at offset: %d\n" ,(int)(z-a)); + // just give a length of 1B to see if we can restart decode... + length = 1; + //exit(1); + } + else { + length = xed_decoded_inst_get_length(&xedd); + xed_stats.total_ilen += length; + xed_stats.total_olen += olen; + if (length > olen) + xed_stats.total_shorter += (length - olen); + else + xed_stats.total_longer += (olen - length); + } + + } + + z = z + length; + } + + printf( "# Errors: " XED_FMT_LU "\n", errors); + (void) s; +} + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 810 && !defined(_M_IA64) +# include +# if __INTEL_COMPILER < 1000 +# pragma intrinsic(__rdtsc) +# endif +#endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_M_IA64) /* MSVS8 and later */ +# include +# pragma intrinsic(__rdtsc) +#endif + +xed_uint64_t get_time() +{ + xed_uint64_t ticks; + xed_uint32_t lo,hi; +#if defined(__GNUC__) +# if defined(__i386__) || defined(i386) || defined(i686) || defined(__x86_64__) + //asm volatile("rdtsc" : "=A" (ticks) ); + //asm volatile("rdtsc" : "=A" (ticks) :: "edx"); + asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); + ticks = hi; + ticks <<=32; + ticks |=lo; +# define FOUND_RDTSC +# endif +#endif +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER>=810 && !defined(_M_IA64) + ticks = __rdtsc(); +# define FOUND_RDTSC +#endif +#if !defined(FOUND_RDTSC) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_M_IA64) /* MSVS7, 8 */ + ticks = __rdtsc(); +# define FOUND_RDTSC +#endif +#if !defined(FOUND_RDTSC) + ticks = 0; +#endif + return ticks; + (void)hi; (void)lo; +} + + +xed_uint8_t +convert_ascii_nibble(char c) +{ + if (c >= '0' && c <= '9') { + return c-'0'; + } + else if (c >= 'a' && c <= 'f') { + return c-'a' + 10; + } + else if (c >= 'A' && c <= 'F') { + return c-'A' + 10; + } + else { + char buffer[200]; + char* x; + xed_strcpy(buffer,"Invalid character in hex string: "); + x= buffer+strlen(buffer); + *x++ = c; + *x++ = 0; + xedex_derror(buffer); + return 0; + } +} + + + +xed_uint64_t convert_ascii_hex_to_int(const char* s) { + xed_uint64_t retval = 0; + const char* p = s; + while (*p) { + retval = (retval << 4) + convert_ascii_nibble(*p); + p++; + } + return retval; +} + + +xed_uint8_t convert_ascii_nibbles(char c1, char c2) { + xed_uint8_t a = convert_ascii_nibble(c1) * 16 + convert_ascii_nibble(c2); + return a; +} + +unsigned int +xed_convert_ascii_to_hex(const char* src, xed_uint8_t* dst, unsigned int max_bytes) +{ + unsigned int j; + unsigned int p = 0; + unsigned int i = 0; + + const unsigned int len = STATIC_CAST(unsigned int,strlen(src)); + if ((len & 1) != 0) + xedex_derror("test string was not an even number of nibbles"); + + if (len > (max_bytes * 2) ) + xedex_derror("test string was too long"); + + for( j=0;j= '0' && c <= '9') + { + unsigned int digit = c - '0'; + v = v*10 + digit; + } + else + { + break; + } + } + return v*sign; +} + +static xed_int64_t +convert_base16(const char* buf) +{ + xed_int64_t v = 0; + int len = STATIC_CAST(int,strlen(buf)); + int start =0 ; + int i; + if (len > 2 && buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) + { + start = 2; + } + for(i=start;i= '0' && c <= '9') + { + unsigned int digit = c - '0'; + v = v*16 + digit; + } + else if (c >= 'A' && c <= 'F') + { + unsigned int digit = c - 'A' + 10; + v = v*16 + digit; + } + else if (c >= 'a' && c <= 'f') + { + unsigned int digit = c - 'a' + 10; + v = v*16 + digit; + } + else + { + break; + } + } + return v; +} + +static xed_int64_t +xed_internal_strtoll(const char* buf, int base) +{ + switch(base) + { + case 0: + if (strlen(buf) > 2 && buf[0] == '0' && + (buf[1] == 'x' || buf[1] == 'X')) + { + return convert_base16(buf); + } + return convert_base10(buf); + case 10: + return convert_base10(buf); + case 16: + return convert_base16(buf); + default: + xed_assert(0); + } + return 0; +} + +#endif + +xed_int64_t xed_strtoll(const char* buf, int base) +{ +#if defined(_WIN32) && !defined(__GNUC__) + // 64b version missing on some MS compilers + return xed_internal_strtoll(buf,base); +#else + return strtoll(buf,0,base); +#endif +} + + + +//////////////////////////////////////////////////////////////////////////// +//Local Variables: +//pref: "xed-examples-util.H" +//End: