Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jreversepro/revengine/JDisAssembler.java


1   /*
2    * @(#)JDisAssembler.java
3    *
4    * JReversePro - Java Decompiler / Disassembler.
5    * Copyright (C) 2000 2001 Karthik Kumar.
6    * EMail: akkumar@users.sourceforge.net
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it , under the terms of the GNU General Public License as published
10   * by the Free Software Foundation; either version 2 of the License,
11   * or (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16   * See the GNU General Public License for more details.
17   * You should have received a copy of the GNU General Public License
18   * along with this program.If not, write to
19   *  The Free Software Foundation, Inc.,
20   *  59 Temple Place - Suite 330,
21   *  Boston, MA 02111-1307, USA.
22   */
23  package jreversepro.revengine;
24  
25  
26  import java.util.List;
27  import java.util.Enumeration;
28  
29  import java.io.IOException;
30  import java.util.Collections;
31  
32  
33  //import jreversepro.common.Helper;
34  //import jreversepro.common.JJvmSet;
35  import jreversepro.common.JJvmOpcodes;
36  import jreversepro.reflect.JConstantPool;
37  import jreversepro.reflect.JInstruction;
38  import jreversepro.reflect.JMethod;
39  import jreversepro.reflect.JImport;
40  
41  import jreversepro.parser.ClassParserException;
42  
43  import jreversepro.runtime.JSymbolTable;
44  
45  /**
46   *  <b>JDisAssembler</b> writes out the assebly byte codes.
47   * @author Karthik Kumar
48   **/
49  public class JDisAssembler implements JReverseEngineer, JJvmOpcodes {
50  
51      /**
52       * byteIns is the Vector of instructions. Individual elements are
53       * JInstruction.
54       **/
55      List byteIns;
56  
57      /**
58       * ConstantPool Information.
59       **/
60      JConstantPool cpInfo;
61  
62      /**
63       * Reference to current method.
64       **/
65      JMethod curMethod;
66  
67      /**
68       * @param rhsMethod Method for which the disassembler is going to act.
69       * @param rhsCpInfo ConstantPool Information.
70       **/
71      public JDisAssembler(JMethod rhsMethod,
72                            JConstantPool rhsCpInfo) {
73          byteIns = rhsMethod.getInstructions();
74          cpInfo =  rhsCpInfo;
75          curMethod = rhsMethod;
76      }
77  
78      /**
79       * Generates the disassembled code.
80       * @throws IOException Thrown incase we encounter any i/o erro
81       * while disassembling.
82       * @throws RevEngineException Thrown in case we encounter any
83       * logical error while trying to disasseble.
84       * @throws ClassParserException Thrown in case of an invalid 
85       * constantpool reference.
86       **/
87      public void genCode()
88                  throws RevEngineException,
89                              IOException,
90                          ClassParserException {
91  
92          StringBuffer assembly = new StringBuffer("\t{");
93          //assembly.append(JDecompiler.getMethodHeaders(curMethod, null));
94          assembly.append(curMethod.getLocalStackInfo());
95  
96          try {
97              JImport importInfo = cpInfo.getImportedClasses();
98              curMethod.setSymbolTable(
99                                  new JSymbolTable(curMethod, importInfo));
100                 
101             Enumeration enum  = Collections.enumeration(byteIns);
102             while (enum.hasMoreElements()) {
103                 JInstruction thisIns = (JInstruction) enum.nextElement();
104                 if (thisIns.opcode == OPCODE_TABLESWITCH) {
105                     JSwitchTable switches = new JSwitchTable(
106                                     curMethod, thisIns, null);
107                     assembly.append("\n\t\t"  +  thisIns.index + ": ");
108                     assembly.append("tableswitch ");
109                     assembly.append(switches.disassemble());
110                 } else if (thisIns.opcode == OPCODE_LOOKUPSWITCH) {
111                     JSwitchTable switches  = new JSwitchTable(
112                                     curMethod, thisIns, null);
113                     assembly.append("\n\t\t"  +  thisIns.index + ": ");
114                     assembly.append("lookupswitch ");
115                     assembly.append(switches.disassemble());
116                 } else if (thisIns.opcode == OPCODE_WIDE) {
117                     //Handling to be done here.
118                 } else {
119                     dealDefault(assembly, thisIns);
120                 }
121             }
122         } catch (RevEngineException  ree) {
123             assembly.append(DECOMPILE_FAILED_MSG);
124         }
125         assembly.append("\n\t}");
126         curMethod.setStringifiedBytecode(assembly.toString());
127         //curmethod.setSymbolTable(symTable);
128         // donno why -- doesnt seem to be initialized.
129     }
130 
131     /**
132      * Method to generate code for normal instructions.
133      * Switch and wide instructions need special care. 
134      * See JSwitchTable for more details.
135      * Wide instructions are not supported as of now.
136      * @param assembly StringBuffer containing the code generated.
137      * @param thisIns Current Instruction.
138      * @throws ClassParserException Thrown in case of an invalid 
139      * constantpool reference.
140      **/
141     private void dealDefault(StringBuffer assembly, JInstruction thisIns)
142                     throws ClassParserException {
143         assembly.append("\n\t\t"  +  thisIns.index + ": ");
144         String ins = thisIns.getInsName();
145         assembly.append(ins);
146         if (thisIns.args == null) {
147             return;
148         }
149         int len = thisIns.args.length;
150         if (len == 1) {
151             int thisByte = thisIns.getArgUnsignedByte();
152             if (thisIns.opcode >= OPCODE_LDC 
153                 && thisIns.opcode  <= OPCODE_LDC2_W) {
154                     
155                 assembly.append(" #");
156                 //Indicates an index to the Constant Pool
157                 assembly.append(thisByte + " <");
158                 assembly.append(cpInfo.getTagDescriptor(thisByte));
159                 assembly.append(" >");
160             } else {
161                 assembly.append(" " + thisByte);
162             }
163         } else if (len == 2) {
164             int value = thisIns.getArgUnsignedShort();
165             assembly.append(" ");
166             if (ins.indexOf("if") != -1 
167                 || thisIns.opcode == OPCODE_GOTO  
168                 || thisIns.opcode == OPCODE_JSR) {
169                     
170                 assembly.append(thisIns.getTargetPc());
171             } else if (thisIns.opcode == OPCODE_IINC) {
172                 assembly.append(thisIns.getArgUnsignedByte() + " " 
173                                 + thisIns.getArgUnsignedByte(1));
174             } else if (thisIns.opcode == OPCODE_SIPUSH) {
175                 assembly.append(value);
176             } else {
177                 assembly.append("#");
178                 //Indicates an index to the Constant Pool
179                 assembly.append(value + " <");
180                 assembly.append(cpInfo.getTagDescriptor(value));
181                 assembly.append(" >");
182             }
183         } else if (len == 4) {
184             int value = thisIns.getArgUnsignedShort();
185             assembly.append(" #");
186             //Indicates an index to the Constant Pool
187             assembly.append(value + " <");
188             assembly.append(cpInfo.getTagDescriptor(value));
189             assembly.append(" >");
190         }
191     }
192 }