Changeset 1504

Show
Ignore:
Timestamp:
01/13/08 16:35:53 (8 months ago)
Author:
common
Message:

libemu

  • improve sctest codequalitity, split profiling process into prepare() and test, allow reading shellcodes from argos csi files (prepare_argos(struct emu *e))
    using the argos csi profiling will require proper linking with libcargos, which is not done by now.
  • this change will introduce memory leaks
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libemu/trunk/testsuite/sctest.c

    r1477 r1504  
    2727 
    2828 
    29  
     29#include "../config.h" 
     30 
     31#define HAVE_GETOPT_H 
     32#ifdef HAVE_GETOPT_H 
     33# include <getopt.h> 
     34#endif 
     35 
     36#ifdef HAVE_STDLIB_H 
     37# include <stdlib.h> 
     38#endif 
     39 
     40 
     41#include <stdint.h> 
     42 
     43#define HAVE_UNISTD 
     44#ifdef HAVE_UNISTD 
     45# include <unistd.h> 
     46#endif 
    3047#include <stdio.h> 
    31 #include <stdlib.h> 
    32 #include <string.h> 
     48 
     49 
     50 
    3351#include <errno.h> 
    3452#include <sys/select.h> 
    35 #include <unistd.h> 
    36 #include <stdio.h> 
    37  
    38 #ifndef _GNU_SOURCE 
    39         #define _GNU_SOURCE 
     53 
     54 
     55#ifdef HAVE_LIBCARGOS 
     56#include <cargos-lib.h> 
     57#include <cargos-lib-static.h> 
    4058#endif 
    41 #include <getopt.h> 
    42  
    43 #include "../config.h" 
     59 
     60 
    4461#include "emu/emu.h" 
    4562#include "emu/emu_memory.h" 
     
    4865#include "emu/emu_cpu_data.h" 
    4966#include "emu/emu_cpu_stack.h" 
     67#include "emu/environment/emu_profile.h" 
    5068#include "emu/environment/win32/emu_env_w32.h" 
    5169#include "emu/environment/win32/emu_env_w32_dll.h" 
     
    7795        char *graphfile; 
    7896        bool from_stdin; 
     97        char *from_argos_csi; 
    7998        unsigned char *scode; 
    8099        uint32_t size; 
    81100        uint32_t offset; 
    82101} opts; 
     102 
    83103 
    84104/* 
     
    16161636} 
    16171637 
    1618 int test(int n) 
     1638int graph_draw(struct emu_graph *graph); 
     1639 
     1640int test(struct emu *e) 
    16191641{ 
    1620         int i=0; 
    1621         struct emu *e = emu_new(); 
     1642//      int i=0; 
    16221643        struct emu_cpu *cpu = emu_cpu_get(e); 
    16231644        struct emu_memory *mem = emu_memory_get(e); 
     
    16581679 
    16591680 
    1660         for ( i=0;i<sizeof(tests)/sizeof(struct instr_test);i++ ) 
    1661         { 
    1662                 if ( n != -1 && i != n && !opts.from_stdin ) 
    1663                         continue; 
    1664  
    1665 //              int failed = 0; 
    1666                 if (!opts.from_stdin) 
    1667                         printf("testing (#%d) '%s' \t", i, tests[i].instr); 
    1668  
    1669                 int j=0; 
    1670  
    1671                 /* set the registers to the initial values */ 
    1672                 for ( j=0;j<8;j++ ) 
    1673                 { 
    1674                         emu_cpu_reg32_set(cpu,j ,tests[i].in_state.reg[j]); 
    1675                 } 
    1676  
    1677  
    1678                 /* set the flags */ 
    1679                 emu_cpu_eflags_set(cpu,tests[i].in_state.eflags); 
    1680  
    1681  
    1682                 /* write the code to the offset */ 
    1683                 int static_offset = CODE_OFFSET; 
    1684                 if (!opts.from_stdin) 
    1685                 emu_memory_write_block(mem, static_offset, tests[i].code,  tests[i].codesize); 
    1686                 else 
    1687                         emu_memory_write_block(mem, static_offset, opts.scode,  opts.size); 
    1688  
    1689  
    1690  
    1691                 /* set eip to the code */ 
    1692                 emu_cpu_eip_set(emu_cpu_get(e), static_offset + opts.offset); 
    1693  
    1694                 /* run the code */ 
     1681        int j=0; 
     1682 
     1683 
     1684        /* run the code */ 
     1685        if ( opts.verbose >= 2 ) 
     1686        { 
     1687                emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
     1688                emu_cpu_debug_print(cpu); 
     1689                emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
     1690        } 
     1691 
     1692 
     1693        struct emu_vertex *last_vertex = NULL; 
     1694        struct emu_graph *graph = NULL; 
     1695        struct emu_hashtable *eh = NULL; 
     1696        struct emu_hashtable_item *ehi = NULL; 
     1697 
     1698        if ( opts.graphfile != NULL ) 
     1699        { 
     1700                graph = emu_graph_new(); 
     1701                eh = emu_hashtable_new(2047, hash, cmp); 
     1702        } 
     1703 
     1704 
     1705        int ret; //= emu_cpu_run(emu_cpu_get(e)); 
     1706 
     1707 
     1708 
     1709        uint32_t eipsave = 0; 
     1710        for ( j=0;j<opts.steps;j++ ) 
     1711        { 
     1712 
    16951713                if ( opts.verbose >= 2 ) 
    16961714                { 
     
    17011719 
    17021720 
    1703                 struct emu_vertex *last_vertex = NULL; 
    1704                 struct emu_graph *graph = NULL; 
    1705                 struct emu_hashtable *eh = NULL; 
    1706                 struct emu_hashtable_item *ehi = NULL; 
     1721 
     1722                if ( cpu->repeat_current_instr == false ) 
     1723                        eipsave = emu_cpu_eip_get(emu_cpu_get(e)); 
     1724 
     1725                struct emu_env_w32_dll_export *dllhook = NULL; 
     1726                struct emu_vertex *ev = NULL; 
     1727                struct instr_vertex *iv = NULL; 
     1728 
     1729 
     1730 
     1731                ret = 0; 
    17071732 
    17081733                if ( opts.graphfile != NULL ) 
    17091734                { 
    1710                         graph = emu_graph_new(); 
    1711                         eh = emu_hashtable_new(2047, hash, cmp); 
     1735 
     1736                        ehi = emu_hashtable_search(eh, (void *)eipsave); 
     1737                        if ( ehi != NULL ) 
     1738                                ev = (struct emu_vertex *)ehi->value; 
     1739 
     1740                        if ( ev == NULL ) 
     1741                        { 
     1742                                ev = emu_vertex_new(); 
     1743                                emu_graph_vertex_add(graph, ev); 
     1744 
     1745                                emu_hashtable_insert(eh, (void *)eipsave, ev); 
     1746                        } 
     1747 
     1748                        if ( last_vertex != NULL ) 
     1749                        { 
     1750                                struct emu_edge *ee = emu_vertex_edge_add(last_vertex, ev); 
     1751                                struct emu_cpu *cpu = emu_cpu_get(e); 
     1752                                if ( cpu->instr.is_fpu == 0 && cpu->instr.source.cond_pos == eipsave && cpu->instr.source.has_cond_pos == 1 ) 
     1753                                        ee->data = (void *)0x1; 
     1754                        } 
     1755 
     1756                        last_vertex = ev; 
    17121757                } 
    17131758 
    1714  
    1715                 int ret; //= emu_cpu_run(emu_cpu_get(e)); 
    1716  
    1717  
    1718  
    1719                 uint32_t eipsave = 0; 
    1720                 for ( j=0;j<opts.steps;j++ ) 
     1759                dllhook = emu_env_w32_eip_check(env); 
     1760 
     1761                if ( dllhook != NULL ) 
    17211762                { 
    1722  
    1723                         if ( opts.verbose >= 2 ) 
     1763                        if ( opts.graphfile != NULL && ev->data == NULL ) 
     1764                        { 
     1765                                iv = instr_vertex_new(eipsave,dllhook->fnname); 
     1766                                emu_vertex_data_set(ev, iv); 
     1767 
     1768                                // get the dll 
     1769                                int numdlls=0; 
     1770                                while ( env->loaded_dlls[numdlls] != NULL ) 
     1771                                { 
     1772                                        if ( eipsave > env->loaded_dlls[numdlls]->baseaddr &&  
     1773                                                 eipsave < env->loaded_dlls[numdlls]->baseaddr + env->loaded_dlls[numdlls]->imagesize ) 
     1774                                        { 
     1775                                                iv->dll = env->loaded_dlls[numdlls]; 
     1776                                        } 
     1777                                        numdlls++; 
     1778                                } 
     1779 
     1780                        } 
     1781 
     1782                        if ( dllhook->fnhook == NULL ) 
     1783                                break; 
     1784 
     1785                } 
     1786                else 
     1787                { 
     1788 
     1789                        ret = emu_cpu_parse(emu_cpu_get(e)); 
     1790 
     1791                        if ( opts.verbose >= 1 ) 
    17241792                        { 
    17251793                                emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
    1726                                 emu_cpu_debug_print(cpu); 
     1794                                logDebug(e, "%s\n", cpu->instr_string); 
    17271795                                emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
    17281796                        } 
    17291797 
    1730  
    1731                          
    1732                         if (cpu->repeat_current_instr == false) 
    1733                                 eipsave = emu_cpu_eip_get(emu_cpu_get(e)); 
    1734  
    1735                         struct emu_env_w32_dll_export *dllhook = NULL; 
    1736                         struct emu_vertex *ev = NULL; 
    1737                         struct instr_vertex *iv = NULL; 
    1738  
    1739  
    1740  
    1741                         ret = 0; 
    1742  
    1743                         if ( opts.graphfile != NULL ) 
     1798                        struct emu_env_linux_syscall *syscall =NULL; 
     1799                        if ( ret != -1 ) 
    17441800                        { 
    17451801 
    1746                                 ehi = emu_hashtable_search(eh, (void *)eipsave); 
    1747                                 if ( ehi != NULL ) 
    1748                                         ev = (struct emu_vertex *)ehi->value; 
    1749  
    1750                                 if ( ev == NULL ) 
     1802                                if ( ( syscall = emu_env_linux_syscall_check(lenv)) != NULL ) 
    17511803                                { 
    1752                                         ev = emu_vertex_new(); 
    1753                                         emu_graph_vertex_add(graph, ev); 
    1754  
    1755                                         emu_hashtable_insert(eh, (void *)eipsave, ev); 
    1756                                 } 
    1757  
    1758                                 if ( last_vertex != NULL ) 
    1759                                 { 
    1760                                         struct emu_edge *ee = emu_vertex_edge_add(last_vertex, ev); 
    1761                                         struct emu_cpu *cpu = emu_cpu_get(e); 
    1762                                         if ( cpu->instr.is_fpu == 0 && cpu->instr.source.cond_pos == eipsave && cpu->instr.source.has_cond_pos == 1 ) 
    1763                                                 ee->data = (void *)0x1; 
    1764                                 } 
    1765  
    1766                                 last_vertex = ev; 
    1767                         } 
    1768  
    1769                         dllhook = emu_env_w32_eip_check(env); 
    1770  
    1771                         if ( dllhook != NULL ) 
    1772                         { 
    1773                                 if ( opts.graphfile != NULL && ev->data == NULL ) 
    1774                                 { 
    1775                                         iv = instr_vertex_new(eipsave,dllhook->fnname); 
    1776                                         emu_vertex_data_set(ev, iv); 
    1777  
    1778                                         // get the dll 
    1779                                         int numdlls=0; 
    1780                                         while ( env->loaded_dlls[numdlls] != NULL ) 
     1804                                        if ( opts.graphfile != NULL && ev->data == NULL ) 
    17811805                                        { 
    1782                                                 if ( eipsave > env->loaded_dlls[numdlls]->baseaddr &&  
    1783                                                          eipsave < env->loaded_dlls[numdlls]->baseaddr + env->loaded_dlls[numdlls]->imagesize ) 
    1784                                                 { 
    1785                                                         iv->dll = env->loaded_dlls[numdlls]; 
    1786                                                 } 
    1787                                                 numdlls++; 
    1788                                         } 
    1789  
    1790                                 } 
    1791  
    1792                                 if ( dllhook->fnhook == NULL ) 
    1793                                         break; 
    1794  
    1795                         } 
    1796                         else 
    1797                         { 
    1798  
    1799                                 ret = emu_cpu_parse(emu_cpu_get(e)); 
    1800  
    1801                                 if ( opts.verbose >= 1 ) 
    1802                                 { 
    1803                                         emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
    1804                                         logDebug(e, "%s\n", cpu->instr_string); 
    1805                                         emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
    1806                                 } 
    1807  
    1808                                 struct emu_env_linux_syscall *syscall =NULL; 
    1809                                 if ( ret != -1 ) 
    1810                                 { 
    1811  
    1812                                         if ( ( syscall = emu_env_linux_syscall_check(lenv)) != NULL) 
    1813                                         { 
    1814                                                 if ( opts.graphfile != NULL && ev->data == NULL ) 
    1815                                                 { 
    1816                                                         iv = instr_vertex_new(eipsave, syscall->name); 
    1817                                                         emu_vertex_data_set(ev, iv); 
    1818                                                         iv->syscall = syscall; 
    1819                                                 } 
    1820                                         }else 
    1821                                         { 
    1822                                          
    1823                                                 if ( opts.graphfile != NULL && ev->data == NULL ) 
    1824                                                 { 
    1825                                                         iv = instr_vertex_new(eipsave, emu_cpu_get(e)->instr_string); 
    1826                                                         emu_vertex_data_set(ev, iv); 
    1827                                                 } 
     1806                                                iv = instr_vertex_new(eipsave, syscall->name); 
     1807                                                emu_vertex_data_set(ev, iv); 
     1808                                                iv->syscall = syscall; 
    18281809                                        } 
    18291810                                } 
    18301811                                else 
    18311812                                { 
     1813 
    18321814                                        if ( opts.graphfile != NULL && ev->data == NULL ) 
    18331815                                        { 
    1834                                                 iv = instr_vertex_new(eipsave, "ERROR"); 
     1816                                                iv = instr_vertex_new(eipsave, emu_cpu_get(e)->instr_string); 
    18351817                                                emu_vertex_data_set(ev, iv); 
    18361818                                        } 
    18371819                                } 
    1838  
    1839                                 if ( ret != -1 ) 
     1820                        } 
     1821                        else 
     1822                        { 
     1823                                if ( opts.graphfile != NULL && ev->data == NULL ) 
    18401824                                { 
    1841                                         if ( syscall == NULL ) 
     1825                                        iv = instr_vertex_new(eipsave, "ERROR"); 
     1826                                        emu_vertex_data_set(ev, iv); 
     1827                                } 
     1828                        } 
     1829 
     1830                        if ( ret != -1 ) 
     1831                        { 
     1832                                if ( syscall == NULL ) 
     1833                                { 
     1834 
     1835                                        if ( opts.verbose >= 2 ) 
    18421836                                        { 
    1843  
    1844                                                 if ( opts.verbose >= 2 ) 
    1845                                                 { 
    1846                                                         emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
    1847                                                         ret = emu_cpu_step(emu_cpu_get(e)); 
    1848                                                         emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
    1849                                                 } 
    1850                                                 else 
    1851                                                 { 
    1852                                                         ret = emu_cpu_step(emu_cpu_get(e)); 
    1853                                                 } 
     1837                                                emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
     1838                                                ret = emu_cpu_step(emu_cpu_get(e)); 
     1839                                                emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
    18541840                                        } 
    18551841                                        else 
    18561842                                        { 
    1857                                                 if (syscall->fnhook != NULL) 
    1858                                                         syscall->fnhook(lenv, syscall); 
    1859                                                 else 
    1860                                                         break; 
     1843                                                ret = emu_cpu_step(emu_cpu_get(e)); 
    18611844                                        } 
    18621845                                } 
    1863  
    1864                                 if ( ret == -1 ) 
     1846                                else 
    18651847                                { 
    1866                                         printf("cpu error %s\n", emu_strerror(e)); 
    1867                                         break; 
     1848                                        if ( syscall->fnhook != NULL ) 
     1849                                                syscall->fnhook(lenv, syscall); 
     1850                                        else 
     1851                                                break; 
    18681852                                } 
    18691853                        } 
    18701854 
     1855                        if ( ret == -1 ) 
     1856                        { 
     1857                                printf("cpu error %s\n", emu_strerror(e)); 
     1858                                break; 
     1859                        } 
     1860                } 
     1861 
    18711862//                      printf("\n"); 
    1872                 } 
    1873  
    1874                 printf("stepcount %i\n",j); 
    1875  
    1876  
    1877                 if ( opts.graphfile != NULL ) 
    1878                 { 
    1879  
    1880                         struct emu_vertex *ev; 
    1881                         struct instr_vertex *iv; 
    1882  
    1883                         FILE *f = fopen(opts.graphfile,"w+"); 
    1884  
    1885                         struct emu_graph *sgraph = emu_graph_new(); 
    1886                         struct emu_hashtable *ht = emu_hashtable_new(2047, hash, cmp); 
    1887  
    1888                         struct emu_vertex *nev; 
    1889                         struct instr_vertex *niv=NULL; 
    1890  
    1891                         printf("copying vertexes\n"); 
    1892                         for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
    1893                         { 
    1894                                 iv = (struct instr_vertex *)ev->data; 
    1895  
    1896                                 nev = emu_vertex_new(); 
    1897                                 emu_graph_vertex_add(sgraph, nev); 
    1898  
    1899                                 niv = instr_vertex_copy(iv);  
    1900                                 nev->data = niv; 
    1901  
    1902                                 emu_hashtable_insert(ht, (void *)iv->eip, nev); 
    1903                                 ev->color = white; 
    1904                         } 
    1905  
    1906                         printf("optimizing graph\n"); 
    1907                         for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
    1908                         { 
    1909                                 // ignore known  
    1910                                 if ( ev->color == black ) 
    1911                                         continue; 
    1912  
    1913  
    1914                                 printf("vertex %08x\n", (unsigned int)ev); 
    1915  
    1916                                 // find the first in a chain 
    1917                                 iv = (struct instr_vertex *)ev->data; 
    1918                                 while ( emu_edges_length(ev->backedges) == 1 && emu_edges_length(ev->edges) <= 1 && ev->color == white && iv->dll == NULL && iv->syscall == NULL ) 
    1919                                 { 
    1920                                         ev->color = grey; 
    1921  
    1922                                         struct emu_vertex *xev = emu_edges_first(ev->backedges)->destination; 
    1923                                         iv = (struct instr_vertex *)xev->data; 
    1924                                         if ( emu_edges_length(xev->backedges) > 1 || emu_edges_length(xev->edges) > 1 || iv->dll != NULL || iv->syscall != NULL ) 
    1925                                                 break; 
    1926  
    1927                                         ev = xev; 
    1928                                         printf(" -> vertex %08x\n",(unsigned int)ev); 
    1929                                 } 
    1930  
    1931  
    1932                                 iv = (struct instr_vertex *)ev->data; 
    1933  
    1934                                 // create the new vertex  
    1935                                 nev = (struct emu_vertex *)emu_hashtable_search(ht, (void *)iv->eip)->value; 
    1936                                 niv = (struct instr_vertex *)nev->data; 
    1937  
    1938                                 iv = (struct instr_vertex *)ev->data; 
    1939  
    1940                                 printf("going forwards from %08x\n", (unsigned int)ev); 
    1941                                 while ( emu_edges_length(ev->edges) == 1 && emu_edges_length(ev->backedges) <= 1 && ev->color != black && iv->dll == NULL && iv->syscall == NULL ) 
    1942                                 { 
    1943                                         ev->color = black; 
    1944                                         struct emu_vertex *xev = emu_edges_first(ev->edges)->destination; 
    1945                                         iv = (struct instr_vertex *)xev->data; 
    1946  
    1947                                         if ( emu_edges_length(xev->backedges) > 1 || emu_edges_length(xev->edges) > 1 || 
    1948                                                  iv->dll != NULL || iv->syscall != NULL ) 
    1949                                                 break; 
    1950  
    1951                                         ev = xev; 
    1952  
    1953                                         iv = (struct instr_vertex *)ev->data; 
    1954                                         emu_string_append_char(niv->instr_string, emu_string_char(iv->instr_string)); 
    1955                                         printf(" -> vertex %08x\n",(unsigned int)ev); 
    1956                                 } 
    1957  
    1958                                 ev->color = black; 
    1959  
    1960                                 printf("copying edges for %08x\n",(unsigned int)ev); 
    1961                                 struct emu_edge *ee; 
    1962                                 for ( ee = emu_edges_first(ev->edges); !emu_edges_attail(ee); ee = emu_edges_next(ee) ) 
    1963                                 { 
    1964                                         struct instr_vertex *ivto = emu_vertex_data_get(ee->destination); 
    1965                                         struct emu_hashtable_item *ehi = emu_hashtable_search(ht, (void *)ivto->eip); 
    1966                                         struct emu_vertex *to = (struct emu_vertex *)ehi->value; 
    1967                                         if (1)// nev != to )//&& to->color != black ) 
    1968                                         { 
    1969                                                 struct emu_edge *nee = emu_vertex_edge_add(nev, to); 
    1970                                                 nee->count = ee->count; 
    1971                                                 nee->data = ee->data; 
    1972                                                 printf(" -> %08x\n", (unsigned int)to); 
    1973                                         } 
    1974                                 } 
    1975  
    1976                         } 
    1977  
    1978                         graph->vertex_destructor = instr_vertex_destructor; 
    1979                         emu_graph_free(graph); 
    1980                         graph = sgraph; 
    1981  
    1982                         emu_hashtable_free(ht); 
    1983                         fprintf(f, "digraph G {\n\trankdir=LR\n"); 
    1984  
    1985 #if 0 
    1986                         int numdlls=0; 
    1987                         while ( env->loaded_dlls[numdlls] != NULL ) 
    1988                         { 
    1989                                 int has_dll = 0; 
    1990                                 struct emu_string *fs = emu_string_new(); 
    1991                                 emu_string_append_format(fs, "\t subgraph cluster%i {\n\t\t node [shape=box, style=filled, color=\".7 .3 1.0\"];\n\t\tstyle=filled;\n\t\tcolor=lightgrey;\n\t\tlabel=\"%s\"\n\t\t", numdlls, env->loaded_dlls[numdlls]->dllname); 
    1992                                 for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
    1993                                 { 
    1994                                         struct instr_vertex *iv = emu_vertex_data_get(ev); 
    1995                                         if ( iv->dll == env->loaded_dlls[numdlls] ) 
    1996                                         { 
    1997                                                 emu_string_append_format(fs, "\t\%i [label = \"%s\"];\n", iv->eip, emu_string_char(iv->instr_string)); 
    1998  
    1999                                                 has_dll = 1; 
    2000                                         } 
    2001  
    2002                                 } 
    2003  
    2004                                 emu_string_append_char(fs, "\t}\n"); 
    2005  
    2006                                 fprintf(f, "%s", emu_string_char(fs)); 
    2007                                 numdlls++; 
    2008                         } 
    2009 #endif // 0 
    2010                         for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
    2011                         { 
    2012                                 if ( emu_edges_length(ev->edges) == 0 && emu_edges_length(ev->backedges) == 0 ) 
    2013                                         continue; 
    2014  
    2015                                 struct instr_vertex *iv = emu_vertex_data_get(ev); 
    2016 #if 0 
    2017                                 if ( iv->dll != NULL ) 
    2018                                         continue; 
    2019 #endif // 0 
    2020                                 if ( iv->dll != NULL || iv->syscall != NULL ) 
    2021                                         fprintf(f, "\t %i [shape=box, style=filled, color=\".7 .3 1.0\", label = \"%s\"]\n",iv->eip, emu_string_char(iv->instr_string)); 
    2022                                 else 
    2023                                         fprintf(f, "\t %i [shape=box, label = \"%s\"]\n",iv->eip, emu_string_char(iv->instr_string)); 
    2024                         } 
    2025  
    2026                         for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
    2027                         { 
    2028                                 struct instr_vertex *ivfrom = emu_vertex_data_get(ev); 
    2029  
    2030                                 struct emu_edge *ee; 
    2031                                 for ( ee = emu_edges_first(ev->edges); !emu_edges_attail(ee); ee = emu_edges_next(ee) ) 
    2032                                 { 
    2033                                         struct instr_vertex *ivto = emu_vertex_data_get(ee->destination); 
    2034                                         struct emu_string *fs = emu_string_new(); 
    2035  
    2036                                         if ( ee->data != (void *)0x0 ) 
    2037                                                 emu_string_append_format(fs, "\t %i -> %i [style = dashed", ivfrom->eip, ivto->eip); 
    2038                                         else 
    2039                                                 emu_string_append_format(fs, "\t %i -> %i [style = bold", ivfrom->eip, ivto->eip); 
    2040  
    2041                                         if ( ee->count > 100 ) 
    2042                                                 emu_string_append_char(fs, ", color=red"); 
    2043                                         else 
    2044                                                 if ( ee->count > 50 ) 
    2045                                                 emu_string_append_char(fs, ", color=blue"); 
    2046                                         else 
    2047                                                 if ( ee->count > 25 ) 
    2048                                                 emu_string_append_char(fs, ", color=green"); 
    2049                                         else 
    2050                                                 if ( ee->count > 1 ) 
    2051                                                 emu_string_append_char(fs, ", color=orange"); 
    2052  
    2053  
    2054  
    2055                                         emu_string_append_char(fs, " ]\n"); 
    2056  
    2057                                         fprintf(f, "%s", emu_string_char(fs)); 
    2058                                         emu_string_free(fs); 
    2059                                 } 
    2060  
    2061                         } 
    2062  
    2063  
    2064                         fprintf(f, "}"); 
    2065                         fclose(f); 
    2066  
    2067                 } 
    2068                 if ( opts.verbose >= 2 ) 
    2069                 { 
    2070                         emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
    2071                         emu_cpu_debug_print(cpu); 
    2072                         emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
    2073                 } 
    2074  
    2075                 if ( opts.graphfile != NULL ) 
    2076                 { 
    2077                         graph->vertex_destructor = instr_vertex_destructor; 
    2078                         emu_graph_free(graph); 
    2079                         emu_hashtable_free(eh); 
    2080                 } 
    2081  
    2082                 if (opts.from_stdin) 
    2083                         break; 
    20841863        } 
     1864 
     1865        printf("stepcount %i\n",j); 
     1866 
     1867 
     1868        if ( opts.graphfile != NULL ) 
     1869        { 
     1870                graph_draw(graph); 
     1871        } 
     1872        if ( opts.verbose >= 2 ) 
     1873        { 
     1874                emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG); 
     1875                emu_cpu_debug_print(cpu); 
     1876                emu_log_level_set(emu_logging_get(e),EMU_LOG_NONE); 
     1877        } 
     1878 
     1879 
     1880        emu_profile_debug(env->profile); 
     1881         
    20851882        emu_env_w32_free(env); 
    20861883        emu_free(e); 
     
    20881885} 
    20891886 
    2090  
     1887int graph_draw(struct emu_graph *graph) 
     1888
     1889        struct emu_vertex *ev; 
     1890        struct instr_vertex *iv; 
     1891 
     1892        FILE *f = fopen(opts.graphfile,"w+"); 
     1893 
     1894        struct emu_graph *sgraph = emu_graph_new(); 
     1895        struct emu_hashtable *ht = emu_hashtable_new(2047, hash, cmp); 
     1896 
     1897        struct emu_vertex *nev; 
     1898        struct instr_vertex *niv=NULL; 
     1899 
     1900        printf("copying vertexes\n"); 
     1901        for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
     1902        { 
     1903                iv = (struct instr_vertex *)ev->data; 
     1904 
     1905                nev = emu_vertex_new(); 
     1906                emu_graph_vertex_add(sgraph, nev); 
     1907 
     1908                niv = instr_vertex_copy(iv);  
     1909                nev->data = niv; 
     1910 
     1911                emu_hashtable_insert(ht, (void *)iv->eip, nev); 
     1912                ev->color = white; 
     1913        } 
     1914 
     1915        printf("optimizing graph\n"); 
     1916        for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
     1917        { 
     1918                // ignore known  
     1919                if ( ev->color == black ) 
     1920                        continue; 
     1921 
     1922 
     1923                printf("vertex %08x\n", (unsigned int)ev); 
     1924 
     1925                // find the first in a chain 
     1926                iv = (struct instr_vertex *)ev->data; 
     1927                while ( emu_edges_length(ev->backedges) == 1 && emu_edges_length(ev->edges) <= 1 && ev->color == white && iv->dll == NULL && iv->syscall == NULL ) 
     1928                { 
     1929                        ev->color = grey; 
     1930 
     1931                        struct emu_vertex *xev = emu_edges_first(ev->backedges)->destination; 
     1932                        iv = (struct instr_vertex *)xev->data; 
     1933                        if ( emu_edges_length(xev->backedges) > 1 || emu_edges_length(xev->edges) > 1 || iv->dll != NULL || iv->syscall != NULL ) 
     1934                                break; 
     1935 
     1936                        ev = xev; 
     1937                        printf(" -> vertex %08x\n",(unsigned int)ev); 
     1938                } 
     1939 
     1940 
     1941                iv = (struct instr_vertex *)ev->data; 
     1942 
     1943                // create the new vertex  
     1944                nev = (struct emu_vertex *)emu_hashtable_search(ht, (void *)iv->eip)->value; 
     1945                niv = (struct instr_vertex *)nev->data; 
     1946 
     1947                iv = (struct instr_vertex *)ev->data; 
     1948 
     1949                printf("going forwards from %08x\n", (unsigned int)ev); 
     1950                while ( emu_edges_length(ev->edges) == 1 && emu_edges_length(ev->backedges) <= 1 && ev->color != black && iv->dll == NULL && iv->syscall == NULL ) 
     1951                { 
     1952                        ev->color = black; 
     1953                        struct emu_vertex *xev = emu_edges_first(ev->edges)->destination; 
     1954                        iv = (struct instr_vertex *)xev->data; 
     1955 
     1956                        if ( emu_edges_length(xev->backedges) > 1 || emu_edges_length(xev->edges) > 1 || 
     1957                                 iv->dll != NULL || iv->syscall != NULL ) 
     1958                                break; 
     1959 
     1960                        ev = xev; 
     1961 
     1962                        iv = (struct instr_vertex *)ev->data; 
     1963                        emu_string_append_char(niv->instr_string, emu_string_char(iv->instr_string)); 
     1964                        printf(" -> vertex %08x\n",(unsigned int)ev); 
     1965                } 
     1966 
     1967                ev->color = black; 
     1968 
     1969                printf("copying edges for %08x\n",(unsigned int)ev); 
     1970                struct emu_edge *ee; 
     1971                for ( ee = emu_edges_first(ev->edges); !emu_edges_attail(ee); ee = emu_edges_next(ee) ) 
     1972                { 
     1973                        struct instr_vertex *ivto = emu_vertex_data_get(ee->destination); 
     1974                        struct emu_hashtable_item *ehi = emu_hashtable_search(ht, (void *)ivto->eip); 
     1975                        struct emu_vertex *to = (struct emu_vertex *)ehi->value; 
     1976                        if ( 1 )// nev != to )//&& to->color != black ) 
     1977                        { 
     1978                                struct emu_edge *nee = emu_vertex_edge_add(nev, to); 
     1979                                nee->count = ee->count; 
     1980                                nee->data = ee->data; 
     1981                                printf(" -> %08x\n", (unsigned int)to); 
     1982                        } 
     1983                } 
     1984 
     1985        } 
     1986 
     1987        graph->vertex_destructor = instr_vertex_destructor; 
     1988        emu_graph_free(graph); 
     1989        graph = sgraph; 
     1990 
     1991        emu_hashtable_free(ht); 
     1992        fprintf(f, "digraph G {\n\t//rankdir=LR\n\tnode [fontname=Courier, labeljust=r];\n"); 
     1993 
     1994#if 0 
     1995        int numdlls=0; 
     1996        while ( env->loaded_dlls[numdlls] != NULL ) 
     1997        { 
     1998                int has_dll = 0; 
     1999                struct emu_string *fs = emu_string_new(); 
     2000                emu_string_append_format(fs, "\t subgraph cluster%i {\n\t\t node [shape=box, style=filled, color=\".7 .3 1.0\"];\n\t\tstyle=filled;\n\t\tcolor=lightgrey;\n\t\tlabel=\"%s\"\n\t\t", numdlls, env->loaded_dlls[numdlls]->dllname); 
     2001                for ( ev = emu_vertexes_first(graph->vertexes); !emu_vertexes_attail(ev); ev = emu_vertexes_next(ev) ) 
     2002                { 
     2003                        struct instr_vertex *iv = emu_vertex_data_get(ev); 
     2004