home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / disasm / source / runtime_dasm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  12.3 KB  |  420 lines

  1. #include "ruleset.h"
  2. #include "runtime_dasm.h"
  3. #include "utils.h"
  4.  
  5. char *apply_ruleset(VDDisassemblyContext *pContext, const ruleset *rs, int *sp, char *hp, const uint8 *source, int bytes, const uint8 *&source_end);
  6. char *VDDisasmMatchRule(VDDisassemblyContext *pContext, const unsigned char *source, const unsigned char *pattern, int pattern_len, int bytes, int *sp, char *hp, const unsigned char *&source_end);
  7.  
  8. void *VDDisasmDecompress(void *_dst, const unsigned char *src, int src_len) {
  9.     const unsigned char *src_limit = src + src_len;
  10.     unsigned char *dst = (unsigned char *)_dst;
  11.  
  12.     // read ruleset count
  13.     int rulesets = *src++;
  14.     unsigned char **prstab = (unsigned char **)dst;
  15.  
  16.     dst += sizeof(unsigned char *) * (rulesets + 1);
  17.  
  18.     // decompress rulesets sequentially
  19.     for(int rs=0; rs<rulesets; ++rs) {
  20.         prstab[rs+1] = dst;
  21.  
  22.         const unsigned char *pattern_cache[4][2];
  23.         const unsigned char *result_cache[4][2];
  24.  
  25.         while(src[0] || src[1]) {
  26.             unsigned char packctl;
  27.             int packsrc, cnt;
  28.  
  29.             // read pack control uint8 and copy prematch-literal-postmatch for pattern
  30.             packctl = *src++;
  31.             packsrc = packctl >> 6;
  32.  
  33.             int prematch = (packctl & 7) * 2;
  34.             int postmatch = ((packctl>>3) & 7) * 2;
  35.             int literal = (*src++ - 1) * 2;
  36.  
  37.             *dst++ = literal + prematch + postmatch;
  38.  
  39.             const unsigned char *pattern_start = dst;
  40.  
  41.             for(cnt=0; cnt<prematch; ++cnt)
  42.                 *dst++ = pattern_cache[packsrc][0][cnt];
  43.  
  44.             for(cnt=0; cnt<literal; ++cnt)
  45.                 *dst++ = *src++;
  46.  
  47.             for(cnt=0; cnt<postmatch; ++cnt)
  48.                 *dst++ = pattern_cache[packsrc][1][cnt-postmatch];
  49.  
  50.             // cycle pattern cache
  51.  
  52.             for(cnt=3; cnt>0; --cnt) {
  53.                 pattern_cache[cnt][0] = pattern_cache[cnt-1][0];
  54.                 pattern_cache[cnt][1] = pattern_cache[cnt-1][1];
  55.             }
  56.  
  57.             pattern_cache[0][0] = pattern_start;
  58.             pattern_cache[0][1] = dst;
  59.  
  60.             // read pack control uint8 and copy prematch-literal-postmatch for result
  61.  
  62.             packctl = *src++;
  63.             packsrc = packctl >> 6;
  64.  
  65.             prematch = (packctl & 7);
  66.             postmatch = ((packctl>>3) & 7);
  67.             literal = (*src++ - 1);
  68.  
  69.             *dst++ = prematch + postmatch + literal;
  70.  
  71.             const unsigned char *result_start = dst;
  72.  
  73.             for(cnt=0; cnt<prematch; ++cnt)
  74.                 *dst++ = result_cache[packsrc][0][cnt];
  75.  
  76.             for(cnt=0; cnt<literal; ++cnt)
  77.                 *dst++ = *src++;
  78.  
  79.             for(cnt=0; cnt<postmatch; ++cnt)
  80.                 *dst++ = result_cache[packsrc][1][cnt-postmatch];
  81.  
  82.             // cycle result cache
  83.  
  84.             for(cnt=3; cnt>0; --cnt) {
  85.                 result_cache[cnt][0] = result_cache[cnt-1][0];
  86.                 result_cache[cnt][1] = result_cache[cnt-1][1];
  87.             }
  88.  
  89.             result_cache[0][0] = result_start;
  90.             result_cache[0][1] = dst;
  91.         }
  92.  
  93.         src += 2;
  94.  
  95.         *dst++ = 0;
  96.         *dst++ = 0;
  97.     }
  98.  
  99.     prstab[0] = prstab[rulesets];
  100.  
  101.     return dst;
  102. }
  103.  
  104. long VDDisasmPack32(const int *src) {
  105.     return src[0] + (src[1]<<8) + (src[2]<<16) + (src[3]<<24);
  106. }
  107.  
  108. void VDDisasmExpandRule(VDDisassemblyContext *pContext, char *s, const unsigned char *result, const int *sp_base, const unsigned char *source) {
  109.     static const char *const reg64[16]={"rax","rcx","rdx","rbx","rsp","rbp","rsi","rdi","r8" ,"r9" ,"r10" ,"r11" ,"r12" ,"r13" ,"r14" ,"r15" };
  110.     static const char *const reg32[16]={"eax","ecx","edx","ebx","esp","ebp","esi","edi","r8d","r9d","r10d","r11d","r12d","r13d","r14d","r15d"};
  111.     static const char *const reg16[16]={ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di","r8w","r9w","r10w","r11w","r12w","r13w","r14w","r15w"};
  112.     static const char *const reg8a[16]={ "al"," cl", "dl", "bl","spl","bpl","sil","dil","r8b","r9b","r10b","r11b","r12b","r13b","r14b","r15b"};
  113.     static const char *const reg8 [16]={"al","cl","dl","bl","ah","ch","dh","bh"};
  114.     static const char *const regmmx[8]={"mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"};
  115.     static const char *const regxmm[16]={"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15"};
  116.     static const char *const regcrn[8]={"cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"};
  117.     static const char *const regdrn[8]={"dr0","dr1","dr2","dr3","dr4","dr5","dr6","dr7"};
  118.     static const char *const regseg[8]={"es","cs","ss","ds","fs","gs","?6s","?7s"};
  119.     static const char *const regf[8]={"st(0)","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"};
  120.  
  121.     static const char *const *const sStaticLabels[]={
  122.         reg32,
  123.         reg16,
  124.         reg8,
  125.         regmmx,
  126.         regxmm,
  127.         regcrn,
  128.         regdrn,
  129.         regseg,
  130.         regf
  131.     };
  132.  
  133.     const unsigned char *result_limit = result + result[0]+1;
  134.  
  135.     ++result;
  136.  
  137.     while(result < result_limit) {
  138.         char c = *result++;
  139.  
  140.         if ((unsigned char)(c&0x7f) < 32) {
  141.             if (c & 0x80) {
  142.                 c &= 0x7f;
  143.                 *s++ = ' ';
  144.             }
  145.  
  146.             static const unsigned char static_bitfields[8]={
  147.                 0x80, 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
  148.             };
  149.  
  150.             unsigned char control_byte = (unsigned char)*result++;
  151.             unsigned char bitfield = static_bitfields[control_byte >> 5];
  152.  
  153.             if (!bitfield)
  154.                 bitfield = (unsigned char)*result++;
  155.  
  156.             int bf_start = bitfield & 15;
  157.             int bf_siz = bitfield>>4;
  158.             const char *arg_s = (const char *)sp_base[c-1];
  159.             int arg = (sp_base[c-1] >> bf_start) & ((1<<bf_siz)-1);
  160.  
  161.             control_byte &= 0x1f;
  162.  
  163.             if (control_byte < 10) {
  164.                 s = strtack(s, sStaticLabels[control_byte-1][arg]);
  165.             } else {
  166.                 long symoffset = 0;
  167.  
  168.                 switch(control_byte) {
  169.                 case kTarget_r1632:
  170.                     s = strtack(s, reg32[arg] + pContext->bSizeOverride);
  171.                     break;
  172.                 case kTarget_rmx:
  173.                     s = strtack(s, (pContext->bSizeOverride ? regxmm : regmmx)[arg]);
  174.                     break;
  175.                 case kTarget_lx:
  176.                     symoffset = VDDisasmPack32(sp_base + c - 1);
  177.                     s += sprintf(s, "%08lxh", symoffset);
  178.                     break;
  179.                 case kTarget_hx:
  180.                     s += sprintf(s, "%02x%02xh"
  181.                                 , (unsigned char)sp_base[c]
  182.                                 , (unsigned char)sp_base[c-1]
  183.                                 );
  184.                     break;
  185.                 case kTarget_x:
  186.                     s += sprintf(s, "0%02xh" + ((unsigned char)arg < 0xa0), arg);
  187.                     break;
  188.                 case kTarget_lo:
  189.                     symoffset = VDDisasmPack32(sp_base + c - 1);
  190.                     s += sprintf(s, "%c%02lxh", symoffset<0 ? '-' : '+', abs(symoffset));
  191.                     break;
  192.                 case kTarget_ho:
  193.                     {
  194.                         short x =  ((unsigned char)sp_base[c  ] << 8)
  195.                                 +  (unsigned char)sp_base[c-1];
  196.  
  197.                         s += sprintf(s, "%c%02lxh", x<0 ? '-' : '+', abs(x));
  198.                     }
  199.                     break;
  200.                 case kTarget_o:
  201.                     s += sprintf(s, "%c%02xh", arg&0x80?'-':'+', abs((signed char)arg));
  202.                     break;
  203.                 case kTarget_la:
  204.                     symoffset = (long)source + VDDisasmPack32(sp_base + c - 1) + pContext->physToVirtOffset;
  205.                     s += sprintf(s, "%08lxh", symoffset);
  206.                     break;
  207.                 case kTarget_ha:
  208.                     symoffset = (long)source + (signed short)(sp_base[c-1] + (sp_base[c]<<8)) + pContext->physToVirtOffset;
  209.                     s += sprintf(s, "%08lxh", symoffset);
  210.                     break;
  211.                 case kTarget_a:
  212.                     symoffset = (long)source + (signed char)arg + pContext->physToVirtOffset;
  213.                     s += sprintf(s, "%08lxh", symoffset);
  214.                     break;
  215.                 case kTarget_s:
  216.                     s = strtack(s, arg_s);
  217.                     break;
  218.                 case kTarget_r3264:
  219.                     s = strtack(s, (pContext->rex & 8 ? reg32 : reg64)[arg + ((pContext->rex & 0x04) << 1)]);
  220.                     break;
  221.                 case kTarget_r163264:
  222.                     s = strtack(s, (pContext->rex & 8 ? reg64 : pContext->bSizeOverride ? reg16 : reg32)[arg + ((pContext->rex & 0x04) << 1)]);
  223.                     break;
  224.                 case kTarget_ext:
  225.                     switch(*result++) {
  226.                     case kTarget_ext_r3264rexX:
  227.                         s = strtack(s, (pContext->bAddressOverride ? reg32 : reg64)[arg + ((pContext->rex & 0x02) << 2)]);
  228.                         break;
  229.                     case kTarget_ext_r3264rexB:
  230.                         s = strtack(s, (pContext->bAddressOverride ? reg32 : reg64)[arg + ((pContext->rex & 0x01) << 3)]);
  231.                         break;
  232.                     case kTarget_ext_r163264rexB:
  233.                         s = strtack(s, (pContext->rex & 8 ? reg64 : pContext->bSizeOverride ? reg16 : reg32)[arg + ((pContext->rex & 0x01) << 3)]);
  234.                         break;
  235.                     }
  236.                     break;
  237.                 }
  238.  
  239.                 if (symoffset && pContext->pSymLookup) {
  240.                     symoffset = pContext->pSymLookup((unsigned long)symoffset, s+2, 128);
  241.  
  242.                     if (symoffset >= 0) {
  243.                         s[0] = ' ';
  244.                         s[1] = '(';
  245.                         s += 2;
  246.                         while(*s)
  247.                             ++s;
  248.                         if (symoffset)
  249.                             s += sprintf(s, "+%02xh", symoffset);
  250.                         *s++ = ')';
  251.                     }
  252.                 }
  253.             }
  254.         } else if ((unsigned char)c >= 0xe0) {
  255.             switch(c) {
  256.             case kTarget_ap:
  257.                 if (pContext->pszSegmentOverride) {
  258.                     s = strtack(s, pContext->pszSegmentOverride);
  259.                     *s++ = ':';
  260.                 }
  261.                 break;
  262.             case kTarget_p_cs:    pContext->pszSegmentOverride = regseg[1];    break;
  263.             case kTarget_p_ss:    pContext->pszSegmentOverride = regseg[2];    break;
  264.             case kTarget_p_ds:    pContext->pszSegmentOverride = regseg[3];    break;
  265.             case kTarget_p_es:    pContext->pszSegmentOverride = regseg[0];    break;
  266.             case kTarget_p_fs:    pContext->pszSegmentOverride = regseg[4];    break;
  267.             case kTarget_p_gs:    pContext->pszSegmentOverride = regseg[5];    break;
  268.             case kTarget_p_66:    pContext->bSizeOverride = true;                break;
  269.             case kTarget_p_67:    pContext->bAddressOverride = true;            break;
  270.             case kTarget_p_F2:    pContext->bRepnePrefix = true;                break;
  271.             case kTarget_p_F3:    pContext->bRepePrefix = true;                break;
  272.             case kTarget_p_rex:    pContext->rex = sp_base[0];                    break;
  273.             }
  274.         } else
  275.             *s++ = c;
  276.     }
  277.  
  278.     *s = 0;
  279. }
  280.  
  281. char *VDDisasmApplyRuleset(VDDisassemblyContext *pContext, const unsigned char *rs, int *sp, char *hp, const unsigned char *source, int bytes, const uint8 *&source_end) {
  282.     char *hpr;
  283.  
  284.     while(rs[0] || rs[1]) {
  285.         const unsigned char *src_end;
  286.         const unsigned char *result = rs + rs[0] + 1;
  287.         const unsigned char *match_next = result + result[0] + 1;
  288.  
  289.         hpr = VDDisasmMatchRule(pContext, source, rs+1, rs[0]>>1, bytes, sp, hp, src_end);
  290.  
  291.         if (hpr) {
  292.             VDDisasmExpandRule(pContext, hpr, result, sp, src_end);
  293.  
  294.             source_end = src_end;
  295.             return hpr;
  296.         }
  297.  
  298.         rs = match_next;
  299.     }
  300.  
  301.     return NULL;
  302. }
  303.  
  304. char *VDDisasmMatchRule(VDDisassemblyContext *pContext, const unsigned char *source, const unsigned char *pattern, int pattern_len, int bytes, int *sp, char *hp, const unsigned char *&source_end) {
  305.     while(bytes && pattern_len) {
  306.         if (!pattern[1] && pattern[0]) {
  307.             if (pattern[0] & 0x80) {
  308.                 int count = pattern[0] & 0x3f;
  309.  
  310.                 if (pattern[0] & 0x40) {
  311.                     --source;
  312.                     ++bytes;
  313.                 }
  314.             
  315.                 const uint8 *src_end;
  316.  
  317.                 hp = VDDisasmApplyRuleset(pContext, pContext->pRuleSystem[count+1], sp, hp, source, bytes, src_end);
  318.  
  319.                 if (!hp)
  320.                     return NULL;
  321.  
  322.                 *sp++ = *source;
  323.                 *sp++ = (int)hp;
  324.  
  325.                 while(*hp++);
  326.  
  327.                 source = src_end;
  328.             } else if (pattern[0] < 16) {
  329.                 if (pattern[0] > bytes)
  330.                     return NULL;
  331.  
  332.                 for(int i=0; i<pattern[0]; ++i) {
  333.                     *sp++ = *source++;
  334.                 }
  335.  
  336.                 bytes -= pattern[0]-1;
  337.             } else {
  338.                 switch(pattern[0]) {
  339.                 case 16:    if (!pContext->bSizeOverride)        return NULL;    break;
  340.                 case 17:    if (!pContext->bAddressOverride)    return NULL;    break;
  341.                 case 18:    if (!pContext->bRepnePrefix)        return NULL;    break;
  342.                 case 19:    if (!pContext->bRepePrefix)            return NULL;    break;
  343.                 case 20:    if (pContext->pszSegmentOverride)    return NULL;    break;
  344.                 case 21:    if (!(pContext->rex & 8))            return NULL;    break;
  345.                 }
  346.             }
  347.         } else {
  348.             uint8 b = *source++;
  349.  
  350.             if ((b & pattern[1]) != pattern[0])
  351.                 return NULL;
  352.  
  353.             *sp++ = b;
  354.         }
  355.         pattern += 2;
  356.         --bytes;
  357.         --pattern_len;
  358.     }
  359.  
  360.     if (!pattern_len) {
  361.         source_end = source;
  362.         return hp;
  363.     }
  364.  
  365.     return NULL;
  366. }
  367.  
  368. void VDDisassemble(VDDisassemblyContext *pvdc, const uint8 *source, int bytes) {
  369.     while(bytes > 0) {
  370.         const uint8 *src2 = source;
  371.         const uint8 *src_end;
  372.         char *s;
  373.  
  374.         pvdc->bAddressOverride = false;
  375.         pvdc->bSizeOverride = false;
  376.         pvdc->bRepePrefix = false;
  377.         pvdc->bRepnePrefix = false;
  378.         pvdc->pszSegmentOverride = NULL;
  379.         pvdc->rex = 0;
  380.  
  381.         do {
  382.             s = VDDisasmApplyRuleset(pvdc, pvdc->pRuleSystem[0], pvdc->stack, pvdc->heap, src2, bytes, src_end);
  383.  
  384.             bytes -= (src_end - src2);
  385.             src2 = src_end;
  386.         } while(!*s && bytes);
  387.  
  388.         if (!bytes)
  389.             break;
  390.  
  391.         int count = src_end - source;
  392.         int linecnt;
  393.  
  394.         printf("%08lx: ", (unsigned long)source + pvdc->physToVirtOffset);
  395.  
  396.         for(linecnt=0; linecnt<7 && source < src_end; ++linecnt)
  397.             printf("%02x", (unsigned char)*source++);
  398.  
  399.         char *t = s;
  400.         while(*t && *t != ' ')
  401.             ++t;
  402.  
  403.         if (*t)
  404.             *t++ = 0;
  405.  
  406.         printf("%*c%-7s%s\n", 2 + 2*(7-linecnt), ' ', s, t);
  407.  
  408.         // flush remaining bytes
  409.  
  410.         while(source < src_end) {
  411.             printf("         ");
  412.             for(linecnt=0; linecnt<7 && source < src_end; ++linecnt)
  413.                 printf(" %02x", (unsigned char)*source++);
  414.             putchar('\n');
  415.         }
  416.  
  417.         bytes -= count;
  418.     }
  419. }
  420.