Changeset 795 for trunk


Ignore:
Timestamp:
2011-04-26T07:28:21+02:00 (4 years ago)
Author:
moo
Message:

Decompiler: decompile try/catch

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Decompiler.class.php

    r791 r795  
    615615    function &fixOpcode($opcodes, $removeTailing = false, $defaultReturnValue = null) // {{{ 
    616616    { 
    617         for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) { 
     617        $last = count($opcodes) - 1; 
     618        for ($i = 0; $i <= $last; $i ++) { 
    618619            if (function_exists('xcache_get_fixed_opcode')) { 
    619620                $opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i); 
     
    706707        $lastOp = &$opcodes[$last]; 
    707708 
     709        // {{{ try/catch 
     710        if (!empty($firstOp['jmpins']) && !empty($opcodes[$firstOp['jmpins'][0]]['isCatchBegin'])) { 
     711            $catchBlocks = array(); 
     712            $catchFirst = $firstOp['jmpins'][0]; 
     713 
     714            $tryFirst = $first; 
     715            $tryLast = $catchFirst - 1; 
     716 
     717            // search for XC_CATCH 
     718            $this->removeJmpInfo($EX, $catchFirst); 
     719            for ($i = $catchFirst; $i <= $last; ) { 
     720                if ($opcodes[$i]['opcode'] == XC_CATCH) { 
     721                    $catchOpLine = $i; 
     722                    $this->removeJmpInfo($EX, $catchOpLine); 
     723 
     724                    $catchNext = $opcodes[$catchOpLine]['extended_value']; 
     725                    $catchBodyLast = $catchNext - 1; 
     726                    if ($opcodes[$catchBodyLast]['opcode'] == XC_JMP) { 
     727                        --$catchBodyLast; 
     728                    } 
     729 
     730                    $catchBlocks[$catchFirst] = array($catchOpLine, $catchBodyLast); 
     731 
     732                    $i = $catchFirst = $catchNext; 
     733                } 
     734                else { 
     735                    ++$i; 
     736                } 
     737            } 
     738 
     739            if ($opcodes[$tryLast]['opcode'] == XC_JMP) { 
     740                --$tryLast; 
     741            } 
     742 
     743            $this->beginComplexBlock($EX); 
     744            echo $indent, 'try {', PHP_EOL; 
     745            $this->recognizeAndDecompileClosedBlocks($EX, $tryFirst, $tryLast, $indent . INDENT); 
     746            echo $indent, '}', PHP_EOL; 
     747            foreach ($catchBlocks as $catchFirst => $catchInfo) { 
     748                list($catchOpLine, $catchBodyLast) = $catchInfo; 
     749                $catchBodyFirst = $catchOpLine + 1; 
     750                $this->recognizeAndDecompileClosedBlocks($EX, $catchFirst, $catchOpLine, $indent); 
     751                $catchOp = &$opcodes[$catchOpLine]; 
     752                echo $indent, 'catch (', str($this->getOpVal($catchOp['op1'], $EX)), ' ', str($this->getOpVal($catchOp['op2'], $EX)), ') {', PHP_EOL; 
     753                unset($catchOp); 
     754 
     755                $EX['lastBlock'] = null; 
     756                $this->recognizeAndDecompileClosedBlocks($EX, $catchBodyFirst, $catchBodyLast, $indent . INDENT); 
     757                echo $indent, '}', PHP_EOL; 
     758            } 
     759            $this->endComplexBlock($EX); 
     760            return; 
     761        } 
     762        // }}} 
     763 
    708764        if ($firstOp['opcode'] == XC_SWITCH_FREE && isset($T[$firstOp['op1']['var']])) { 
    709765            // TODO: merge this code to CASE code. use SWITCH_FREE to detect begin of switch by using $Ts if possible 
     
    722778        ) { 
    723779            $cases = array(); 
    724             $caseNext = null; 
    725780            $caseDefault = null; 
    726781            $caseOp = null; 
    727             for ($i = $first; $i <= $last; ++$i) { 
     782            for ($i = $first; $i <= $last; ) { 
    728783                $op = $opcodes[$i]; 
    729784                if ($op['opcode'] == XC_CASE) { 
     
    734789                    assert('$jmpz["opcode"] == XC_JMPZ'); 
    735790                    $caseNext = $jmpz['jmpouts'][0]; 
    736                     $i = $cases[$i] = $caseNext - 1; 
    737                 } 
    738                 else if ($op['opcode'] == XC_JMP) { 
     791                    $cases[$i] = $caseNext - 1; 
     792                    $i = $caseNext; 
     793                } 
     794                else if ($op['opcode'] == XC_JMP && $op['jmpouts'][0] >= $i) { 
    739795                    // default 
    740                     if ($op['jmpouts'][0] >= $i) { 
    741                         $caseNext = $op['jmpouts'][0]; 
    742                         $caseDefault = $i; 
    743                         $i = $cases[$i] = $caseNext - 1; 
    744                     } 
     796                    $caseNext = $op['jmpouts'][0]; 
     797                    $caseDefault = $i; 
     798                    $cases[$i] = $caseNext - 1; 
     799                    $i = $caseNext; 
     800                } 
     801                else { 
     802                    ++$i; 
    745803                } 
    746804            } 
     
    881939 
    882940        $starti = $first; 
    883         for ($i = $starti; $i <= $last; ++$i) { 
    884             $op = $opcodes[$i]; 
    885             if (!empty($op['jmpins']) || !empty($op['jmpouts'])) { 
     941        for ($i = $starti; $i <= $last; ) { 
     942            if (!empty($opcodes[$i]['jmpins']) || !empty($opcodes[$i]['jmpouts'])) { 
    886943                $blockFirst = $i; 
    887944                $blockLast = -1; 
     
    902959                    ++$j; 
    903960                } while ($j <= $blockLast); 
    904                 assert('$blockLast <= $last'); 
     961                if (!assert('$blockLast <= $last')) { 
     962                    var_dump($blockLast, $last); 
     963                } 
    905964 
    906965                if ($blockLast >= $blockFirst) { 
     
    910969                    $this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent); 
    911970                    $starti = $blockLast + 1; 
    912                     $i = $starti - 1; 
    913                     continue; 
    914                 } 
     971                    $i = $starti; 
     972                } 
     973                else { 
     974                    ++$i; 
     975                } 
     976            } 
     977            else { 
     978                ++$i; 
    915979            } 
    916980        } 
     
    924988        $op_array['opcodes'] = $this->fixOpcode($op_array['opcodes'], true, $indent == '' ? 1 : null); 
    925989        $opcodes = &$op_array['opcodes']; 
     990        $last = count($opcodes) - 1; 
    926991        // {{{ build jmpins/jmpouts to op_array 
    927         for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) { 
     992        for ($i = 0; $i <= $last; $i ++) { 
    928993            $op = &$opcodes[$i]; 
    929994            $op['line'] = $i; 
     
    9871052                $opcodes[$i + 2]['jmpins'][] = $i; 
    9881053                break; 
     1054 
     1055            case XC_CATCH: 
     1056                $catchNext = $op['extended_value']; 
     1057                $op['jmpouts'] = array($catchNext); 
     1058                $opcodes[$catchNext]['jmpins'][] = $i; 
     1059                break; 
    9891060            } 
    9901061            /* 
     
    9951066        } 
    9961067        unset($op); 
     1068        if ($op_array['try_catch_array']) { 
     1069            foreach ($op_array['try_catch_array'] as $try_catch_element) { 
     1070                $catch_op = $try_catch_element['catch_op']; 
     1071                $try_op = $try_catch_element['try_op']; 
     1072                $opcodes[$try_op]['jmpins'][] = $catch_op; 
     1073                $opcodes[$catch_op]['jmpouts'][] = $try_op; 
     1074                $opcodes[$catch_op]['isCatchBegin'] = true; 
     1075            } 
     1076        } 
    9971077        // }}} 
    9981078        // build semi-basic blocks 
    9991079        $nextbbs = array(); 
    10001080        $starti = 0; 
    1001         for ($i = 1, $cnt = count($opcodes); $i < $cnt; $i ++) { 
     1081        for ($i = 1; $i <= $last; $i ++) { 
    10021082            if (isset($opcodes[$i]['jmpins']) 
    10031083             || isset($opcodes[$i - 1]['jmpouts'])) { 
     
    10061086            } 
    10071087        } 
    1008         $nextbbs[$starti] = $cnt; 
     1088        $nextbbs[$starti] = $last + 1; 
    10091089 
    10101090        $EX = array(); 
     
    12391319                    // }}} 
    12401320                case XC_CATCH: // {{{ 
    1241                     $resvar = 'catch (' . str($this->getOpVal($op1, $EX)) . ' ' . str($this->getOpVal($op2, $EX)) . ')'; 
    12421321                    break; 
    12431322                    // }}} 
     
    20222101    function dumpop($op, &$EX) // {{{ 
    20232102    { 
     2103        assert('isset($op)'); 
    20242104        $op1 = $op['op1']; 
    20252105        $op2 = $op['op2']; 
     
    20532133                if ($k == 'result') { 
    20542134                    var_dump($op); 
     2135                    assert(0); 
    20552136                    exit; 
    2056                     assert(0); 
    20572137                } 
    20582138                else { 
     
    20622142        } 
    20632143        $d[';'] = $op['extended_value']; 
     2144        if (!empty($op['jmpouts'])) { 
     2145            $d['>>'] = implode(',', $op['jmpouts']); 
     2146        } 
     2147        if (!empty($op['jmpins'])) { 
     2148            $d['<<'] = implode(',', $op['jmpins']); 
     2149        } 
    20642150 
    20652151        foreach ($d as $k => $v) { 
  • trunk/decompilesample.php

    r793 r795  
    257257$a = $b || $c; 
    258258 
    259 try { 
    260     echo 'outer try 1'; 
     259do { 
    261260    try { 
    262         echo 'inner try'; 
    263     } 
    264     catch (InnerException $e) { 
     261        echo 'outer try 1'; 
     262 
     263        try { 
     264            echo 'inner try'; 
     265        } 
     266        catch (InnerException $e) { 
     267            echo $e; 
     268        } 
     269 
     270        echo 'outer try 2'; 
     271    } 
     272    catch (OuterException $e) { 
    265273        echo $e; 
    266274    } 
    267     echo 'outer try 2'; 
    268 } 
    269 catch (OuterException $e) { 
    270     echo $e; 
    271 } 
     275} while (0); 
    272276 
    273277if (if_()) { 
Note: See TracChangeset for help on using the changeset viewer.