Changeset 800 in svn for trunk/Decompiler.class.php


Ignore:
Timestamp:
2011-04-27T02:45:42Z (4 years ago)
Author:
Xuefer
Message:

Decompiler: use range to simplify calling

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Decompiler.class.php

    r799 r800  
    555555    }
    556556    // }}}
    557     function outputPhp(&$EX, $opline, $last, $indent) // {{{
     557    function outputPhp(&$EX, $range, $indent) // {{{
    558558    {
    559559        $needBlankline = isset($EX['lastBlock']);
    560560        $origindent = $indent;
    561561        $curticks = 0;
    562         for ($i = $opline; $i <= $last; $i ++) {
     562        for ($i = $range[0]; $i <= $range[1]; $i ++) {
    563563            $op = $EX['opcodes'][$i];
    564564            if (isset($op['gofrom'])) {
     
    699699    }
    700700    // }}}
    701     function decompileBasicBlock(&$EX, $first, $last, $indent) // {{{
    702     {
    703         $this->dasmBasicBlock($EX, $first, $last);
    704         // $this->dumpRange($EX, $first, $last, $indent);
    705         $this->outputPhp($EX, $first, $last, $indent);
     701    function decompileBasicBlock(&$EX, $range, $indent) // {{{
     702    {
     703        $this->dasmBasicBlock($EX, $range);
     704        // $this->dumpRange($EX, $range, $indent);
     705        $this->outputPhp($EX, $range, $indent);
    706706    }
    707707    // }}}
     
    732732    }
    733733    // }}}
    734     function decompileComplexBlock(&$EX, $first, $last, $indent) // {{{
     734    function decompileComplexBlock(&$EX, $range, $indent) // {{{
    735735    {
    736736        $T = &$EX['Ts'];
    737737        $opcodes = &$EX['opcodes'];
    738738
    739         $firstOp = &$opcodes[$first];
    740         $lastOp = &$opcodes[$last];
     739        $firstOp = &$opcodes[$range[0]];
     740        $lastOp = &$opcodes[$range[1]];
    741741
    742742        // {{{ ?: excludign JMP_SET
    743743        if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts'])
    744          && $last >= $first + 3
     744         && $range[1] >= $range[0] + 3
    745745         && $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN
    746          && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $last + 1
     746         && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1
    747747         && $lastOp['opcode'] == XC_QM_ASSIGN
    748748        ) {
    749             $trueFirst = $first + 1;
    750             $trueLast = $firstOp['jmpouts'][0] - 2;
    751             $falseFirst = $firstOp['jmpouts'][0];
    752             $falseLast = $last;
    753             $this->removeJmpInfo($EX, $first);
     749            $trueRange = array($range[0] + 1, $firstOp['jmpouts'][0] - 2);
     750            $falseRange = array($firstOp['jmpouts'][0], $range[1]);
     751            $this->removeJmpInfo($EX, $range[0]);
    754752
    755753            $condition = $this->getOpVal($firstOp['op1'], $EX);
    756             $this->recognizeAndDecompileClosedBlocks($EX, $trueFirst, $trueLast, $indent . INDENT);
    757             $trueValue = $this->getOpVal($opcodes[$trueLast]['op1'], $EX, false, true);
    758             $this->recognizeAndDecompileClosedBlocks($EX, $falseFirst, $falseLast, $indent . INDENT);
    759             $falseValue = $this->getOpVal($opcodes[$falseLast]['op1'], $EX, false, true);
    760             $T[$opcodes[$trueLast]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue);
     754            $this->recognizeAndDecompileClosedBlocks($EX, $trueRange, $indent . INDENT);
     755            $trueValue = $this->getOpVal($opcodes[$trueRange[1]]['op1'], $EX, false, true);
     756            $this->recognizeAndDecompileClosedBlocks($EX, $falseRange, $indent . INDENT);
     757            $falseValue = $this->getOpVal($opcodes[$falseRange[1]]['op1'], $EX, false, true);
     758            $T[$opcodes[$trueRange[1]]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue);
    761759            return false;
    762760        }
     
    767765            $catchFirst = $firstOp['jmpins'][0];
    768766
    769             $tryFirst = $first;
    770             $tryLast = $catchFirst - 1;
     767            $tryRange = array($range[0], $catchFirst - 1);
    771768
    772769            // search for XC_CATCH
    773770            $this->removeJmpInfo($EX, $catchFirst);
    774             for ($i = $catchFirst; $i <= $last; ) {
     771            for ($i = $catchFirst; $i <= $range[1]; ) {
    775772                if ($opcodes[$i]['opcode'] == XC_CATCH) {
    776773                    $catchOpLine = $i;
     
    792789            }
    793790
    794             if ($opcodes[$tryLast]['opcode'] == XC_JMP) {
    795                 --$tryLast;
     791            if ($opcodes[$tryRange[1]]['opcode'] == XC_JMP) {
     792                --$tryRange[1];
    796793            }
    797794
    798795            $this->beginComplexBlock($EX);
    799796            echo $indent, "try {", PHP_EOL;
    800             $this->recognizeAndDecompileClosedBlocks($EX, $tryFirst, $tryLast, $indent . INDENT);
     797            $this->recognizeAndDecompileClosedBlocks($EX, $tryRange, $indent . INDENT);
    801798            echo $indent, '}', PHP_EOL;
    802799            foreach ($catchBlocks as $catchFirst => $catchInfo) {
    803800                list($catchOpLine, $catchBodyLast) = $catchInfo;
    804801                $catchBodyFirst = $catchOpLine + 1;
    805                 $this->recognizeAndDecompileClosedBlocks($EX, $catchFirst, $catchOpLine, $indent);
     802                $this->recognizeAndDecompileClosedBlocks($EX, array($catchFirst, $catchOpLine), $indent);
    806803                $catchOp = &$opcodes[$catchOpLine];
    807804                echo $indent, 'catch (', str($this->getOpVal($catchOp['op1'], $EX)), ' ', str($this->getOpVal($catchOp['op2'], $EX)), ") {", PHP_EOL;
     
    809806
    810807                $EX['lastBlock'] = null;
    811                 $this->recognizeAndDecompileClosedBlocks($EX, $catchBodyFirst, $catchBodyLast, $indent . INDENT);
     808                $this->recognizeAndDecompileClosedBlocks($EX, array($catchBodyFirst, $catchBodyLast), $indent . INDENT);
    812809                echo $indent, '}', PHP_EOL;
    813810            }
     
    835832            $caseDefault = null;
    836833            $caseOp = null;
    837             for ($i = $first; $i <= $last; ) {
     834            for ($i = $range[0]; $i <= $range[1]; ) {
    838835                $op = $opcodes[$i];
    839836                if ($op['opcode'] == XC_CASE) {
     
    907904                }
    908905
    909                 $this->recognizeAndDecompileClosedBlocks($EX, $caseFirst, $caseLast, $indent . INDENT);
     906                $this->recognizeAndDecompileClosedBlocks($EX, array($caseFirst, $caseLast), $indent . INDENT);
    910907                $caseIsOut = true;
    911908            }
     
    918915        // {{{ do/while
    919916        if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts'])
    920          && $lastOp['jmpouts'][0] == $first) {
    921             $this->removeJmpInfo($EX, $last);
     917         && $lastOp['jmpouts'][0] == $range[0]) {
     918            $this->removeJmpInfo($EX, $range[1]);
    922919            $this->beginComplexBlock($EX);
    923920
    924921            echo $indent, "do {", PHP_EOL;
    925             $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
     922            $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT);
    926923            echo $indent, "} while (", str($this->getOpVal($lastOp['op1'], $EX)), ');', PHP_EOL;
    927924
     
    934931        $firstJmp = null;
    935932        $firstJmpOp = null;
    936         for ($i = $first; $i <= $last; ++$i) {
     933        for ($i = $range[0]; $i <= $range[1]; ++$i) {
    937934            if (!empty($opcodes[$i]['jmpouts'])) {
    938935                $firstJmp = $i;
     
    946943        if (isset($firstJmpOp)
    947944         && $firstJmpOp['opcode'] == XC_JMPZ
    948          && $firstJmpOp['jmpouts'][0] > $last
     945         && $firstJmpOp['jmpouts'][0] > $range[1]
    949946         && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
    950          && $lastOp['jmpouts'][0] == $first) {
     947         && $lastOp['jmpouts'][0] == $range[0]) {
    951948            $this->removeJmpInfo($EX, $firstJmp);
    952             $this->removeJmpInfo($EX, $last);
     949            $this->removeJmpInfo($EX, $range[1]);
    953950            $this->beginComplexBlock($EX);
    954951
    955952            ob_start();
    956             $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
     953            $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT);
    957954            $body = ob_get_clean();
    958955
     
    968965        if (isset($firstJmpOp)
    969966         && $firstJmpOp['opcode'] == XC_FE_FETCH
    970          && $firstJmpOp['jmpouts'][0] > $last
     967         && $firstJmpOp['jmpouts'][0] > $range[1]
    971968         && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
    972969         && $lastOp['jmpouts'][0] == $firstJmp) {
    973970            $this->removeJmpInfo($EX, $firstJmp);
    974             $this->removeJmpInfo($EX, $last);
     971            $this->removeJmpInfo($EX, $range[1]);
    975972            $this->beginComplexBlock($EX);
    976973
    977974            ob_start();
    978             $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
     975            $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT);
    979976            $body = ob_get_clean();
    980977
     
    993990        // }}}
    994991
    995         $this->decompileBasicBlock($EX, $first, $last, $indent);
     992        $this->decompileBasicBlock($EX, $range, $indent);
    996993    }
    997994    // }}}
    998     function recognizeAndDecompileClosedBlocks(&$EX, $first, $last, $indent) // {{{ decompile in a tree way
     995    function recognizeAndDecompileClosedBlocks(&$EX, $range, $indent) // {{{ decompile in a tree way
    999996    {
    1000997        $opcodes = &$EX['opcodes'];
    1001998
    1002         $starti = $first;
    1003         for ($i = $starti; $i <= $last; ) {
     999        $starti = $range[0];
     1000        for ($i = $starti; $i <= $range[1]; ) {
    10041001            if (!empty($opcodes[$i]['jmpins']) || !empty($opcodes[$i]['jmpouts'])) {
    10051002                $blockFirst = $i;
     
    10111008                        // care about jumping from blocks behind, not before
    10121009                        foreach ($op['jmpins'] as $oplineNumber) {
    1013                             if ($oplineNumber <= $last && $blockLast < $oplineNumber) {
     1010                            if ($oplineNumber <= $range[1] && $blockLast < $oplineNumber) {
    10141011                                $blockLast = $oplineNumber;
    10151012                            }
     
    10211018                    ++$j;
    10221019                } while ($j <= $blockLast);
    1023                 if (!assert('$blockLast <= $last')) {
    1024                     var_dump($blockLast, $last);
     1020                if (!assert('$blockLast <= $range[1]')) {
     1021                    var_dump($blockLast, $range[1]);
    10251022                }
    10261023
    10271024                if ($blockLast >= $blockFirst) {
    10281025                    if ($blockFirst > $starti) {
    1029                         $this->decompileBasicBlock($EX, $starti, $blockFirst - 1, $indent);
    1030                     }
    1031                     if ($this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent) === false) {
     1026                        $this->decompileBasicBlock($EX, array($starti, $blockFirst - 1), $indent);
     1027                    }
     1028                    if ($this->decompileComplexBlock($EX, array($blockFirst, $blockLast), $indent) === false) {
    10321029                        if ($EX['lastBlock'] == 'complex') {
    10331030                            echo PHP_EOL;
     
    10461043            }
    10471044        }
    1048         if ($starti <= $last) {
    1049             $this->decompileBasicBlock($EX, $starti, $last, $indent);
     1045        if ($starti <= $range[1]) {
     1046            $this->decompileBasicBlock($EX, array($starti, $range[1]), $indent);
    10501047        }
    10511048    }
     
    11611158        $EX['op_array'] = &$op_array;
    11621159        $EX['opcodes'] = &$opcodes;
     1160        $EX['range'] = array(0, count($opcodes) - 1);
    11631161        // func call
    11641162        $EX['object'] = null;
     
    11671165        $EX['argstack'] = array();
    11681166        $EX['arg_types_stack'] = array();
    1169         $EX['last'] = count($opcodes) - 1;
    11701167        $EX['silence'] = 0;
    11711168        $EX['recvs'] = array();
     
    11731170        $EX['lastBlock'] = null;
    11741171
    1175         $first = 0;
    1176         $last = count($opcodes) - 1;
    1177 
    11781172        /* dump whole array
    11791173        $this->keepTs = true;
    1180         $this->dasmBasicBlock($EX, $first, $last);
    1181         for ($i = $first; $i <= $last; ++$i) {
     1174        $this->dasmBasicBlock($EX, $range);
     1175        for ($i = $range[0]; $i <= $range[1]; ++$i) {
    11821176            echo $i, "\t", $this->dumpop($opcodes[$i], $EX);
    11831177        }
    11841178        // */
    11851179        // decompile in a tree way
    1186         $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $EX['indent']);
     1180        $this->recognizeAndDecompileClosedBlocks($EX, $EX['range'], $EX['indent']);
    11871181        return $EX;
    11881182    }
    11891183    // }}}
    1190     function outputCode(&$EX, $opline, $last, $indent, $loop = false) // {{{
    1191     {
    1192         $op = &$EX['opcodes'][$opline];
    1193         $next = $EX['nextbbs'][$opline];
     1184    function outputCode(&$EX, $range, $indent, $loop = false) // {{{
     1185    {
     1186        $op = &$EX['opcodes'][$range[0]];
     1187        $next = $EX['nextbbs'][$range[0]];
    11941188
    11951189        $end = $next - 1;
    1196         if ($end > $last) {
    1197             $end = $last;
     1190        if ($end > $range[1]) {
     1191            $end = $range[1];
    11981192        }
    11991193
     
    12041198            // echo ";;;\n";
    12051199        }
    1206         $this->dasmBasicBlock($EX, $opline, $end);
    1207         $this->outputPhp($EX, $opline, $end, $indent);
     1200        $this->dasmBasicBlock($EX, array($opline, $end));
     1201        $this->outputPhp($EX, array($opline, $end), $indent);
    12081202        // jmpout op
    12091203        $op = &$EX['opcodes'][$end];
     
    12141208
    12151209        if (isset($EX['opcodes'][$next])) {
    1216             if (isset($last) && $next > $last) {
     1210            if (isset($range[1]) && $next > $range[1]) {
    12171211                $next = null;
    12181212            }
     
    12321226                        $cond = $op['cond'];
    12331227                        echo "{$indent}if ($cond) {\n";
    1234                         $this->outputCode($EX, $next, $last, INDENT . $indent);
     1228                        $this->outputCode($EX, $next, $range[1], INDENT . $indent);
    12351229                        echo "$indent}\n";
    1236                         $this->outputCode($EX, $target, $last, $indent);
     1230                        $this->outputCode($EX, $target, $range[1], $indent);
    12371231                        return;
    12381232                    }
     
    12841278                $EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
    12851279            }
    1286             #$this->outputCode($EX, $next, $last, $indent);
     1280            #$this->outputCode($EX, $next, $range[1], $indent);
    12871281            #return;
    12881282        }
     
    12991293        }
    13001294
     1295        $nextRange = array($next, $range[1]);
    13011296        if ($loop) {
    1302             return array($next, $last);
    1303         }
    1304         $this->outputCode($EX, $next, $last, $indent);
     1297            return $nextRange;
     1298        }
     1299        $this->outputCode($EX, $nextRange, $indent);
    13051300    }
    13061301    // }}}
    1307     function dasmBasicBlock(&$EX, $opline, $last) // {{{
     1302    function dasmBasicBlock(&$EX, $range) // {{{
    13081303    {
    13091304        $T = &$EX['Ts'];
     
    13111306        $lastphpop = null;
    13121307
    1313         for ($i = $opline; $i <= $last; $i ++) {
     1308        for ($i = $range[0]; $i <= $range[1]; $i ++) {
    13141309            // {{{ prepair
    13151310            $op = &$opcodes[$i];
     
    18021797
    18031798                    for (;;) {
    1804                         if ($i + 1 <= $last
     1799                        if ($i + 1 <= $range[1]
    18051800                         && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE
    18061801                         && $opcodes[$i + 1]['op1']['var'] == $res['var']) {
    18071802                            // continue
    18081803                        }
    1809                         else if ($i + 2 <= $last
     1804                        else if ($i + 2 <= $range[1]
    18101805                         && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
    18111806                         && $opcodes[$i + 2]['op1']['var'] == $res['var']
     
    22302225    }
    22312226    // }}}
    2232     function dumpRange(&$EX, $first, $last, $indent = '') // {{{
    2233     {
    2234         for ($i = $first; $i <= $last; ++$i) {
     2227    function dumpRange(&$EX, $range, $indent = '') // {{{
     2228    {
     2229        for ($i = $range[0]; $i <= $range[1]; ++$i) {
    22352230            echo $indent, $i, "\t"; $this->dumpop($EX['opcodes'][$i], $EX);
    22362231        }
Note: See TracChangeset for help on using the changeset viewer.