static xed_ast_input_enum_t classify_avx_sse(xed_decoded_inst_t* xedd)
{
    xed_extension_enum_t ext = xed_decoded_inst_get_extension(xedd);
    xed_iclass_enum_t iclass  = xed_decoded_inst_get_iclass(xedd);
    if(iclass == XED_ICLASS_VZEROALL)
    {
        return XED_AST_INPUT_VZEROALL;
    }
    else if(iclass == XED_ICLASS_VZEROUPPER)
    {
        return XED_AST_INPUT_VZEROUPPER;
    }
    else if(is_interesting_avx(ext))
    {
        if(is_avx128(xedd))
            return XED_AST_INPUT_AVX128;
        return XED_AST_INPUT_AVX256;
    }
    else if(is_sse(xedd))
    {
        return XED_AST_INPUT_SSE;
    }
    else if(iclass == XED_ICLASS_XRSTOR)
    {
        return XED_AST_INPUT_XRSTOR;
    }
    return XED_AST_INPUT_NOTHING;
}
static int is_sse(xed_decoded_inst_t* xedd)
{
    const xed_extension_enum_t extension = xed_decoded_inst_get_extension(xedd);
    const xed_category_enum_t category = xed_decoded_inst_get_category(xedd);

    if(extension == XED_EXTENSION_SSE)
    {
        if(category != XED_CATEGORY_MMX  &&
                category != XED_CATEGORY_PREFETCH) /* exclude PREFETCH* insts */
            return 1;
    }
    else if(extension == XED_EXTENSION_SSE2  ||
            extension == XED_EXTENSION_SSSE3 ||
            extension == XED_EXTENSION_SSE4)
    {
        if(category != XED_CATEGORY_MMX)
            return 1;
    }
    else if(extension == XED_EXTENSION_AES ||
            extension == XED_EXTENSION_PCLMULQDQ)
    {
        return 1;
    }
    return 0;
}
xed_uint_t disas_decode_binary(const xed_state_t* dstate,
                               const xed_uint8_t* hex_decode_text,
                               const unsigned int bytes,
                               xed_decoded_inst_t* xedd,
                               xed_uint64_t runtime_address) {
    xed_uint64_t t1,t2;
    xed_error_enum_t xed_error;
    xed_bool_t okay;

    if (CLIENT_VERBOSE) {
        print_hex_line(hex_decode_text, bytes);
    }
    t1 = xed_get_time();
    xed_error = xed_decode(xedd, hex_decode_text, bytes);
    t2 = xed_get_time();
    okay = (xed_error == XED_ERROR_NONE);
    if (CLIENT_VERBOSE3) {
        xed_uint64_t delta = t2-t1;
        printf("Decode time = " XED_FMT_LU "\n", delta);
    }
    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 buf[XED_TMP_BUF_LEN];
            if (xed_decoded_inst_valid(xedd)) 
            {
                printf( "ICLASS: %s   CATEGORY: %s   EXTENSION: %s  IFORM: %s"
                        "   ISA_SET: %s\n", 
                xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(xedd)),
                xed_category_enum_t2str(xed_decoded_inst_get_category(xedd)),
                xed_extension_enum_t2str(xed_decoded_inst_get_extension(xedd)),
                xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(xedd)),
                xed_isa_set_enum_t2str(xed_decoded_inst_get_isa_set(xedd)));
            }
            memset(buf,0,XED_TMP_BUF_LEN);
            disassemble(buf,XED_TMP_BUF_LEN, xedd, runtime_address,0);
            printf("SHORT: %s\n", buf);
        }
        return 1;
    }
    else {
        xed_decode_error(0, 0, hex_decode_text, xed_error);
        return 0;
    }
    (void) dstate; // pacify compiler
}
void xed_disas_test(xed_disas_info_t* di)
{

    static int first = 1;
#if !defined(XED_ILD_ONLY) && !defined(XED2_PERF_MEASURE)
    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;

    xed_decoded_inst_t xedd;


    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);
        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) && !defined(XED2_PERF_MEASURE)
                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;

        xed_decoded_inst_zero_set_mode(&xedd, di->dstate);
        if(di->late_init)
            (*di->late_init)(&xedd);

        if(di->decode_only)
        {
            xed_uint64_t t1;
            xed_uint64_t t2;
            xed_error_enum_t xed_error = XED_ERROR_NONE;

            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 = decode_internal(
                            &xedd,
                            XED_REINTERPRET_CAST(const xed_uint8_t*, z),
                            ilim);
#endif
            t2 = xed_get_time();

            okay = (xed_error == XED_ERROR_NONE);
#if defined(PTI_XED_TEST)
            if(okay)
                pti_xed_test(&xedd,
                             XED_REINTERPRET_CAST(const xed_uint8_t*, z),
                             ilim,
                             runtime_instruction_address);
#endif

            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(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) && !defined(XED2_PERF_MEASURE)

            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);
#if 0  /* test code for the new API */
                        if(xed_decoded_inst_masked_vector_operation(&xedd))
                            printf("MSK ");
                        else
                            printf("    ");
#endif

                        if(di->ast)
                        {
                            printf("%-6s ",
                                   xed_ast_input_enum_t2str(
                                       classify_avx_sse(&xedd)));
                        }
                        else
                        {
                            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
        {
static string
disassemble(UINT64 start, UINT64 stop) {
    UINT64 pc = start;
    xed_state_t dstate;
    xed_syntax_enum_t syntax = XED_SYNTAX_INTEL;
    xed_error_enum_t xed_error;
    xed_decoded_inst_t xedd;
    ostringstream os;
    if (sizeof(ADDRINT) == 4) 
        xed_state_init(&dstate,     
                       XED_MACHINE_MODE_LEGACY_32,
                       XED_ADDRESS_WIDTH_32b, 
                       XED_ADDRESS_WIDTH_32b);
    else
        xed_state_init(&dstate,
                       XED_MACHINE_MODE_LONG_64,
                       XED_ADDRESS_WIDTH_64b, 
                       XED_ADDRESS_WIDTH_64b);

    /*while( pc < stop )*/ {
        xed_decoded_inst_zero_set_mode(&xedd, &dstate);
        UINT32 len = 15;
        if (stop - pc < 15)
            len = stop-pc;

        xed_error = xed_decode(&xedd, reinterpret_cast<const UINT8*>(pc), len);
        bool okay = (xed_error == XED_ERROR_NONE);
        iostream::fmtflags fmt = os.flags();
        os << std::setfill('0')
           << "XDIS "
           << std::hex
           << std::setw(sizeof(ADDRINT)*2)
           << pc
           << std::dec
           << ": "
           << std::setfill(' ')
           << std::setw(4);

        if (okay) {
            char buffer[200];
            unsigned int dec_len, sp;

            os << xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd));
            dec_len = xed_decoded_inst_get_length(&xedd);
            print_hex_line(buffer, reinterpret_cast<UINT8*>(pc), dec_len);
            os << " " << buffer;
            for ( sp=dec_len; sp < 12; sp++)     // pad out the instruction bytes
                os << "  ";
            os << " ";
            memset(buffer,0,200);
            int dis_okay = xed_format(syntax, &xedd, buffer, 200, pc);
            if (dis_okay) 
                os << buffer << endl;
            else
                os << "Error disasassembling pc 0x" << std::hex << pc << std::dec << endl;
            pc += dec_len;
        }
        else { // print the byte and keep going.
            UINT8 memval = *reinterpret_cast<UINT8*>(pc);
            os << "???? " // no extension
               << std::hex
               << std::setw(2)
               << std::setfill('0')
               << static_cast<UINT32>(memval)
               << std::endl;
            pc += 1;
        }
        os.flags(fmt);
    }
    return os.str();
}
Ejemplo n.º 6
0
static PyObject *get_extension(instruction_t *self)
{
    return PyInt_FromLong(xed_decoded_inst_get_extension(self->decoded_inst));
}