Allow pool to be dynamically rebuilt

This commit is contained in:
Adam
2015-05-09 17:00:30 -04:00
parent 0d21d49d2d
commit 4af719032d
45 changed files with 597 additions and 333 deletions

View File

@@ -4,6 +4,7 @@ import info.sigterm.deob.attributes.Attributes;
import info.sigterm.deob.pool.Class; import info.sigterm.deob.pool.Class;
import info.sigterm.deob.pool.NameAndType; import info.sigterm.deob.pool.NameAndType;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -11,19 +12,20 @@ import java.util.ArrayList;
public class ClassFile public class ClassFile
{ {
private static final int MAGIC = 0xcafebabe;
private ClassGroup group; private ClassGroup group;
private DataInputStream is; private DataInputStream is;
private ClassFile parent; // super class private ClassFile parent; // super class
private ArrayList<ClassFile> children = new ArrayList<ClassFile>(); // classes which inherit from this private ArrayList<ClassFile> children = new ArrayList<ClassFile>(); // classes which inherit from this
private int magic;
private short minor_version; private short minor_version;
private short major_version; private short major_version;
private ConstantPool pool; private ConstantPool pool;
private short access_flags; private short access_flags;
private int this_class; private Class name;
private int super_class; private Class super_class;
private Interfaces interfaces; private Interfaces interfaces;
private Fields fields; private Fields fields;
private Methods methods; private Methods methods;
@@ -34,18 +36,18 @@ public class ClassFile
this.group = group; this.group = group;
this.is = is; this.is = is;
magic = is.readInt(); int magic = is.readInt();
if (magic != 0xcafebabe) if (magic != MAGIC)
throw new IOException("File is not a java class file."); throw new IOException("File is not a java class file.");
minor_version = is.readShort(); minor_version = is.readShort();
major_version = is.readShort(); major_version = is.readShort();
pool = new ConstantPool(this); pool = new ConstantPool(this, is);
access_flags = is.readShort(); access_flags = is.readShort();
this_class = is.readUnsignedShort(); name = pool.getClass(is.readUnsignedShort());
super_class = is.readUnsignedShort(); super_class = pool.getClass(is.readUnsignedShort());
interfaces = new Interfaces(this); interfaces = new Interfaces(this);
@@ -58,24 +60,32 @@ public class ClassFile
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeInt(0xcafebabe); out.writeInt(MAGIC);
out.writeShort(minor_version); out.writeShort(minor_version);
out.writeShort(major_version); out.writeShort(major_version);
/* constant pool will be rebuilt now */
pool.reset();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream rest = new DataOutputStream(bout);
rest.writeShort(access_flags);
rest.writeShort(pool.make(name));
rest.writeShort(pool.make(super_class));
interfaces.write(rest);
fields.write(rest);
methods.write(rest);
attributes.write(rest);
// Now the pool is created
pool.write(out); pool.write(out);
out.write(bout.toByteArray());
out.writeShort(access_flags);
out.writeShort(this_class);
out.writeShort(super_class);
interfaces.write(out);
fields.write(out);
methods.write(out);
attributes.write(out);
} }
public ClassGroup getGroup() public ClassGroup getGroup()
@@ -110,14 +120,12 @@ public class ClassFile
public String getName() public String getName()
{ {
Class entry = (Class) pool.getEntry(this_class); return name.getName();
return entry.getName();
} }
public ClassFile getParent() public ClassFile getParent()
{ {
Class entry = (Class) pool.getEntry(super_class); String superName = super_class.getName();
String superName = entry.getName();
ClassFile other = group.findClass(superName); ClassFile other = group.findClass(superName);
assert other != this; assert other != this;
return other; return other;

View File

@@ -1,7 +1,8 @@
package info.sigterm.deob; package info.sigterm.deob;
import info.sigterm.deob.attributes.code.instructions.Return;
import info.sigterm.deob.pool.ConstantType; import info.sigterm.deob.pool.ConstantType;
import info.sigterm.deob.pool.InterfaceMethod;
import info.sigterm.deob.pool.NameAndType;
import info.sigterm.deob.pool.PoolEntry; import info.sigterm.deob.pool.PoolEntry;
import info.sigterm.deob.pool.UTF8; import info.sigterm.deob.pool.UTF8;
@@ -9,22 +10,26 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.security.KeyStore.Entry;
import java.util.ArrayList;
import java.util.List;
public class ConstantPool public class ConstantPool
{ {
private ClassFile classFile; private ClassFile classFile;
private int count; private List<PoolEntry> entries = new ArrayList<PoolEntry>();
private PoolEntry pool[];
ConstantPool(ClassFile c)
ConstantPool(ClassFile c) throws IOException
{ {
classFile = c; classFile = c;
}
DataInputStream is = c.getStream(); ConstantPool(ClassFile c, DataInputStream is) throws IOException
{
this(c);
count = is.readUnsignedShort(); int count = is.readUnsignedShort();
pool = new PoolEntry[count];
for (int i = 1; i < count; ++i) for (int i = 1; i < count; ++i)
{ {
@@ -36,8 +41,9 @@ public class ConstantPool
{ {
Constructor<? extends PoolEntry> con = type.getPoolClass().getConstructor(new Class[] { ConstantPool.class }); Constructor<? extends PoolEntry> con = type.getPoolClass().getConstructor(new Class[] { ConstantPool.class });
PoolEntry entry = con.newInstance(this); PoolEntry entry = con.newInstance(this);
entry.id = i;
pool[i] = entry; entries.add(entry);
i += entry.getSlots() - 1; i += entry.getSlots() - 1;
} }
catch (Exception e) catch (Exception e)
@@ -45,16 +51,41 @@ public class ConstantPool
throw new IOException(e); throw new IOException(e);
} }
} }
for (PoolEntry entry : entries)
entry.resolve();
}
public void reset()
{
for (PoolEntry entry : entries)
{
entry.id = 0;
}
entries.clear();
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(count); /* this grows as it is iterated */
for (int i = 1; i < count; ++i) for (int i = 0; i < entries.size(); ++i)
{ {
PoolEntry entry = pool[i]; PoolEntry entry = entries.get(i);
if (entry == null) entry.prime();
continue; }
int size = 0;
for (PoolEntry entry : entries)
size += entry.getSlots();
out.writeShort(size + 1);
int i = 1;
for (PoolEntry entry : entries)
{
assert i == entry.id;
i += entry.getSlots();
out.writeByte(entry.getType().getType()); out.writeByte(entry.getType().getType());
entry.write(out); entry.write(out);
} }
@@ -67,24 +98,92 @@ public class ConstantPool
public PoolEntry getEntry(int index) public PoolEntry getEntry(int index)
{ {
return pool[index]; for (PoolEntry entry : entries)
if (entry.id == index)
return entry;
return null;
} }
public int findUTF8Index(String s) public String getUTF8(int index)
{ {
for (int i = 1; i < count; ++i) PoolEntry entry = getEntry(index);
UTF8 u = (UTF8) entry;
return u.getValue();
}
public info.sigterm.deob.pool.Class getClass(int index)
{
return (info.sigterm.deob.pool.Class) getEntry(index);
}
public info.sigterm.deob.pool.Field getField(int index)
{
return (info.sigterm.deob.pool.Field) getEntry(index);
}
public InterfaceMethod getInterfaceMethod(int index)
{
return (InterfaceMethod) getEntry(index);
}
public info.sigterm.deob.pool.Method getMethod(int index)
{
return (info.sigterm.deob.pool.Method) getEntry(index);
}
public NameAndType getNameAndType(int index)
{
return (NameAndType) getEntry(index);
}
public Object get(int index)
{
PoolEntry entry = getEntry(index);
return entry.getObject();
}
public int make(PoolEntry entry)
{
int i = 1;
for (PoolEntry e : entries)
{ {
PoolEntry entry = pool[i]; if (e.equals(entry))
if (entry instanceof UTF8) return i;
{
UTF8 u = (UTF8) entry; i += e.getSlots();
if (s.equals(u.getValue()))
{
return i;
}
}
} }
return -1; entries.add(entry);
entry.id = i;
entry.pool = this;
return i;
}
public int makeUTF8(String str)
{
return make(new UTF8(str));
}
public int make(Object object)
{
if (object instanceof String)
return make(new info.sigterm.deob.pool.String(this, (String) object));
if (object instanceof Integer)
return make(new info.sigterm.deob.pool.Integer(this, (int) object));
if (object instanceof Float)
return make(new info.sigterm.deob.pool.Float(this, (float) object));
if (object instanceof Long)
return make(new info.sigterm.deob.pool.Long(this, (long) object));
if (object instanceof Double)
return make(new info.sigterm.deob.pool.Double(this, (double) object));
System.err.println("Constant pool make with unknown object " + object + " type " + object.getClass());
return 0;
} }
} }

View File

@@ -43,7 +43,7 @@ public class Deob
group.buildCallGraph(); group.buildCallGraph();
checkCallGraph(group); checkCallGraph(group);
checkParameters(group); //checkParameters(group);
//execute(group); //execute(group);

View File

@@ -2,7 +2,6 @@ package info.sigterm.deob;
import info.sigterm.deob.attributes.Attributes; import info.sigterm.deob.attributes.Attributes;
import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.Instruction;
import info.sigterm.deob.pool.UTF8;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -24,8 +23,7 @@ public class Field
private Fields fields; private Fields fields;
private short accessFlags; private short accessFlags;
private int nameIndex; private String name, descriptor;
private int descriptorIndex;
private Attributes attributes; private Attributes attributes;
private ArrayList<Instruction> instructions = new ArrayList<Instruction>(); // instructions which reference this field private ArrayList<Instruction> instructions = new ArrayList<Instruction>(); // instructions which reference this field
@@ -35,18 +33,21 @@ public class Field
this.fields = fields; this.fields = fields;
DataInputStream is = fields.getClassFile().getStream(); DataInputStream is = fields.getClassFile().getStream();
ConstantPool pool = fields.getClassFile().getPool();
accessFlags = is.readShort(); accessFlags = is.readShort();
nameIndex = is.readUnsignedShort(); name = pool.getUTF8(is.readUnsignedShort());
descriptorIndex = is.readUnsignedShort(); descriptor = pool.getUTF8(is.readUnsignedShort());
attributes = new Attributes(this); attributes = new Attributes(this);
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
ConstantPool pool = fields.getClassFile().getPool();
out.writeShort(accessFlags); out.writeShort(accessFlags);
out.writeShort(nameIndex); out.writeShort(pool.makeUTF8(name));
out.writeShort(descriptorIndex); out.writeShort(pool.makeUTF8(descriptor));
attributes.write(out); attributes.write(out);
} }
@@ -62,14 +63,12 @@ public class Field
public String getName() public String getName()
{ {
UTF8 u = (UTF8) fields.getClassFile().getPool().getEntry(nameIndex); return name;
return u.getValue();
} }
public String getDescriptor() public String getDescriptor()
{ {
UTF8 u = (UTF8) fields.getClassFile().getPool().getEntry(descriptorIndex); return descriptor;
return u.getValue();
} }
public Attributes getAttributes() public Attributes getAttributes()

View File

@@ -5,13 +5,14 @@ import info.sigterm.deob.pool.NameAndType;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Fields public class Fields
{ {
private ClassFile classFile; private ClassFile classFile;
private int count; private List<Field> fields = new ArrayList<>();
private Field[] fields;
Fields(ClassFile c) throws IOException Fields(ClassFile c) throws IOException
{ {
@@ -19,16 +20,15 @@ public class Fields
DataInputStream is = c.getStream(); DataInputStream is = c.getStream();
count = is.readUnsignedShort(); int count = is.readUnsignedShort();
fields = new Field[count];
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
fields[i] = new Field(this); fields.add(new Field(this));
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(count); out.writeShort(fields.size());
for (Field f : fields) for (Field f : fields)
f.write(out); f.write(out);
} }
@@ -38,7 +38,7 @@ public class Fields
return classFile; return classFile;
} }
public Field[] getFields() public List<Field> getFields()
{ {
return fields; return fields;
} }

View File

@@ -12,8 +12,7 @@ public class Interfaces
{ {
private ClassFile classFile; private ClassFile classFile;
private int count; private List<Class> interfaces = new ArrayList<Class>();
private int interfaces[];
Interfaces(ClassFile c) throws IOException Interfaces(ClassFile c) throws IOException
{ {
@@ -21,19 +20,17 @@ public class Interfaces
DataInputStream is = c.getStream(); DataInputStream is = c.getStream();
count = is.readUnsignedShort(); int count = is.readUnsignedShort();
interfaces = new int[count];
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
interfaces[i] = is.readUnsignedShort(); interfaces.add(c.getPool().getClass(is.readUnsignedShort()));
} }
public List<ClassFile> getInterfaces() public List<ClassFile> getInterfaces()
{ {
List<ClassFile> l = new ArrayList<>(); List<ClassFile> l = new ArrayList<>();
for (int i : interfaces) for (Class clazz : interfaces)
{ {
Class clazz = (Class) classFile.getPool().getEntry(i);
ClassFile iface = classFile.getGroup().findClass(clazz.getName()); ClassFile iface = classFile.getGroup().findClass(clazz.getName());
if (iface != null) if (iface != null)
l.add(iface); l.add(iface);
@@ -43,16 +40,15 @@ public class Interfaces
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(count); out.writeShort(interfaces.size());
for (int i : interfaces) for (Class clazz : interfaces)
out.writeShort(i); out.writeShort(classFile.getPool().make(clazz));
} }
public boolean instanceOf(ClassFile cf) public boolean instanceOf(ClassFile cf)
{ {
for (int i : interfaces) for (Class clazz : interfaces)
{ {
Class clazz = (Class) classFile.getPool().getEntry(i);
ClassFile iface = classFile.getGroup().findClass(clazz.getName()); ClassFile iface = classFile.getGroup().findClass(clazz.getName());
if (iface.instanceOf(cf)) if (iface.instanceOf(cf))
return true; return true;

View File

@@ -7,7 +7,6 @@ import info.sigterm.deob.attributes.code.Instruction;
import info.sigterm.deob.attributes.code.instruction.types.LVTInstruction; import info.sigterm.deob.attributes.code.instruction.types.LVTInstruction;
import info.sigterm.deob.callgraph.Node; import info.sigterm.deob.callgraph.Node;
import info.sigterm.deob.pool.NameAndType; import info.sigterm.deob.pool.NameAndType;
import info.sigterm.deob.pool.UTF8;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -22,8 +21,8 @@ public class Method
private Methods methods; private Methods methods;
private short accessFlags; private short accessFlags;
private int nameIndex; private String name;
private int descriptorIndex; private String descriptor;
private Attributes attributes; private Attributes attributes;
private List<Node> callsTo = new ArrayList<>(), private List<Node> callsTo = new ArrayList<>(),
callsFrom = new ArrayList<>(); callsFrom = new ArrayList<>();
@@ -33,18 +32,21 @@ public class Method
this.methods = methods; this.methods = methods;
DataInputStream is = methods.getClassFile().getStream(); DataInputStream is = methods.getClassFile().getStream();
ConstantPool pool = methods.getClassFile().getPool();
accessFlags = is.readShort(); accessFlags = is.readShort();
nameIndex = is.readUnsignedShort(); name = pool.getUTF8(is.readUnsignedShort());
descriptorIndex = is.readUnsignedShort(); descriptor = pool.getUTF8(is.readUnsignedShort());
attributes = new Attributes(this); attributes = new Attributes(this);
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
ConstantPool pool = methods.getClassFile().getPool();
out.writeShort(accessFlags); out.writeShort(accessFlags);
out.writeShort(nameIndex); out.writeShort(pool.makeUTF8(name));
out.writeShort(descriptorIndex); out.writeShort(pool.makeUTF8(descriptor));
attributes.write(out); attributes.write(out);
} }
@@ -60,20 +62,17 @@ public class Method
public String getName() public String getName()
{ {
UTF8 u = (UTF8) methods.getClassFile().getPool().getEntry(nameIndex); return name;
return u.getValue();
} }
public String getDescriptor() public String getDescriptor()
{ {
UTF8 u = (UTF8) methods.getClassFile().getPool().getEntry(descriptorIndex); return descriptor;
return u.getValue();
} }
public NameAndType getNameAndType() public NameAndType getNameAndType()
{ {
// this isn't really from the pool .. return new NameAndType(name, descriptor);
return new NameAndType(methods.getClassFile().getPool(), nameIndex, descriptorIndex);
} }
public boolean isStatic() public boolean isStatic()

View File

@@ -10,7 +10,6 @@ public abstract class Attribute
private Attributes attributes; private Attributes attributes;
private AttributeType type; private AttributeType type;
private int length; private int length;
public int nameIndex;
Attribute(Attributes attr, AttributeType type) throws IOException Attribute(Attributes attr, AttributeType type) throws IOException
{ {
@@ -21,7 +20,7 @@ public abstract class Attribute
this.length = is.readInt(); this.length = is.readInt();
} }
public void write(DataOutputStream out) throws IOException public final void write(DataOutputStream out) throws IOException
{ {
ByteArrayOutputStream bout = new ByteArrayOutputStream(); ByteArrayOutputStream bout = new ByteArrayOutputStream();
writeAttr(new DataOutputStream(bout)); writeAttr(new DataOutputStream(bout));

View File

@@ -8,7 +8,6 @@ public enum AttributeType
private String name; private String name;
private Class<? extends Attribute> clazz; private Class<? extends Attribute> clazz;
public int nameIndex;
AttributeType(String name, Class<? extends Attribute> clazz) AttributeType(String name, Class<? extends Attribute> clazz)
{ {

View File

@@ -9,6 +9,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
public class Attributes public class Attributes
{ {
@@ -17,8 +19,7 @@ public class Attributes
private Method method; private Method method;
private Code code; private Code code;
private int count; private List<Attribute> attributes = new ArrayList<>();
private Attribute[] attributes;
public Attributes(ClassFile cf) throws IOException public Attributes(ClassFile cf) throws IOException
{ {
@@ -87,22 +88,20 @@ public class Attributes
{ {
DataInputStream is = getStream(); DataInputStream is = getStream();
count = is.readUnsignedShort(); int count = is.readUnsignedShort();
attributes = new Attribute[count];
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
int nameIndex = is.readUnsignedShort(); String name = this.getClassFile().getPool().getUTF8(is.readUnsignedShort());
UTF8 name = (UTF8) getClassFile().getPool().getEntry(nameIndex);
AttributeType type = AttributeType.findType(name.getValue()); AttributeType type = AttributeType.findType(name);
try try
{ {
Constructor<? extends Attribute> con = type.getAttributeClass().getConstructor(new Class[] { Attributes.class }); Constructor<? extends Attribute> con = type.getAttributeClass().getConstructor(new Class[] { Attributes.class });
Attribute attr = con.newInstance(this); Attribute attr = con.newInstance(this);
attr.nameIndex = nameIndex;
attributes[i] = attr; if (type != AttributeType.UNKNOWN)
attributes.add(attr);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -113,10 +112,10 @@ public class Attributes
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(count); out.writeShort(attributes.size());
for (Attribute a : attributes) for (Attribute a : attributes)
{ {
out.writeShort(a.nameIndex); out.writeShort(this.getClassFile().getPool().makeUTF8(a.getType().getName()));
a.write(out); a.write(out);
} }
} }

View File

@@ -29,6 +29,17 @@ public class Code extends Attribute
exceptions = new Exceptions(this); exceptions = new Exceptions(this);
this.attributes = new Attributes(this); this.attributes = new Attributes(this);
} }
@Override
public void writeAttr(DataOutputStream out) throws IOException
{
out.writeShort(maxStack);
out.writeShort(maxLocals);
instructions.write(out);
exceptions.write(out);
attributes.write(out);
}
public int getMaxStack() public int getMaxStack()
{ {
@@ -59,15 +70,4 @@ public class Code extends Attribute
{ {
instructions.buildCallGraph(); instructions.buildCallGraph();
} }
@Override
public void writeAttr(DataOutputStream out) throws IOException
{
out.writeShort(maxStack);
out.writeShort(maxLocals);
instructions.write(out);
exceptions.write(out);
attributes.write(out);
}
} }

View File

@@ -8,24 +8,24 @@ import java.io.IOException;
public class ConstantValue extends Attribute public class ConstantValue extends Attribute
{ {
private int constantValueIndex; private PoolEntry value;
public ConstantValue(Attributes attributes) throws IOException public ConstantValue(Attributes attributes) throws IOException
{ {
super(attributes, AttributeType.CONSTANT_VALUE); super(attributes, AttributeType.CONSTANT_VALUE);
DataInputStream is = attributes.getStream(); DataInputStream is = attributes.getStream();
constantValueIndex = is.readUnsignedShort(); value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort());
} }
public PoolEntry getValue() public PoolEntry getValue()
{ {
return this.getAttributes().getClassFile().getPool().getEntry(constantValueIndex); return value;
} }
@Override @Override
public void writeAttr(DataOutputStream out) throws IOException public void writeAttr(DataOutputStream out) throws IOException
{ {
out.writeShort(constantValueIndex); out.writeShort(this.getAttributes().getClassFile().getPool().make(value));
} }
} }

View File

@@ -1,6 +1,7 @@
package info.sigterm.deob.attributes.code; package info.sigterm.deob.attributes.code;
import info.sigterm.deob.ConstantPool; import info.sigterm.deob.ConstantPool;
import info.sigterm.deob.pool.Class;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -13,26 +14,29 @@ public class Exception
private int startPc; private int startPc;
private int endPc; private int endPc;
private int handlerPc; private int handlerPc;
private int catchType; private Class cacheType;
public Exception(Exceptions exceptions) throws IOException public Exception(Exceptions exceptions) throws IOException
{ {
this.exceptions = exceptions; this.exceptions = exceptions;
DataInputStream is = exceptions.getCode().getAttributes().getStream(); DataInputStream is = exceptions.getCode().getAttributes().getStream();
ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool();
startPc = is.readUnsignedShort(); startPc = is.readUnsignedShort();
endPc = is.readUnsignedShort(); endPc = is.readUnsignedShort();
handlerPc = is.readUnsignedShort(); handlerPc = is.readUnsignedShort();
catchType = is.readUnsignedShort(); cacheType = pool.getClass(is.readUnsignedShort());
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool();
out.writeShort(startPc); out.writeShort(startPc);
out.writeShort(endPc); out.writeShort(endPc);
out.writeShort(handlerPc); out.writeShort(handlerPc);
out.writeShort(catchType); out.writeShort(cacheType == null ? 0 : pool.make(cacheType));
} }
public Exceptions getExceptions() public Exceptions getExceptions()

View File

@@ -1,18 +1,18 @@
package info.sigterm.deob.attributes.code; package info.sigterm.deob.attributes.code;
import info.sigterm.deob.attributes.Code; import info.sigterm.deob.attributes.Code;
import info.sigterm.deob.execution.ObjectInstance;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class Exceptions public class Exceptions
{ {
private Code code; private Code code;
private Exception[] exceptions; private List<Exception> exceptions = new ArrayList<Exception>();
public Exceptions(Code code) throws IOException public Exceptions(Code code) throws IOException
{ {
@@ -21,15 +21,14 @@ public class Exceptions
DataInputStream is = code.getAttributes().getStream(); DataInputStream is = code.getAttributes().getStream();
int count = is.readUnsignedShort(); int count = is.readUnsignedShort();
exceptions = new Exception[count];
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
exceptions[i] = new Exception(this); exceptions.add(new Exception(this));
} }
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(exceptions.length); out.writeShort(exceptions.size());
for (Exception e : exceptions) for (Exception e : exceptions)
e.write(out); e.write(out);
} }

View File

@@ -1,5 +1,6 @@
package info.sigterm.deob.attributes.code; package info.sigterm.deob.attributes.code;
import info.sigterm.deob.ConstantPool;
import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.Frame;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -33,6 +34,11 @@ public abstract class Instruction
{ {
return instructions; return instructions;
} }
public ConstantPool getPool()
{
return instructions.getCode().getAttributes().getClassFile().getPool();
}
public int getPc() public int getPc()
{ {

View File

@@ -5,7 +5,6 @@ import info.sigterm.deob.attributes.code.InstructionType;
import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.attributes.code.Instructions;
import info.sigterm.deob.execution.ArrayInstance; import info.sigterm.deob.execution.ArrayInstance;
import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.Frame;
import info.sigterm.deob.execution.ObjectInstance;
import info.sigterm.deob.execution.Stack; import info.sigterm.deob.execution.Stack;
public class AAStore extends Instruction public class AAStore extends Instruction

View File

@@ -1,6 +1,5 @@
package info.sigterm.deob.attributes.code.instructions; package info.sigterm.deob.attributes.code.instructions;
import info.sigterm.deob.Method;
import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.Instruction;
import info.sigterm.deob.attributes.code.InstructionType; import info.sigterm.deob.attributes.code.InstructionType;
import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.attributes.code.Instructions;

View File

@@ -15,14 +15,14 @@ import java.io.IOException;
public class ANewArray extends Instruction public class ANewArray extends Instruction
{ {
private int index; private Class clazz;
public ANewArray(Instructions instructions, InstructionType type, int pc) throws IOException public ANewArray(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); clazz = this.getPool().getClass(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -30,14 +30,14 @@ public class ANewArray extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index);
out.writeShort(this.getPool().make(clazz));
} }
@Override @Override
public void execute(Frame frame) public void execute(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
Class clazz = (Class) thisClass.getPool().getEntry(index);
int count = (int) frame.getStack().pop(); int count = (int) frame.getStack().pop();

View File

@@ -15,14 +15,14 @@ import java.io.IOException;
public class CheckCast extends Instruction public class CheckCast extends Instruction
{ {
private int index; private Class clazz;
public CheckCast(Instructions instructions, InstructionType type, int pc) throws IOException public CheckCast(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); clazz = this.getPool().getClass(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -30,7 +30,7 @@ public class CheckCast extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(clazz));
} }
@Override @Override
@@ -39,7 +39,6 @@ public class CheckCast extends Instruction
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool(); ConstantPool pool = thisClass.getPool();
Class clazz = (Class) pool.getEntry(index);
ObjectInstance obj = (ObjectInstance) e.getStack().pop(); ObjectInstance obj = (ObjectInstance) e.getStack().pop();
if (obj == null) if (obj == null)

View File

@@ -17,14 +17,14 @@ import java.io.IOException;
public class GetField extends Instruction public class GetField extends Instruction
{ {
private int index; private Field field;
public GetField(Instructions instructions, InstructionType type, int pc) throws IOException public GetField(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); field = this.getPool().getField(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -32,7 +32,7 @@ public class GetField extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(field));
} }
@Override @Override
@@ -43,9 +43,8 @@ public class GetField extends Instruction
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool(); ConstantPool pool = thisClass.getPool();
Field entry = (Field) pool.getEntry(index);
NameAndType nat = entry.getNameAndType(); NameAndType nat = field.getNameAndType();
if (object == null) if (object == null)
{ {

View File

@@ -18,14 +18,14 @@ import java.io.IOException;
public class GetStatic extends Instruction public class GetStatic extends Instruction
{ {
private int index; private Field field;
public GetStatic(Instructions instructions, InstructionType type, int pc) throws IOException public GetStatic(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); field = this.getPool().getField(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -33,7 +33,7 @@ public class GetStatic extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(field));
} }
@Override @Override
@@ -41,11 +41,8 @@ public class GetStatic extends Instruction
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool(); Class clazz = field.getClassEntry();
Field entry = (Field) pool.getEntry(index); NameAndType nat = field.getNameAndType();
Class clazz = entry.getClassEntry();
NameAndType nat = entry.getNameAndType();
ClassFile cf = thisClass.getGroup().findClass(clazz.getName()); ClassFile cf = thisClass.getGroup().findClass(clazz.getName());
if (cf == null) if (cf == null)
@@ -65,11 +62,8 @@ public class GetStatic extends Instruction
@Override @Override
public void buildInstructionGraph() public void buildInstructionGraph()
{ {
ConstantPool pool = this.getInstructions().getCode().getAttributes().getClassFile().getPool(); Class clazz = field.getClassEntry();
Field entry = (Field) pool.getEntry(index); NameAndType nat = field.getNameAndType();
Class clazz = entry.getClassEntry();
NameAndType nat = entry.getNameAndType();
ClassFile cf = this.getInstructions().getCode().getAttributes().getClassFile().getGroup().findClass(clazz.getName()); ClassFile cf = this.getInstructions().getCode().getAttributes().getClassFile().getGroup().findClass(clazz.getName());
if (cf == null) if (cf == null)

View File

@@ -15,14 +15,14 @@ import java.io.IOException;
public class InstanceOf extends Instruction public class InstanceOf extends Instruction
{ {
private int index; private Class clazz;
public InstanceOf(Instructions instructions, InstructionType type, int pc) throws IOException public InstanceOf(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); clazz = this.getPool().getClass(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -30,16 +30,13 @@ public class InstanceOf extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(clazz));
} }
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Class clazz = (Class) pool.getEntry(index);
ObjectInstanceBase obj = (ObjectInstanceBase) e.getStack().pop(); ObjectInstanceBase obj = (ObjectInstanceBase) e.getStack().pop();
if (obj == null) if (obj == null)

View File

@@ -18,7 +18,7 @@ import java.io.IOException;
public class InvokeInterface extends Instruction public class InvokeInterface extends Instruction
{ {
private int index; private InterfaceMethod method;
private int count; private int count;
public InvokeInterface(Instructions instructions, InstructionType type, int pc) throws IOException public InvokeInterface(Instructions instructions, InstructionType type, int pc) throws IOException
@@ -26,7 +26,7 @@ public class InvokeInterface extends Instruction
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); method = this.getPool().getInterfaceMethod(is.readUnsignedShort());
count = is.readUnsignedByte(); count = is.readUnsignedByte();
is.skip(1); is.skip(1);
length += 4; length += 4;
@@ -36,19 +36,14 @@ public class InvokeInterface extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(method));
out.writeByte(count); out.writeByte(count);
out.writeByte(0); out.writeByte(0);
} }
@Override @Override
public void buildCallGraph() public void buildCallGraph()
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
InterfaceMethod method = (InterfaceMethod) pool.getEntry(index);
info.sigterm.deob.pool.Class clazz = method.getClassEntry(); info.sigterm.deob.pool.Class clazz = method.getClassEntry();
NameAndType nat = method.getNameAndType(); NameAndType nat = method.getNameAndType();
@@ -64,12 +59,7 @@ public class InvokeInterface extends Instruction
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
InterfaceMethod method = (InterfaceMethod) pool.getEntry(index);
ObjectInstance object = (ObjectInstance) e.getStack().pop(); ObjectInstance object = (ObjectInstance) e.getStack().pop();
ClassInstance objectType = object.getType(); ClassInstance objectType = object.getType();

View File

@@ -10,7 +10,6 @@ import info.sigterm.deob.execution.Frame;
import info.sigterm.deob.execution.ObjectInstance; import info.sigterm.deob.execution.ObjectInstance;
import info.sigterm.deob.pool.Method; import info.sigterm.deob.pool.Method;
import info.sigterm.deob.pool.NameAndType; import info.sigterm.deob.pool.NameAndType;
import info.sigterm.deob.pool.PoolEntry;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -18,14 +17,14 @@ import java.io.IOException;
public class InvokeSpecial extends Instruction public class InvokeSpecial extends Instruction
{ {
private int index; private Method method;
public InvokeSpecial(Instructions instructions, InstructionType type, int pc) throws IOException public InvokeSpecial(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); method = this.getPool().getMethod(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -33,17 +32,12 @@ public class InvokeSpecial extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(method));
} }
@Override @Override
public void buildCallGraph() public void buildCallGraph()
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
info.sigterm.deob.pool.Class clazz = method.getClassEntry(); info.sigterm.deob.pool.Class clazz = method.getClassEntry();
NameAndType nat = method.getNameAndType(); NameAndType nat = method.getNameAndType();
@@ -61,10 +55,6 @@ public class InvokeSpecial extends Instruction
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
int count = method.getNameAndType().getNumberOfArgs(); int count = method.getNameAndType().getNumberOfArgs();
ObjectInstance object = (ObjectInstance) e.getStack().pop(); ObjectInstance object = (ObjectInstance) e.getStack().pop();
@@ -89,10 +79,7 @@ public class InvokeSpecial extends Instruction
@Override @Override
public String getDesc(Frame frame) public String getDesc(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
Method method = (Method) thisClass.getPool().getEntry(index);
return "invokespecial " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName(); return "invokespecial " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName();
} }
} }

View File

@@ -15,14 +15,14 @@ import java.io.IOException;
public class InvokeStatic extends Instruction public class InvokeStatic extends Instruction
{ {
private int index; private Method method;
public InvokeStatic(Instructions instructions, InstructionType type, int pc) throws IOException public InvokeStatic(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); method = this.getPool().getMethod(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -30,17 +30,12 @@ public class InvokeStatic extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(method));
} }
@Override @Override
public void buildCallGraph() public void buildCallGraph()
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
info.sigterm.deob.pool.Class clazz = method.getClassEntry(); info.sigterm.deob.pool.Class clazz = method.getClassEntry();
NameAndType nat = method.getNameAndType(); NameAndType nat = method.getNameAndType();
@@ -60,8 +55,6 @@ public class InvokeStatic extends Instruction
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
info.sigterm.deob.pool.Class clazz = method.getClassEntry(); info.sigterm.deob.pool.Class clazz = method.getClassEntry();
ClassFile otherClass = thisClass.getGroup().findClass(clazz.getName()); ClassFile otherClass = thisClass.getGroup().findClass(clazz.getName());

View File

@@ -17,14 +17,14 @@ import java.io.IOException;
public class InvokeVirtual extends Instruction public class InvokeVirtual extends Instruction
{ {
private int index; private Method method;
public InvokeVirtual(Instructions instructions, InstructionType type, int pc) throws IOException public InvokeVirtual(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); method = this.getPool().getMethod(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -32,17 +32,12 @@ public class InvokeVirtual extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(method));
} }
@Override @Override
public void buildCallGraph() public void buildCallGraph()
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
info.sigterm.deob.pool.Class clazz = method.getClassEntry(); info.sigterm.deob.pool.Class clazz = method.getClassEntry();
NameAndType nat = method.getNameAndType(); NameAndType nat = method.getNameAndType();
@@ -61,10 +56,6 @@ public class InvokeVirtual extends Instruction
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool();
Method method = (Method) pool.getEntry(index);
int count = method.getNameAndType().getNumberOfArgs(); int count = method.getNameAndType().getNumberOfArgs();
Object[] args = new Object[count + 1]; Object[] args = new Object[count + 1];

View File

@@ -13,14 +13,14 @@ import java.io.IOException;
public class LDC extends Instruction public class LDC extends Instruction
{ {
private int index; private Object value;
public LDC(Instructions instructions, InstructionType type, int pc) throws IOException public LDC(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readByte(); value = this.getPool().get(is.readUnsignedByte());
length += 1; length += 1;
} }
@@ -28,14 +28,12 @@ public class LDC extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeByte(index); out.writeByte(this.getPool().make(value));
} }
@Override @Override
public void execute(Frame frame) public void execute(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); frame.getStack().push(this, value);
PoolEntry entry = thisClass.getPool().getEntry(index);
frame.getStack().push(this, entry.getObject());
} }
} }

View File

@@ -13,14 +13,14 @@ import java.io.IOException;
public class LDC2_W extends Instruction public class LDC2_W extends Instruction
{ {
private int index; private Object value;
public LDC2_W(Instructions instructions, InstructionType type, int pc) throws IOException public LDC2_W(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); value = this.getPool().get(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -28,14 +28,12 @@ public class LDC2_W extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(value));
} }
@Override @Override
public void execute(Frame frame) public void execute(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); frame.getStack().push(this, value);
PoolEntry entry = thisClass.getPool().getEntry(index);
frame.getStack().push(this, entry.getObject());
} }
} }

View File

@@ -13,14 +13,14 @@ import java.io.IOException;
public class LDC_W extends Instruction public class LDC_W extends Instruction
{ {
private int index; private Object value;
public LDC_W(Instructions instructions, InstructionType type, int pc) throws IOException public LDC_W(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); value = this.getPool().get(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -28,24 +28,19 @@ public class LDC_W extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(value));
} }
@Override @Override
public void execute(Frame frame) public void execute(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); frame.getStack().push(this, value);
PoolEntry entry = thisClass.getPool().getEntry(index);
frame.getStack().push(this, entry.getObject());
} }
@Override @Override
public String getDesc(Frame frame) public String getDesc(Frame frame)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); return "ldc_w " + value;
PoolEntry entry = thisClass.getPool().getEntry(index);
return "ldc_w " + entry.getObject();
} }
} }

View File

@@ -14,7 +14,7 @@ import java.io.IOException;
public class MultiANewArray extends Instruction public class MultiANewArray extends Instruction
{ {
private int index; private Class clazz;
private int dimensions; private int dimensions;
public MultiANewArray(Instructions instructions, InstructionType type, int pc) throws IOException public MultiANewArray(Instructions instructions, InstructionType type, int pc) throws IOException
@@ -22,7 +22,7 @@ public class MultiANewArray extends Instruction
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); clazz = this.getPool().getClass(is.readUnsignedShort());
dimensions = is.readUnsignedByte(); dimensions = is.readUnsignedByte();
length += 3; length += 3;
} }
@@ -31,7 +31,7 @@ public class MultiANewArray extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(clazz));
out.writeByte(dimensions); out.writeByte(dimensions);
} }
@@ -41,7 +41,6 @@ public class MultiANewArray extends Instruction
Stack stack = e.getStack(); Stack stack = e.getStack();
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
Class clazz = (Class) thisClass.getPool().getEntry(index);
// XXX primive type/array type ? [[I [[Lmyclass; etc // XXX primive type/array type ? [[I [[Lmyclass; etc
ClassFile cf = thisClass.getGroup().findClass(clazz.getName()); ClassFile cf = thisClass.getGroup().findClass(clazz.getName());

View File

@@ -15,14 +15,14 @@ import java.io.IOException;
public class New extends Instruction public class New extends Instruction
{ {
private int index; private Class clazz;
public New(Instructions instructions, InstructionType type, int pc) throws IOException public New(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); clazz = this.getPool().getClass(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -30,14 +30,13 @@ public class New extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(clazz));
} }
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
Class clazz = (Class) thisClass.getPool().getEntry(index);
ClassFile cf = thisClass.getGroup().findClass(clazz.getName()); ClassFile cf = thisClass.getGroup().findClass(clazz.getName());
if (cf == null) if (cf == null)
{ {

View File

@@ -17,14 +17,14 @@ import java.io.IOException;
public class PutField extends Instruction public class PutField extends Instruction
{ {
private int index; private Field field;
public PutField(Instructions instructions, InstructionType type, int pc) throws IOException public PutField(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); field = this.getPool().getField(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -32,17 +32,13 @@ public class PutField extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(field));
} }
@Override @Override
public void execute(Frame e) public void execute(Frame e)
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); NameAndType nat = field.getNameAndType();
ConstantPool pool = thisClass.getPool();
Field entry = (Field) pool.getEntry(index);
NameAndType nat = entry.getNameAndType();
ObjectInstance object = (ObjectInstance) e.getStack().pop(); ObjectInstance object = (ObjectInstance) e.getStack().pop();
Object value = e.getStack().pop(); Object value = e.getStack().pop();

View File

@@ -18,14 +18,14 @@ import java.io.IOException;
public class PutStatic extends Instruction public class PutStatic extends Instruction
{ {
private int index; private Field field;
public PutStatic(Instructions instructions, InstructionType type, int pc) throws IOException public PutStatic(Instructions instructions, InstructionType type, int pc) throws IOException
{ {
super(instructions, type, pc); super(instructions, type, pc);
DataInputStream is = instructions.getCode().getAttributes().getStream(); DataInputStream is = instructions.getCode().getAttributes().getStream();
index = is.readUnsignedShort(); field = this.getPool().getField(is.readUnsignedShort());
length += 2; length += 2;
} }
@@ -33,7 +33,7 @@ public class PutStatic extends Instruction
public void write(DataOutputStream out, int pc) throws IOException public void write(DataOutputStream out, int pc) throws IOException
{ {
super.write(out, pc); super.write(out, pc);
out.writeShort(index); out.writeShort(this.getPool().make(field));
} }
@Override @Override
@@ -41,10 +41,8 @@ public class PutStatic extends Instruction
{ {
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile(); ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
ConstantPool pool = thisClass.getPool(); Class clazz = field.getClassEntry();
Field entry = (Field) pool.getEntry(index); NameAndType nat = field.getNameAndType();
Class clazz = entry.getClassEntry();
NameAndType nat = entry.getNameAndType();
Object value = e.getStack().pop(); Object value = e.getStack().pop();

View File

@@ -9,6 +9,7 @@ import java.io.IOException;
public class Class extends PoolEntry public class Class extends PoolEntry
{ {
private int index; private int index;
private java.lang.String name;
public Class(ConstantPool pool) throws IOException public Class(ConstantPool pool) throws IOException
{ {
@@ -17,11 +18,32 @@ public class Class extends PoolEntry
DataInputStream is = pool.getClassFile().getStream(); DataInputStream is = pool.getClassFile().getStream();
index = is.readUnsignedShort(); index = is.readUnsignedShort();
} }
@Override
public void resolve()
{
name = this.getPool().getUTF8(index);
}
@Override
public void prime()
{
index = this.getPool().makeUTF8(name);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Class))
return false;
Class c = (Class) other;
return name.equals(c.name);
}
public java.lang.String getName() public java.lang.String getName()
{ {
UTF8 u = (UTF8) this.getPool().getEntry(index); return name;
return u.getValue();
} }
@Override @Override
@@ -29,4 +51,10 @@ public class Class extends PoolEntry
{ {
out.writeShort(index); out.writeShort(index);
} }
@Override
public Object getObject()
{
return name;
}
} }

View File

@@ -18,6 +18,23 @@ public class Double extends PoolEntry
value = is.readDouble(); value = is.readDouble();
} }
public Double(ConstantPool pool, double d)
{
super(pool, ConstantType.DOUBLE);
value = d;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Double))
return false;
Double d = (Double) other;
return value == d.value;
}
@Override @Override
public int getSlots() public int getSlots()

View File

@@ -8,8 +8,9 @@ import java.io.IOException;
public class Field extends PoolEntry public class Field extends PoolEntry
{ {
private int classIndex; private int classIndex, natIndex;
private int nameAndTypeIndex; private Class clazz;
private NameAndType nat;
public Field(ConstantPool pool) throws IOException public Field(ConstantPool pool) throws IOException
{ {
@@ -18,23 +19,47 @@ public class Field extends PoolEntry
DataInputStream is = pool.getClassFile().getStream(); DataInputStream is = pool.getClassFile().getStream();
classIndex = is.readUnsignedShort(); classIndex = is.readUnsignedShort();
nameAndTypeIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort();
}
@Override
public void resolve()
{
clazz = this.getPool().getClass(classIndex);
nat = this.getPool().getNameAndType(natIndex);
}
@Override
public void prime()
{
classIndex = this.getPool().make(clazz);
natIndex = this.getPool().make(nat);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Field))
return false;
Field f = (Field) other;
return clazz.equals(f.clazz) && nat.equals(f.nat);
} }
public Class getClassEntry() public Class getClassEntry()
{ {
return (Class) this.getPool().getEntry(classIndex); return clazz;
} }
public NameAndType getNameAndType() public NameAndType getNameAndType()
{ {
return (NameAndType) this.getPool().getEntry(nameAndTypeIndex); return nat;
} }
@Override @Override
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(classIndex); out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex); out.writeShort(natIndex);
} }
} }

View File

@@ -18,6 +18,23 @@ public class Float extends PoolEntry
value = is.readFloat(); value = is.readFloat();
} }
public Float(ConstantPool pool, float f)
{
super(pool, ConstantType.FLOAT);
value = f;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Float))
return false;
Float f = (Float) other;
return value == f.value;
}
@Override @Override
public Object getObject() public Object getObject()

View File

@@ -18,6 +18,23 @@ public class Integer extends PoolEntry
value = is.readInt(); value = is.readInt();
} }
public Integer(ConstantPool pool, int i)
{
super(pool, ConstantType.INTEGER);
value = i;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Integer))
return false;
Integer i = (Integer) other;
return value == i.value;
}
@Override @Override
public Object getObject() public Object getObject()

View File

@@ -8,8 +8,9 @@ import java.io.IOException;
public class InterfaceMethod extends PoolEntry public class InterfaceMethod extends PoolEntry
{ {
private int classIndex; private int classIndex, natIndex;
private int nameAndTypeIndex; private Class clazz;
private NameAndType nat;
public InterfaceMethod(ConstantPool pool) throws IOException public InterfaceMethod(ConstantPool pool) throws IOException
{ {
@@ -18,23 +19,47 @@ public class InterfaceMethod extends PoolEntry
DataInputStream is = pool.getClassFile().getStream(); DataInputStream is = pool.getClassFile().getStream();
classIndex = is.readUnsignedShort(); classIndex = is.readUnsignedShort();
nameAndTypeIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort();
}
@Override
public void resolve()
{
clazz = this.getPool().getClass(classIndex);
nat = this.getPool().getNameAndType(natIndex);
}
@Override
public void prime()
{
classIndex = this.getPool().make(clazz);
natIndex = this.getPool().make(nat);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof InterfaceMethod))
return false;
InterfaceMethod i = (InterfaceMethod) other;
return clazz.equals(i.clazz) && nat.equals(i.nat);
} }
public Class getClassEntry() public Class getClassEntry()
{ {
return (Class) this.getPool().getEntry(classIndex); return clazz;
} }
public NameAndType getNameAndType() public NameAndType getNameAndType()
{ {
return (NameAndType) this.getPool().getEntry(nameAndTypeIndex); return nat;
} }
@Override @Override
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(classIndex); out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex); out.writeShort(natIndex);
} }
} }

View File

@@ -18,6 +18,23 @@ public class Long extends PoolEntry
value = is.readLong(); value = is.readLong();
} }
public Long(ConstantPool pool, long l)
{
super(pool, ConstantType.LONG);
value = l;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Long))
return false;
Long l = (Long) other;
return value == l.value;
}
@Override @Override
public int getSlots() public int getSlots()

View File

@@ -8,8 +8,9 @@ import java.io.IOException;
public class Method extends PoolEntry public class Method extends PoolEntry
{ {
private int classIndex; private int classIndex, natIndex;
private int nameAndTypeIndex; private Class clazz;
private NameAndType nat;
public Method(ConstantPool pool) throws IOException public Method(ConstantPool pool) throws IOException
{ {
@@ -18,23 +19,47 @@ public class Method extends PoolEntry
DataInputStream is = pool.getClassFile().getStream(); DataInputStream is = pool.getClassFile().getStream();
classIndex = is.readUnsignedShort(); classIndex = is.readUnsignedShort();
nameAndTypeIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort();
}
@Override
public void resolve()
{
clazz = this.getPool().getClass(classIndex);
nat = this.getPool().getNameAndType(natIndex);
}
@Override
public void prime()
{
classIndex = this.getPool().make(clazz);
natIndex = this.getPool().make(nat);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof Method))
return false;
Method m = (Method) other;
return clazz.equals(m.clazz) && nat.equals(m.nat);
} }
public Class getClassEntry() public Class getClassEntry()
{ {
return (Class) this.getPool().getEntry(classIndex); return clazz;
} }
public NameAndType getNameAndType() public NameAndType getNameAndType()
{ {
return (NameAndType) this.getPool().getEntry(nameAndTypeIndex); return nat;
} }
@Override @Override
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
out.writeShort(classIndex); out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex); out.writeShort(natIndex);
} }
} }

View File

@@ -10,8 +10,8 @@ import java.util.regex.Pattern;
public class NameAndType extends PoolEntry public class NameAndType extends PoolEntry
{ {
private int nameIndex; private int nameIndex, descriptorIndex;
private int descriptorIndex; private java.lang.String name, descriptor;
public NameAndType(ConstantPool pool) throws IOException public NameAndType(ConstantPool pool) throws IOException
{ {
@@ -23,24 +23,46 @@ public class NameAndType extends PoolEntry
descriptorIndex = is.readUnsignedShort(); descriptorIndex = is.readUnsignedShort();
} }
public NameAndType(ConstantPool pool, int name, int type) public NameAndType(java.lang.String name, java.lang.String type)
{ {
super(pool, ConstantType.NAME_AND_TYPE); super(null, ConstantType.NAME_AND_TYPE);
this.nameIndex = name; this.name = name;
this.descriptorIndex = type; descriptor = type;
}
@Override
public void resolve()
{
name = this.getPool().getUTF8(nameIndex);
descriptor = this.getPool().getUTF8(descriptorIndex);
}
@Override
public void prime()
{
nameIndex = this.getPool().makeUTF8(name);
descriptorIndex = this.getPool().makeUTF8(descriptor);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof NameAndType))
return false;
NameAndType nat = (NameAndType) other;
return name.equals(nat.name) && descriptor.equals(nat.descriptor);
} }
public java.lang.String getName() public java.lang.String getName()
{ {
UTF8 u = (UTF8) this.getPool().getEntry(nameIndex); return name;
return u.getValue();
} }
public java.lang.String getDescriptor() public java.lang.String getDescriptor()
{ {
UTF8 u = (UTF8) this.getPool().getEntry(descriptorIndex); return descriptor;
return u.getValue();
} }
public Object getStackObject() public Object getStackObject()

View File

@@ -7,8 +7,9 @@ import info.sigterm.deob.ConstantPool;
public abstract class PoolEntry public abstract class PoolEntry
{ {
private ConstantPool pool; public ConstantPool pool;
private ConstantType type; private ConstantType type;
public int id;
protected PoolEntry(ConstantPool pool, ConstantType type) protected PoolEntry(ConstantPool pool, ConstantType type)
{ {
@@ -16,6 +17,18 @@ public abstract class PoolEntry
this.type = type; this.type = type;
} }
// read objects from indexes
public void resolve()
{
}
// make objects and prime indexes
public void prime()
{
}
public abstract boolean equals(Object other);
public abstract void write(DataOutputStream out) throws IOException; public abstract void write(DataOutputStream out) throws IOException;
public ConstantPool getPool() public ConstantPool getPool()
@@ -35,6 +48,6 @@ public abstract class PoolEntry
public Object getObject() public Object getObject()
{ {
throw new RuntimeException("No getObject implemented for " + this); return this;
} }
} }

View File

@@ -9,6 +9,7 @@ import java.io.IOException;
public class String extends PoolEntry public class String extends PoolEntry
{ {
private int stringIndex; private int stringIndex;
private java.lang.String string;
public String(ConstantPool pool) throws IOException public String(ConstantPool pool) throws IOException
{ {
@@ -18,11 +19,40 @@ public class String extends PoolEntry
stringIndex = is.readUnsignedShort(); stringIndex = is.readUnsignedShort();
} }
public String(ConstantPool pool, java.lang.String str)
{
super(pool, ConstantType.STRING);
string = str;
}
@Override
public void resolve()
{
string = this.getPool().getUTF8(stringIndex);
}
@Override
public void prime()
{
stringIndex = this.getPool().makeUTF8(string);
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof String))
return false;
String s = (String) other;
return string.equals(s.string);
}
@Override @Override
public Object getObject() public Object getObject()
{ {
return this.getPool().getEntry(stringIndex).getObject(); return string;
} }
@Override @Override

View File

@@ -8,58 +8,48 @@ import java.io.IOException;
public class UTF8 extends PoolEntry public class UTF8 extends PoolEntry
{ {
private StringBuilder sb = new StringBuilder(); private java.lang.String string;
public UTF8(ConstantPool pool) throws IOException public UTF8(ConstantPool pool) throws IOException
{ {
super(pool, ConstantType.UTF8); super(pool, ConstantType.UTF8);
DataInputStream ios = pool.getClassFile().getStream(); DataInputStream ios = pool.getClassFile().getStream();
string = ios.readUTF();
short length = ios.readShort(); }
for (int i = 0; i < length; i++)
{ public UTF8(java.lang.String value)
int a = ios.read(); {
if ((a & 0x80) == 0) super(null, ConstantType.UTF8);
{
sb.append((char)a); string = value;
} }
else if ((a & 0x20) == 0)
{ @Override
int b = ios.read(); public boolean equals(Object other)
char c = (char)(((a & 0x1f) << 6) + (b & 0x3f)); {
sb.append(c); if (!(other instanceof UTF8))
i++; return false;
}
else UTF8 u = (UTF8) other;
{ return string.equals(u.string);
int b = ios.read();
int c = ios.read();
char ch = (char)(((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f));
sb.append(ch);
i += 2;
}
}
} }
public java.lang.String getValue() public java.lang.String getValue()
{ {
return (java.lang.String) getObject(); return string;
} }
@Override @Override
public Object getObject() public Object getObject()
{ {
return sb.toString(); return getValue();
} }
@Override @Override
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
java.lang.String s = getValue(); java.lang.String s = getValue();
byte[] bytes = s.getBytes("UTF-8"); out.writeUTF(s);
out.writeShort(bytes.length);
out.write(bytes);
} }
} }