new attribute handling

LocalVariableTable and LineNumberTable handling
getSize()
bug fixes:  -Byte.MIN_VALUE  -->  Byte.MIN_VALUE


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@618 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent a0d1c9051c
commit 7a326a40c1
  1. 280
      jode/jode/bytecode/BytecodeInfo.java

@ -19,8 +19,6 @@
package jode.bytecode; package jode.bytecode;
import jode.Decompiler/*XXX*/; import jode.Decompiler/*XXX*/;
import jode.type.Type;
import jode.type.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;
@ -40,11 +38,19 @@ import java.util.Enumeration;
*/ */
public class BytecodeInfo extends BinaryInfo implements Opcodes { public class BytecodeInfo extends BinaryInfo implements Opcodes {
MethodInfo methodInfo;
ConstantPool cp; ConstantPool cp;
int maxStack, maxLocals; int maxStack, maxLocals;
int codeLength; int codeLength;
Instruction firstInstr = null; Instruction firstInstr = null;
Handler[] exceptionHandlers; Handler[] exceptionHandlers;
LocalVariableInfo[] lvt;
LineNumber[] lnt;
public BytecodeInfo(MethodInfo mi) {
methodInfo = mi;
}
private final static Object[] constants = { private final static Object[] constants = {
null, null,
@ -55,6 +61,96 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
new Double(0), new Double(1) new Double(0), new Double(1)
}; };
protected void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if (name.equals("LocalVariableTable")) {
if (Decompiler.showLVT)
Decompiler.err.println("LocalVariableTable of "+methodInfo.clazzInfo.getName() + "." + methodInfo.getName());
int count = input.readUnsignedShort();
if (length != 2 + count * 10) {
if (Decompiler.showLVT)
Decompiler.err.println("Illegal LVT length, ignoring it");
return;
}
lvt = new LocalVariableInfo[count];
for (int i=0; i < count; i++) {
lvt[i] = new LocalVariableInfo();
int start = input.readUnsignedShort();
int end = start + input.readUnsignedShort();
int nameIndex = input.readUnsignedShort();
int typeIndex = input.readUnsignedShort();
int slot = input.readUnsignedShort();
Instruction startInstr, endInstr;
for (startInstr = firstInstr;
startInstr.addr < start && startInstr != null;
startInstr = startInstr.nextByAddr) {
/* empty */
}
endInstr = startInstr;
if (startInstr != null) {
while (endInstr.nextByAddr != null
&& endInstr.nextByAddr.addr < end)
endInstr = endInstr.nextByAddr;
}
if (startInstr == null
|| startInstr.addr != start
|| endInstr == null
|| endInstr.addr + endInstr.length != end
|| nameIndex == 0 || typeIndex == 0
|| slot >= maxLocals
|| cp.getTag(nameIndex) != cp.UTF8
|| cp.getTag(typeIndex) != cp.UTF8) {
// This is probably an evil lvt as created by HashJava
// simply ignore it.
if (Decompiler.showLVT)
Decompiler.err.println("Illegal entry, ignoring LVT");
lvt = null;
return;
}
lvt[i].start = startInstr;
lvt[i].end = endInstr;
lvt[i].name = cp.getUTF8(nameIndex);
lvt[i].type = cp.getUTF8(typeIndex);
lvt[i].slot = slot;
if (Decompiler.showLVT)
Decompiler.err.println("\t" + lvt[i].name + ": "
+ lvt[i].type
+" range "+start+" - "+end
+" slot "+slot);
}
} else if (name.equals("LineNumberTable")) {
int count = input.readUnsignedShort();
if (length != 2 + count * 4) {
Decompiler.err.println
("Illegal LineNumberTable, ignoring it");
return;
}
lnt = new LineNumber[count];
for (int i = 0; i < count; i++) {
lnt[i] = new LineNumber();
int start = input.readUnsignedShort();
Instruction startInstr;
for (startInstr = firstInstr;
startInstr.addr < start && startInstr != null;
startInstr = startInstr.nextByAddr) {
/* empty */
}
if (startInstr == null
|| startInstr.addr != start) {
Decompiler.err.println
("Illegal entry, ignoring LineNumberTable table");
lnt = null;
return;
}
lnt[i].start = startInstr;
lnt[i].linenr = input.readUnsignedShort();
}
} else
super.readAttribute(name, length, cp, input, howMuch);
}
public void read(ConstantPool cp, public void read(ConstantPool cp,
DataInputStream input) throws IOException { DataInputStream input) throws IOException {
this.cp = cp; this.cp = cp;
@ -534,6 +630,28 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
} }
} }
public void reserveSmallConstants(GrowableConstantPool gcp) {
next_instr:
for (Instruction instr = firstInstr;
instr != null; instr = instr.nextByAddr) {
if (instr.opcode == opc_ldc) {
if (instr.objData == null)
continue next_instr;
for (int i=1; i < constants.length; i++) {
if (instr.objData.equals(constants[i]))
continue next_instr;
}
if (instr.objData instanceof Integer) {
int value = ((Integer) instr.objData).intValue();
if (value >= Short.MIN_VALUE
&& value <= Short.MAX_VALUE)
continue next_instr;
}
gcp.reserveConstant(instr.objData);
}
}
}
public void prepareWriting(GrowableConstantPool gcp) { public void prepareWriting(GrowableConstantPool gcp) {
/* Recalculate addr and length */ /* Recalculate addr and length */
int addr = 0; int addr = 0;
@ -554,22 +672,23 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
} }
} }
if (instr.opcode == opc_ldc2_w) { if (instr.opcode == opc_ldc2_w) {
gcp.putLongConstant(instr.objData);
instr.length = 3; instr.length = 3;
continue; continue;
} }
if (instr.objData instanceof Integer) { if (instr.objData instanceof Integer) {
int value = ((Integer) instr.objData).intValue(); int value = ((Integer) instr.objData).intValue();
if (value >= -Byte.MIN_VALUE if (value >= Byte.MIN_VALUE
&& value <= Byte.MAX_VALUE) { && value <= Byte.MAX_VALUE) {
instr.length = 2; instr.length = 2;
continue; continue;
} else if (value >= -Short.MIN_VALUE } else if (value >= Short.MIN_VALUE
&& value <= Short.MAX_VALUE) { && value <= Short.MAX_VALUE) {
instr.length = 2; instr.length = 3;
continue; continue;
} }
} }
if (gcp.reserveConstant(instr.objData) < 256) { if (gcp.putConstant(instr.objData) < 256) {
instr.length = 2; instr.length = 2;
} else { } else {
instr.length = 3; instr.length = 3;
@ -603,23 +722,90 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
instr.length = 5; instr.length = 5;
} else } else
instr.length = 3; instr.length = 3;
} else if (instr.opcode == opc_multianewarray } else if (instr.opcode == opc_multianewarray) {
&& instr.intData == 1) { if (instr.intData == 1) {
String clazz = ((String) instr.objData).substring(1); String clazz = ((String) instr.objData).substring(1);
if (newArrayTypes.indexOf(clazz.charAt(0)) if (newArrayTypes.indexOf(clazz.charAt(0))
!= -1) { != -1) {
instr.length = 2; instr.length = 2;
} else {
gcp.putClassType(clazz);
instr.length = 3;
}
} else { } else {
instr.length = 3; gcp.putClassType((String)instr.objData);
instr.length = 4;
} }
} else if (instr.opcode >= opc_getstatic
&& instr.opcode <= opc_invokeinterface) {
int tag = (instr.opcode <= opc_putfield ? gcp.FIELDREF
: instr.opcode <= opc_invokestatic ? gcp.METHODREF
: gcp.INTERFACEMETHODREF);
gcp.putRef(tag, (Reference) instr.objData);
} else if (instr.opcode == opc_new
|| instr.opcode == opc_checkcast
|| instr.opcode == opc_instanceof) {
gcp.putClassType((String) instr.objData);
} }
} }
codeLength = addr; codeLength = addr;
for (int i=0; i< exceptionHandlers.length; i++)
if (exceptionHandlers[i].type != null)
gcp.putClassName(exceptionHandlers[i].type);
if (lvt != null) {
gcp.putUTF8("LocalVariableTable");
for (int i=0; i < lvt.length; i++) {
gcp.putUTF8(lvt[i].name);
gcp.putUTF8(lvt[i].type);
}
}
if (lnt != null)
gcp.putUTF8("LineNumberTable");
prepareAttributes(gcp);
}
protected int getKnownAttributeCount() {
int count = 0;
if (lvt != null)
count++;
if (lnt != null)
count++;
return count;
}
public void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
throws IOException {
if (lvt != null) {
output.writeShort(gcp.putUTF8("LocalVariableTable"));
int count = lvt.length;
int length = 2 + 10 * count;
output.writeInt(length);
output.writeShort(count);
for (int i=0; i < count; i++) {
output.writeShort(lvt[i].start.addr);
output.writeShort(lvt[i].end.addr + lvt[i].end.length
- lvt[i].start.addr);
output.writeShort(gcp.putUTF8(lvt[i].name));
output.writeShort(gcp.putUTF8(lvt[i].type));
output.writeShort(lvt[i].slot);
}
}
if (lnt != null) {
output.writeShort(gcp.putUTF8("LineNumberTable"));
int count = lnt.length;
int length = 2 + 4 * count;
output.writeInt(length);
output.writeShort(count);
for (int i=0; i < count; i++) {
output.writeShort(lnt[i].start.addr);
output.writeShort(lnt[i].linenr);
}
}
} }
public void writeCode(GrowableConstantPool gcp, public void write(GrowableConstantPool gcp,
jode.obfuscator.ClassBundle bundle, DataOutputStream output) throws IOException {
DataOutputStream output) throws IOException {
output.writeShort(maxStack); output.writeShort(maxStack);
output.writeShort(maxLocals); output.writeShort(maxLocals);
output.writeInt(codeLength); output.writeInt(codeLength);
@ -680,17 +866,19 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
} else { } else {
if (instr.objData instanceof Integer) { if (instr.objData instanceof Integer) {
int value = ((Integer) instr.objData).intValue(); int value = ((Integer) instr.objData).intValue();
if (value >= -Byte.MIN_VALUE if (value >= Byte.MIN_VALUE
&& value <= Byte.MAX_VALUE) { && value <= Byte.MAX_VALUE) {
output.writeByte(instr.opcode); output.writeByte(opc_bipush);
output.writeByte(((Integer)instr.objData) output.writeByte(((Integer)instr.objData)
.intValue()); .intValue());
} else if (value >= -Short.MIN_VALUE break switch_opc;
} else if (value >= Short.MIN_VALUE
&& value <= Short.MAX_VALUE) { && value <= Short.MAX_VALUE) {
output.writeByte(instr.opcode); output.writeByte(opc_sipush);
output.writeShort(((Integer)instr.objData) output.writeShort(((Integer)instr.objData)
.intValue()); .intValue());
break switch_opc;
} }
} }
if (instr.length == 2) { if (instr.length == 2) {
@ -834,7 +1022,33 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
output.writeShort((exceptionHandlers[i].type == null) ? 0 output.writeShort((exceptionHandlers[i].type == null) ? 0
: gcp.putClassName(exceptionHandlers[i].type)); : gcp.putClassName(exceptionHandlers[i].type));
} }
output.writeShort(0); // No Attributes; writeAttributes(gcp, output);
}
public int getSize() {
/* maxStack: 2
* maxLocals: 2
* code: 4 + codeLength
* exc count: 2
* exceptions: n * 8
* attributes:
* lvt_name: 2
* lvt_length: 4
* lvt_count: 2
* lvt_entries: n * 10
* attributes:
* lnt_name: 2
* lnt_length: 4
* lnt_count: 2
* lnt_entries: n * 4
*/
int size = 0;
if (lvt != null)
size += 8 + lvt.length * 10;
if (lnt != null)
size += 8 + lnt.length * 4;
return 10 + codeLength + exceptionHandlers.length * 8
+ getAttributeSize() + size;
} }
public int getMaxStack() { public int getMaxStack() {
@ -853,7 +1067,31 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
return exceptionHandlers; return exceptionHandlers;
} }
public LocalVariableInfo[] getLocalVariableTable() {
return lvt;
}
public LineNumber[] getLineNumberTable() {
return lnt;
}
public void setMaxStack(int ms) {
maxStack = ms;
}
public void setMaxLocals(int ml) {
maxLocals = ml;
}
public void setExceptionHandlers(Handler[] handlers) { public void setExceptionHandlers(Handler[] handlers) {
exceptionHandlers = handlers; exceptionHandlers = handlers;
} }
public void setLocalVariableTable(LocalVariableInfo[] newLvt) {
lvt = newLvt;
}
public void setLineNumberTable(LineNumber[] newLnt) {
lnt = newLnt;
}
} }

Loading…
Cancel
Save