Changeset 787
- Timestamp:
- 04/25/2011 11:46:09 AM (2 years ago)
- Files:
-
- 1 modified
-
trunk/Decompiler.class.php (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Decompiler.class.php
r781 r787 522 522 } 523 523 // }}} 524 function outputPhp(&$ opcodes, $opline, $last, $indent) // {{{524 function outputPhp(&$EX, $opline, $last, $indent) // {{{ 525 525 { 526 526 $origindent = $indent; 527 527 $curticks = 0; 528 528 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 } 530 533 if (isset($op['php'])) { 531 534 $toticks = isset($op['ticks']) ? (int) str($op['ticks']) : 0; … … 648 651 } 649 652 // }}} 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 // }}} 650 762 function &dop_array($op_array, $indent = '') // {{{ 651 763 { 652 764 $op_array['opcodes'] = $this->fixOpcode($op_array['opcodes'], true, $indent == '' ? 1 : null); 653 765 $opcodes = &$op_array['opcodes']; 654 $EX['indent'] = ''; 655 // {{{ build jmp array 766 // {{{ build jmpins/jmpouts to op_array 656 767 for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) { 657 768 $op = &$opcodes[$i]; 658 /*659 if ($op['opcode'] == XC_JMPZ) {660 $this->dumpop($op, $EX);661 var_dump($op);662 }663 continue;664 */665 769 $op['line'] = $i; 666 770 switch ($op['opcode']) { … … 671 775 672 776 case XC_GOTO: 777 $target = $op['op1']['var']; 778 $op['goto'] = $target; 779 $opcodes[$target]['gofrom'][] = $i; 780 break; 781 673 782 case XC_JMP: 674 783 $target = $op['op1']['var']; … … 708 817 */ 709 818 } 819 /* 820 if (!empty($op['jmpouts']) || !empty($op['jmpins'])) { 821 echo $i, "\t", xcache_get_opcode($op['opcode']), PHP_EOL; 822 } 823 // */ 710 824 } 711 825 unset($op); … … 740 854 $EX['uses'] = array(); 741 855 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']); 747 858 return $EX; 748 859 } … … 765 876 } 766 877 $this->dasmBasicBlock($EX, $opline, $end); 767 $this->outputPhp($EX ['opcodes'], $opline, $end, $indent);878 $this->outputPhp($EX, $opline, $end, $indent); 768 879 // jmpout op 769 880 $op = &$EX['opcodes'][$end]; … … 833 944 break; 834 945 835 case XC_GOTO:836 echo $indent, 'goto', ' line', $op['jmpouts'][0], ';', "\n";837 break;838 839 946 default: 840 947 echo $indent; … … 894 1001 $lastphpop = null; 895 1002 896 for ($i = $opline , $ic = $last + 1; $i < $ic; $i ++) {1003 for ($i = $opline; $i <= $last; $i ++) { 897 1004 // {{{ prepair 898 1005 $op = &$opcodes[$i]; … … 1382 1489 1383 1490 for (;;) { 1384 if ($i + 1 < $ic1491 if ($i + 1 <= $last 1385 1492 && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE 1386 1493 && $opcodes[$i + 1]['op1']['var'] == $res['var']) { 1387 1494 // continue 1388 1495 } 1389 else if ($i + 2 < $ic1496 else if ($i + 2 <= $last 1390 1497 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE 1391 1498 && $opcodes[$i + 2]['op1']['var'] == $res['var'] … … 1592 1699 break; 1593 1700 case XC_GOTO: 1701 $resvar = 'goto label' . $op['op1']['var']; 1702 $istmpres = false; 1703 break; 1704 1594 1705 case XC_JMP: // {{{ 1595 1706 $op['cond'] = null; … … 1795 1906 } 1796 1907 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; 1797 1916 } 1798 1917 // }}}

