Changeset 787


Ignore:
Timestamp:
2011-04-25T11:46:09+02:00 (4 years ago)
Author:
moo
Message:

decompile code branch

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Decompiler.class.php

    r781 r787  
    522522    } 
    523523    // }}} 
    524     function outputPhp(&$opcodes, $opline, $last, $indent) // {{{ 
     524    function outputPhp(&$EX, $opline, $last, $indent) // {{{ 
    525525    { 
    526526        $origindent = $indent; 
    527527        $curticks = 0; 
    528528        for ($i = $opline; $i <= $last; $i ++) { 
    529             $op = $opcodes[$i]; 
     529            $op = $EX['opcodes'][$i]; 
     530            if (isset($op['gofrom'])) { 
     531                echo 'label' . $i, ":\n"; 
     532            } 
    530533            if (isset($op['php'])) { 
    531534                $toticks = isset($op['ticks']) ? (int) str($op['ticks']) : 0; 
     
    648651    } 
    649652    // }}} 
     653    function decompileBasicBlock(&$EX, $first, $last, $indent) // {{{ 
     654    { 
     655        $this->dasmBasicBlock($EX, $first, $last); 
     656        // $this->dumpRange($EX, $first, $last); 
     657        $this->outputPhp($EX, $first, $last, $indent); 
     658    } 
     659    // }}} 
     660    function removeJmpInfo(&$EX, $line) // {{{ 
     661    { 
     662        $opcodes = &$EX['opcodes']; 
     663        foreach ($opcodes[$line]['jmpouts'] as $jmpTo) { 
     664            $jmpins = &$opcodes[$jmpTo]['jmpins']; 
     665            $jmpins = array_flip($jmpins); 
     666            unset($jmpins[$line]); 
     667            $jmpins = array_keys($jmpins); 
     668        } 
     669        $opcodes[$line]['opcode'] = XC_NOP; 
     670        unset($opcodes[$line]['jmpouts']); 
     671    } 
     672    // }}} 
     673    function decompileComplexBlock(&$EX, $first, $last, $indent) // {{{ 
     674    { 
     675        $opcodes = &$EX['opcodes']; 
     676 
     677        $firstOp = &$opcodes[$first]; 
     678        $lastOp = &$opcodes[$last]; 
     679 
     680        if ($lastOp['opcode'] == XC_JMPNZ 
     681         && $lastOp['jmpouts'][0] == $first) { 
     682            $this->removeJmpInfo($EX, $last); 
     683            echo $indent, 'do {', PHP_EOL; 
     684            $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT); 
     685            echo $indent, '} while (', str($this->getOpVal($lastOp['op1'], $EX)), ');', PHP_EOL; 
     686            return; 
     687        } 
     688 
     689        $firstJmp = null; 
     690        $firstJmpOp = null; 
     691        for ($i = $first; $i <= $last; ++$i) { 
     692            if (!empty($opcodes[$i]['jmpouts'])) { 
     693                $firstJmp = $i; 
     694                $firstJmpOp = &$opcodes[$firstJmp]; 
     695                break; 
     696            } 
     697        } 
     698 
     699        if (isset($firstJmpOp) 
     700         && $firstJmpOp['opcode'] == XC_JMPZ 
     701         && $lastOp['opcode'] == XC_JMP 
     702         && $lastOp['jmpouts'][0] == $first) { 
     703            $this->removeJmpInfo($EX, $firstJmp); 
     704            $this->removeJmpInfo($EX, $last); 
     705 
     706            ob_start(); 
     707            $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT); 
     708            $code = ob_get_clean(); 
     709            echo $indent, 'while (', str($this->getOpVal($firstJmpOp['op1'], $EX)), ') {', PHP_EOL; 
     710            echo $code; 
     711            echo $indent, '}', PHP_EOL; 
     712            return; 
     713        } 
     714 
     715        $this->decompileBasicBlock($EX, $first, $last, $indent); 
     716    } 
     717    // }}} 
     718    function recognizeAndDecompileClosedBlocks(&$EX, $first, $last, $indent) // {{{ decompile in a tree way 
     719    { 
     720        $opcodes = &$EX['opcodes']; 
     721        $firstComplex = false; 
     722 
     723        $i = $starti = $first; 
     724        while ($i <= $last) { 
     725            $op = $opcodes[$i]; 
     726            if (!empty($op['jmpins']) || !empty($op['jmpouts'])) { 
     727                $blockFirst = $i; 
     728                $blockLast = -1; 
     729                $i = $blockFirst; 
     730                do { 
     731                    if (!empty($op['jmpins'])) { 
     732                        // care about jumping from blocks behind, not before 
     733                        foreach ($op['jmpins'] as $oplineNumber) { 
     734                            if ($oplineNumber <= $last && $blockLast < $oplineNumber) { 
     735                                $blockLast = $oplineNumber; 
     736                            } 
     737                        } 
     738                    } 
     739                    if (!empty($op['jmpouts'])) { 
     740                        $blockLast = max($blockLast, max($op['jmpouts']) - 1); 
     741                    } 
     742                    ++$i; 
     743                } while ($i <= $blockLast); 
     744                assert('$blockLast <= $last'); 
     745 
     746                if ($blockLast >= $blockFirst) { 
     747                    if ($blockFirst > $starti) { 
     748                        $this->decompileBasicBlock($EX, $starti, $blockFirst - 1, $indent); 
     749                    } 
     750                    $this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent); 
     751                    $i = $starti = $blockLast + 1; 
     752                } 
     753                continue; 
     754            } 
     755            ++$i; 
     756        } 
     757        if ($starti <= $last) { 
     758            $this->decompileBasicBlock($EX, $starti, $last, $indent); 
     759        } 
     760    } 
     761    // }}} 
    650762    function &dop_array($op_array, $indent = '') // {{{ 
    651763    { 
    652764        $op_array['opcodes'] = $this->fixOpcode($op_array['opcodes'], true, $indent == '' ? 1 : null); 
    653765        $opcodes = &$op_array['opcodes']; 
    654         $EX['indent'] = ''; 
    655         // {{{ build jmp array 
     766        // {{{ build jmpins/jmpouts to op_array 
    656767        for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) { 
    657768            $op = &$opcodes[$i]; 
    658             /* 
    659             if ($op['opcode'] == XC_JMPZ) { 
    660                 $this->dumpop($op, $EX); 
    661                 var_dump($op); 
    662             } 
    663             continue; 
    664             */ 
    665769            $op['line'] = $i; 
    666770            switch ($op['opcode']) { 
     
    671775 
    672776            case XC_GOTO: 
     777                $target = $op['op1']['var']; 
     778                $op['goto'] = $target; 
     779                $opcodes[$target]['gofrom'][] = $i; 
     780                break; 
     781 
    673782            case XC_JMP: 
    674783                $target = $op['op1']['var']; 
     
    708817            */ 
    709818            } 
     819            /* 
     820            if (!empty($op['jmpouts']) || !empty($op['jmpins'])) { 
     821                echo $i, "\t", xcache_get_opcode($op['opcode']), PHP_EOL; 
     822            } 
     823            // */ 
    710824        } 
    711825        unset($op); 
     
    740854        $EX['uses'] = array(); 
    741855 
    742         for ($next = 0, $last = $EX['last']; 
    743                 $loop = $this->outputCode($EX, $next, $last, $indent, true); 
    744                 list($next, $last) = $loop) { 
    745             // empty 
    746         } 
     856        // decompile in a tree way 
     857        $this->recognizeAndDecompileClosedBlocks($EX, 0, count($opcodes) - 1, $EX['indent']); 
    747858        return $EX; 
    748859    } 
     
    765876        } 
    766877        $this->dasmBasicBlock($EX, $opline, $end); 
    767         $this->outputPhp($EX['opcodes'], $opline, $end, $indent); 
     878        $this->outputPhp($EX, $opline, $end, $indent); 
    768879        // jmpout op 
    769880        $op = &$EX['opcodes'][$end]; 
     
    833944                break; 
    834945 
    835             case XC_GOTO: 
    836                 echo $indent, 'goto', ' line', $op['jmpouts'][0], ';', "\n"; 
    837                 break; 
    838  
    839946            default: 
    840947                echo $indent; 
     
    8941001        $lastphpop = null; 
    8951002 
    896         for ($i = $opline, $ic = $last + 1; $i < $ic; $i ++) { 
     1003        for ($i = $opline; $i <= $last; $i ++) { 
    8971004            // {{{ prepair 
    8981005            $op = &$opcodes[$i]; 
     
    13821489 
    13831490                    for (;;) { 
    1384                         if ($i + 1 < $ic 
     1491                        if ($i + 1 <= $last 
    13851492                         && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE 
    13861493                         && $opcodes[$i + 1]['op1']['var'] == $res['var']) { 
    13871494                            // continue 
    13881495                        } 
    1389                         else if ($i + 2 < $ic 
     1496                        else if ($i + 2 <= $last 
    13901497                         && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE 
    13911498                         && $opcodes[$i + 2]['op1']['var'] == $res['var'] 
     
    15921699                    break; 
    15931700                case XC_GOTO: 
     1701                    $resvar = 'goto label' . $op['op1']['var']; 
     1702                    $istmpres = false; 
     1703                    break; 
     1704 
    15941705                case XC_JMP: // {{{ 
    15951706                    $op['cond'] = null; 
     
    17951906        } 
    17961907        echo PHP_EOL; 
     1908    } 
     1909    // }}} 
     1910    function dumpRange(&$EX, $first, $last) // {{{ 
     1911    { 
     1912        for ($i = $first; $i <= $last; ++$i) { 
     1913            echo $i, "\t"; $this->dumpop($EX['opcodes'][$i], $EX); 
     1914        } 
     1915        echo "==", PHP_EOL; 
    17971916    } 
    17981917    // }}} 
Note: See TracChangeset for help on using the changeset viewer.