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 }