added copyright

debugging messages
big rewrites


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@482 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 50add9944b
commit 8ebe96a5ac
  1. 258
      jode/jode/bytecode/BytecodeInfo.java

@ -1,5 +1,26 @@
/* BytecodeInfo Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode; package jode.bytecode;
import jode.Decompiler/*XXX*/; import jode.Decompiler/*XXX*/;
import jode.Type;
import jode.MethodType;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -7,11 +28,21 @@ import java.io.InputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration;
/**
* This class represents the byte code of a method. Each instruction is
* stored in an Instruction instance.
*
* We canocalize some opcodes: wide opcodes are mapped to short ones,
* opcodes that load a constant are mapped to opc_ldc or opc_ldc2_w, and
* opc_xload_x / opc_xstore_x opcodes are mapped to opc_xload / opc_xstore.
*/
public class BytecodeInfo extends BinaryInfo implements Opcodes { public class BytecodeInfo extends BinaryInfo implements Opcodes {
ConstantPool cp; ConstantPool cp;
int maxStack, maxLocals; int maxStack, maxLocals;
int codeLength;
Instruction firstInstr = null; Instruction firstInstr = null;
Handler[] exceptionHandlers; Handler[] exceptionHandlers;
@ -29,14 +60,14 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
this.cp = cp; this.cp = cp;
maxStack = input.readUnsignedShort(); maxStack = input.readUnsignedShort();
maxLocals = input.readUnsignedShort(); maxLocals = input.readUnsignedShort();
int codeLength = input.readInt(); codeLength = input.readInt();
Instruction[] instrs = new Instruction[codeLength]; Instruction[] instrs = new Instruction[codeLength];
int[][] succAddrs = new int[codeLength][]; int[][] succAddrs = new int[codeLength][];
{ {
int addr = 0; int addr = 0;
Instruction lastInstr = null; Instruction lastInstr = null;
while (addr < codeLength) { while (addr < codeLength) {
Instruction instr = new Instruction(); Instruction instr = new Instruction(this);
if (lastInstr != null) { if (lastInstr != null) {
lastInstr.nextByAddr = instr; lastInstr.nextByAddr = instr;
instr.prevByAddr = lastInstr; instr.prevByAddr = lastInstr;
@ -47,7 +78,7 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
int opcode = input.readUnsignedByte(); int opcode = input.readUnsignedByte();
if (Decompiler.isDebugging)/*XXX*/ if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.println(addr+": "+opcodeString[opcode]); Decompiler.err.print(addr+": "+opcodeString[opcode]);
instr.opcode = opcode; instr.opcode = opcode;
switch (opcode) { switch (opcode) {
@ -61,17 +92,25 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
case opc_fstore: case opc_dstore: case opc_astore: case opc_fstore: case opc_dstore: case opc_astore:
instr.localSlot = input.readUnsignedShort(); instr.localSlot = input.readUnsignedShort();
instr.length = 4; instr.length = 4;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+opcodeString[wideopcode]
+" "+instr.localSlot);
break; break;
case opc_ret: case opc_ret:
instr.localSlot = input.readUnsignedShort(); instr.localSlot = input.readUnsignedShort();
instr.length = 4; instr.length = 4;
instr.alwaysJumps = true; instr.alwaysJumps = true;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" ret "+instr.localSlot);
break; break;
case opc_iinc: case opc_iinc:
instr.localSlot = input.readUnsignedShort(); instr.localSlot = input.readUnsignedShort();
instr.intData = input.readShort(); instr.intData = input.readShort();
instr.length = 6; instr.length = 6;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" iinc "+instr.localSlot
+" "+instr.intData);
break; break;
default: default:
throw new ClassFormatError("Invalid wide opcode " throw new ClassFormatError("Invalid wide opcode "
@ -113,29 +152,40 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
case opc_fstore: case opc_dstore: case opc_astore: case opc_fstore: case opc_dstore: case opc_astore:
instr.localSlot = input.readUnsignedByte(); instr.localSlot = input.readUnsignedByte();
instr.length = 2; instr.length = 2;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+instr.localSlot);
break; break;
case opc_ret: case opc_ret:
instr.localSlot = input.readUnsignedByte(); instr.localSlot = input.readUnsignedByte();
instr.alwaysJumps = true; instr.alwaysJumps = true;
instr.length = 2; instr.length = 2;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+instr.localSlot);
break; break;
case opc_aconst_null: case opc_aconst_null:
case opc_iconst_m1: case opc_iconst_m1:
case opc_iconst_0: case opc_iconst_1: case opc_iconst_2: case opc_iconst_0: case opc_iconst_1: case opc_iconst_2:
case opc_iconst_3: case opc_iconst_4: case opc_iconst_5: case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:
case opc_lconst_0: case opc_lconst_1:
case opc_fconst_0: case opc_fconst_1: case opc_fconst_2: case opc_fconst_0: case opc_fconst_1: case opc_fconst_2:
instr.objData = constants[instr.opcode - opc_aconst_null];
instr.opcode = opc_ldc;
instr.length = 1;
break;
case opc_lconst_0: case opc_lconst_1:
case opc_dconst_0: case opc_dconst_1: case opc_dconst_0: case opc_dconst_1:
instr.objData = constants[instr.opcode - opc_aconst_null]; instr.objData = constants[instr.opcode - opc_aconst_null];
instr.opcode = opc_ldc2_w;
instr.length = 1; instr.length = 1;
break; break;
case opc_bipush: case opc_bipush:
instr.opcode = opc_ldc;
instr.objData = new Integer(input.readByte()); instr.objData = new Integer(input.readByte());
instr.length = 2; instr.length = 2;
break; break;
case opc_sipush: case opc_sipush:
instr.opcode = opc_ldc;
instr.objData = new Integer(input.readShort()); instr.objData = new Integer(input.readShort());
instr.length = 3; instr.length = 3;
break; break;
@ -155,6 +205,9 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
instr.localSlot = input.readUnsignedByte(); instr.localSlot = input.readUnsignedByte();
instr.intData = input.readByte(); instr.intData = input.readByte();
instr.length = 3; instr.length = 3;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+instr.localSlot
+" "+instr.intData);
break; break;
case opc_goto: case opc_goto:
@ -172,6 +225,8 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
succAddrs[addr] = new int[1]; succAddrs[addr] = new int[1];
succAddrs[addr][0] = addr+input.readShort(); succAddrs[addr][0] = addr+input.readShort();
instr.length = 3; instr.length = 3;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+succAddrs[addr][0]);
break; break;
case opc_goto_w: case opc_goto_w:
@ -182,6 +237,8 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
succAddrs[addr] = new int[1]; succAddrs[addr] = new int[1];
succAddrs[addr][0] = addr+input.readInt(); succAddrs[addr][0] = addr+input.readInt();
instr.length = 5; instr.length = 5;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+succAddrs[addr][0]);
break; break;
case opc_tableswitch: { case opc_tableswitch: {
@ -232,15 +289,23 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
case opc_putfield: case opc_putfield:
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic: case opc_invokestatic:
case opc_invokevirtual: case opc_invokevirtual: {
instr.objData = cp.getRef(input.readUnsignedShort()); Reference ref = cp.getRef(input.readUnsignedShort());
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+ref);
instr.objData = ref;
instr.length = 3; instr.length = 3;
break; break;
case opc_invokeinterface: }
instr.objData = cp.getRef(input.readUnsignedShort()); case opc_invokeinterface: {
Reference ref = cp.getRef(input.readUnsignedShort());
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.print(" "+ref);
instr.objData = ref;
instr.intData = input.readUnsignedShort(); instr.intData = input.readUnsignedShort();
instr.length = 5; instr.length = 5;
break; break;
}
case opc_new: case opc_new:
case opc_anewarray: case opc_anewarray:
@ -269,6 +334,8 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
instr.length = 1; instr.length = 1;
} }
addr += lastInstr.length; addr += lastInstr.length;
if (Decompiler.isDebugging)/*XXX*/
Decompiler.err.println();
} }
} }
firstInstr = instrs[0]; firstInstr = instrs[0];
@ -310,67 +377,72 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
readAttributes(cp, input, FULLINFO); readAttributes(cp, input, FULLINFO);
} }
public void dumpCode(java.io.PrintStream output) {
for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) {
output.println(instr+ ": " + opcodeString[instr.opcode]);
if (instr.succs != null) {
output.print("\tsuccs: "+instr.succs[0]);
for (int i = 1; i < instr.succs.length; i++)
output.print(", "+instr.succs[i]);
output.println();
}
if (instr.preds.size() > 0) {
Enumeration enum = instr.preds.elements();
output.print("\tpreds: " + enum.nextElement());
while (enum.hasMoreElements())
output.print(", " + enum.nextElement());
output.println();
}
}
}
public void writeCode(GrowableConstantPool gcp, public void prepareWriting(GrowableConstantPool gcp) {
jode.obfuscator.ClassBundle bundle,
DataOutputStream output) throws IOException {
/* Recalculate addr and length */ /* Recalculate addr and length */
int addr = 0; int addr = 0;
next_instr:
for (Instruction instr = firstInstr; for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) { instr != null; addr += instr.length, instr = instr.nextByAddr) {
instr.addr = addr; instr.addr = addr;
if (instr.opcode == opc_ldc) { if (instr.opcode == opc_ldc
if (gcp.reserveConstant(instr.objData) < 256) || instr.opcode == opc_ldc2_w) {
if (instr.objData == null) {
instr.opcode = opc_aconst_null;
instr.length = 1;
continue next_instr;
}
for (int i=1; i < constants.length; i++) {
if (instr.objData.equals(constants[i])) {
instr.opcode = opc_aconst_null+i;
instr.length = 1;
continue next_instr;
}
}
if (instr.opcode == opc_ldc2_w) {
instr.length = 3;
continue;
}
if (instr.objData instanceof Integer) {
int value = ((Integer) instr.objData).intValue();
if (value >= -Byte.MIN_VALUE
&& value <= Byte.MAX_VALUE) {
instr.opcode = opc_bipush;
instr.length = 2; instr.length = 2;
else continue;
} else if (value >= -Short.MIN_VALUE
&& value <= Short.MAX_VALUE) {
instr.opcode = opc_bipush;
instr.length = 2;
continue;
}
}
if (gcp.reserveConstant(instr.objData) < 256) {
instr.opcode = opc_ldc;
instr.length = 2;
} else {
instr.opcode = opc_ldc_w;
instr.length = 3; instr.length = 3;
// if (instr.objData == null) { }
// instr.length = 1;
// } else if (instr.objData instanceof Integer) {
// int value = ((Integer) instr.objData).intValue();
// if (value >= -1 && value <= 5)
// instr.length = 1;
// else if (value >= -Byte.MIN_VALUE
// && value <= Byte.MAX_VALUE)
// instr.length = 2;
// else if (value >= -Short.MIN_VALUE
// && value <= Short.MAX_VALUE)
// instr.length = 3;
// else if (gcp.reserveConstant(instr.objData) < 256)
// instr.length = 2;
// else
// instr.length = 3;
// } else if (instr.objData instanceof Long) {
// long value = ((Long) instr.objData).longValue();
// if (value == 0L || value == 1L)
// instr.length = 1;
// else
// instr.length = 3;
// } else if (instr.objData instanceof Float) {
// float value = ((Float) instr.objData).floatValue();
// if (value == 0.0F || value == 1.0F)
// instr.length = 1;
// else if (gcp.reserveConstant(instr.objData) < 256)
// instr.length = 2;
// else
// instr.length = 3;
// } else if (instr.objData instanceof Double) {
// double value = ((Double) instr.objData).doubleValue();
// if (value == 0.0 || value == 1.0)
// instr.length = 1;
// else
// instr.length = 3;
// } else {
// if (gcp.reserveConstant(instr.objData) < 256)
// instr.length = 2;
// else
// instr.length = 3;
// }
} else if (instr.localSlot != -1) { } else if (instr.localSlot != -1) {
if (instr.opcode == opc_iinc) { if (instr.opcode == opc_iinc) {
if (instr.localSlot < 256 if (instr.localSlot < 256
@ -380,7 +452,7 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
else else
instr.length = 6; instr.length = 6;
} else { } else {
if (instr.localSlot < 4) if (instr.opcode != opc_ret && instr.localSlot < 4)
instr.length = 1; instr.length = 1;
else if (instr.localSlot < 256) else if (instr.localSlot < 256)
instr.length = 2; instr.length = 2;
@ -401,13 +473,16 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
} else } else
instr.length = 3; instr.length = 3;
} }
addr += instr.length; }
codeLength = addr;
} }
/* Now output the code */ public void writeCode(GrowableConstantPool gcp,
jode.obfuscator.ClassBundle bundle,
DataOutputStream output) throws IOException {
output.writeShort(maxStack); output.writeShort(maxStack);
output.writeShort(maxLocals); output.writeShort(maxLocals);
output.writeInt(addr); output.writeInt(codeLength);
for (Instruction instr = firstInstr; for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) { instr != null; instr = instr.nextByAddr) {
switch (instr.opcode) { switch (instr.opcode) {
@ -446,47 +521,12 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
break; break;
case opc_ldc: case opc_ldc:
// if (instr.objData == null)
// output.writeByte(opc_aconst_null);
// else if (instr.length == 1) {
// int value = ((Number) instr.objData).intValue();
// if (instr.objData instanceof Integer)
// output.writeByte(opc_iconst_0+value);
// else if (instr.objData instanceof Long)
// output.writeByte(opc_lconst_0+value);
// else if (instr.objData instanceof Float)
// output.writeByte(opc_fconst_0+value);
// else if (instr.objData instanceof Double)
// output.writeByte(opc_dconst_0+value);
// } else if (instr.objData instanceof Long
// || instr.objData instanceof Double) {
// output.writeByte(opc_ldc2_w);
// output.writeShort(gcp.putConstant(instr.objData));
// } else {
// if (instr.objData instanceof Integer) {
// int value = ((Integer) instr.objData).intValue();
// if (value >= -Byte.MIN_VALUE
// && value <= Byte.MAX_VALUE) {
// output.writeByte(opc_bipush);
// output.writeByte(value);
// break;
// } else if (value >= -Short.MIN_VALUE
// && value <= Short.MAX_VALUE) {
// output.writeByte(opc_sipush);
// output.writeShort(value);
// break;
// }
// }
if (instr.length == 2) {
output.writeByte(opc_ldc); output.writeByte(opc_ldc);
output.writeByte(gcp.putConstant(instr.objData)); output.writeByte(gcp.putConstant(instr.objData));
} else { break;
case opc_ldc_w:
output.writeByte(opc_ldc_w); output.writeByte(opc_ldc_w);
output.writeShort(gcp.putConstant(instr.objData)); output.writeShort(gcp.putConstant(instr.objData));
}
break; break;
case opc_ldc2_w: case opc_ldc2_w:
output.writeByte(instr.opcode); output.writeByte(instr.opcode);
@ -571,7 +611,7 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
case opc_putfield: case opc_putfield:
output.writeByte(instr.opcode); output.writeByte(instr.opcode);
output.writeShort(gcp.putRef(gcp.FIELDREF, output.writeShort(gcp.putRef(gcp.FIELDREF,
(String[]) instr.objData)); (Reference) instr.objData));
break; break;
case opc_invokespecial: case opc_invokespecial:
@ -581,11 +621,11 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
output.writeByte(instr.opcode); output.writeByte(instr.opcode);
if (instr.opcode == opc_invokeinterface) { if (instr.opcode == opc_invokeinterface) {
output.writeShort(gcp.putRef(gcp.INTERFACEMETHODREF, output.writeShort(gcp.putRef(gcp.INTERFACEMETHODREF,
(String[]) instr.objData)); (Reference) instr.objData));
output.writeShort(instr.intData); output.writeShort(instr.intData);
} else } else
output.writeShort(gcp.putRef(gcp.METHODREF, output.writeShort(gcp.putRef(gcp.METHODREF,
(String[]) instr.objData)); (Reference) instr.objData));
break; break;
case opc_new: case opc_new:
case opc_anewarray: case opc_anewarray:
@ -607,6 +647,10 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
if (instr.opcode == opc_xxxunusedxxx if (instr.opcode == opc_xxxunusedxxx
|| instr.opcode >= opc_breakpoint) || instr.opcode >= opc_breakpoint)
throw new ClassFormatError("Invalid opcode "+instr.opcode); throw new ClassFormatError("Invalid opcode "+instr.opcode);
else if (instr.length != 1)
throw new ClassFormatError("Length differs at "
+ instr.addr + " opcode "
+ opcodeString[instr.opcode]);
else else
output.writeByte(instr.opcode); output.writeByte(instr.opcode);
} }

Loading…
Cancel
Save