git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@2 379699f6-c40d-0410-875b-85095c16579estable
parent
1be1aaff37
commit
55a5ea33d9
@ -0,0 +1,18 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class Block extends Instruction { |
||||||
|
Expression[] exprs; |
||||||
|
|
||||||
|
public Block(int addr, int length, Expression[] exprs) { |
||||||
|
super(addr,length); |
||||||
|
this.exprs = exprs; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
for (int i=0; i< exprs.length; i++) |
||||||
|
exprs[i].dumpSource(writer,ca); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,10 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class AssertError extends Error { |
||||||
|
public AssertError() { |
||||||
|
} |
||||||
|
|
||||||
|
public AssertError(String detail) { |
||||||
|
super(detail); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
|
||||||
|
public class Decompiler { |
||||||
|
public static void main(String[] params) { |
||||||
|
JodeEnvironment env = new JodeEnvironment(); |
||||||
|
for (int i=0; i<params.length; i++) { |
||||||
|
env.doClass(params[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,225 @@ |
|||||||
|
package jode; |
||||||
|
import java.io.*; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public interface Opcodes { |
||||||
|
public final static int NOP_OP = 0; |
||||||
|
public final static int ACONST_NULL_OP = 1; |
||||||
|
public final static int ICONST_M1_OP = 2; |
||||||
|
public final static int ICONST_0_OP = 3; |
||||||
|
public final static int ICONST_1_OP = 4; |
||||||
|
public final static int ICONST_2_OP = 5; |
||||||
|
public final static int ICONST_3_OP = 6; |
||||||
|
public final static int ICONST_4_OP = 7; |
||||||
|
public final static int ICONST_5_OP = 8; |
||||||
|
public final static int LCONST_0_OP = 9; |
||||||
|
public final static int LCONST_1_OP = 10; |
||||||
|
public final static int FCONST_0_OP = 11; |
||||||
|
public final static int FCONST_1_OP = 12; |
||||||
|
public final static int FCONST_2_OP = 13; |
||||||
|
public final static int DCONST_0_OP = 14; |
||||||
|
public final static int DCONST_1_OP = 15; |
||||||
|
public final static int BIPUSH_OP = 16; |
||||||
|
public final static int SIPUSH_OP = 17; |
||||||
|
public final static int LDC_OP = 18; |
||||||
|
public final static int LDC_W_OP = 19; |
||||||
|
public final static int LDC2_W_OP = 20; |
||||||
|
public final static int ILOAD_OP = 21; |
||||||
|
public final static int LLOAD_OP = 22; |
||||||
|
public final static int FLOAD_OP = 23; |
||||||
|
public final static int DLOAD_OP = 24; |
||||||
|
public final static int ALOAD_OP = 25; |
||||||
|
public final static int ILOAD_0_OP = 26; |
||||||
|
public final static int ILOAD_1_OP = 27; |
||||||
|
public final static int ILOAD_2_OP = 28; |
||||||
|
public final static int ILOAD_3_OP = 29; |
||||||
|
public final static int LLOAD_0_OP = 30; |
||||||
|
public final static int LLOAD_1_OP = 31; |
||||||
|
public final static int LLOAD_2_OP = 32; |
||||||
|
public final static int LLOAD_3_OP = 33; |
||||||
|
public final static int FLOAD_0_OP = 34; |
||||||
|
public final static int FLOAD_1_OP = 35; |
||||||
|
public final static int FLOAD_2_OP = 36; |
||||||
|
public final static int FLOAD_3_OP = 37; |
||||||
|
public final static int DLOAD_0_OP = 38; |
||||||
|
public final static int DLOAD_1_OP = 39; |
||||||
|
public final static int DLOAD_2_OP = 40; |
||||||
|
public final static int DLOAD_3_OP = 41; |
||||||
|
public final static int ALOAD_0_OP = 42; |
||||||
|
public final static int ALOAD_1_OP = 43; |
||||||
|
public final static int ALOAD_2_OP = 44; |
||||||
|
public final static int ALOAD_3_OP = 45; |
||||||
|
public final static int IALOAD_OP = 46; |
||||||
|
public final static int LALOAD_OP = 47; |
||||||
|
public final static int FALOAD_OP = 48; |
||||||
|
public final static int DALOAD_OP = 49; |
||||||
|
public final static int AALOAD_OP = 50; |
||||||
|
public final static int BALOAD_OP = 51; |
||||||
|
public final static int CALOAD_OP = 52; |
||||||
|
public final static int SALOAD_OP = 53; |
||||||
|
public final static int ISTORE_OP = 54; |
||||||
|
public final static int LSTORE_OP = 55; |
||||||
|
public final static int FSTORE_OP = 56; |
||||||
|
public final static int DSTORE_OP = 57; |
||||||
|
public final static int ASTORE_OP = 58; |
||||||
|
public final static int ISTORE_0_OP = 59; |
||||||
|
public final static int ISTORE_1_OP = 60; |
||||||
|
public final static int ISTORE_2_OP = 61; |
||||||
|
public final static int ISTORE_3_OP = 62; |
||||||
|
public final static int LSTORE_0_OP = 63; |
||||||
|
public final static int LSTORE_1_OP = 64; |
||||||
|
public final static int LSTORE_2_OP = 65; |
||||||
|
public final static int LSTORE_3_OP = 66; |
||||||
|
public final static int FSTORE_0_OP = 67; |
||||||
|
public final static int FSTORE_1_OP = 68; |
||||||
|
public final static int FSTORE_2_OP = 69; |
||||||
|
public final static int FSTORE_3_OP = 70; |
||||||
|
public final static int DSTORE_0_OP = 71; |
||||||
|
public final static int DSTORE_1_OP = 72; |
||||||
|
public final static int DSTORE_2_OP = 73; |
||||||
|
public final static int DSTORE_3_OP = 74; |
||||||
|
public final static int ASTORE_0_OP = 75; |
||||||
|
public final static int ASTORE_1_OP = 76; |
||||||
|
public final static int ASTORE_2_OP = 77; |
||||||
|
public final static int ASTORE_3_OP = 78; |
||||||
|
public final static int IASTORE_OP = 79; |
||||||
|
public final static int LASTORE_OP = 80; |
||||||
|
public final static int FASTORE_OP = 81; |
||||||
|
public final static int DASTORE_OP = 82; |
||||||
|
public final static int AASTORE_OP = 83; |
||||||
|
public final static int BASTORE_OP = 84; |
||||||
|
public final static int CASTORE_OP = 85; |
||||||
|
public final static int SASTORE_OP = 86; |
||||||
|
public final static int POP_OP = 87; |
||||||
|
public final static int POP2_OP = 88; |
||||||
|
public final static int DUP_OP = 89; |
||||||
|
public final static int DUP_X1_OP = 90; |
||||||
|
public final static int DUP_X2_OP = 91; |
||||||
|
public final static int DUP2_OP = 92; |
||||||
|
public final static int DUP2_X1_OP = 93; |
||||||
|
public final static int DUP2_X2_OP = 94; |
||||||
|
public final static int SWAP_OP = 95; |
||||||
|
public final static int IADD_OP = 96; |
||||||
|
public final static int LADD_OP = 97; |
||||||
|
public final static int FADD_OP = 98; |
||||||
|
public final static int DADD_OP = 99; |
||||||
|
public final static int ISUB_OP = 100; |
||||||
|
public final static int LSUB_OP = 101; |
||||||
|
public final static int FSUB_OP = 102; |
||||||
|
public final static int DSUB_OP = 103; |
||||||
|
public final static int IMUL_OP = 104; |
||||||
|
public final static int LMUL_OP = 105; |
||||||
|
public final static int FMUL_OP = 106; |
||||||
|
public final static int DMUL_OP = 107; |
||||||
|
public final static int IDIV_OP = 108; |
||||||
|
public final static int LDIV_OP = 109; |
||||||
|
public final static int FDIV_OP = 110; |
||||||
|
public final static int DDIV_OP = 111; |
||||||
|
public final static int IREM_OP = 112; |
||||||
|
public final static int LREM_OP = 113; |
||||||
|
public final static int FREM_OP = 114; |
||||||
|
public final static int DREM_OP = 115; |
||||||
|
public final static int INEG_OP = 116; |
||||||
|
public final static int LNEG_OP = 117; |
||||||
|
public final static int FNEG_OP = 118; |
||||||
|
public final static int DNEG_OP = 119; |
||||||
|
public final static int ISHL_OP = 120; |
||||||
|
public final static int LSHL_OP = 121; |
||||||
|
public final static int ISHR_OP = 122; |
||||||
|
public final static int LSHR_OP = 123; |
||||||
|
public final static int IUSHR_OP = 124; |
||||||
|
public final static int LUSHR_OP = 125; |
||||||
|
public final static int IAND_OP = 126; |
||||||
|
public final static int LAND_OP = 127; |
||||||
|
public final static int IOR_OP = 128; |
||||||
|
public final static int LOR_OP = 129; |
||||||
|
public final static int IXOR_OP = 130; |
||||||
|
public final static int LXOR_OP = 131; |
||||||
|
public final static int IINC_OP = 132; |
||||||
|
public final static int I2L_OP = 133; |
||||||
|
public final static int I2F_OP = 134; |
||||||
|
public final static int I2D_OP = 135; |
||||||
|
public final static int L2I_OP = 136; |
||||||
|
public final static int L2F_OP = 137; |
||||||
|
public final static int L2D_OP = 138; |
||||||
|
public final static int F2I_OP = 139; |
||||||
|
public final static int F2L_OP = 140; |
||||||
|
public final static int F2D_OP = 141; |
||||||
|
public final static int D2I_OP = 142; |
||||||
|
public final static int D2L_OP = 143; |
||||||
|
public final static int D2F_OP = 144; |
||||||
|
public final static int I2B_OP = 145; |
||||||
|
public final static int I2C_OP = 146; |
||||||
|
public final static int I2S_OP = 147; |
||||||
|
public final static int LCMP_OP = 148; |
||||||
|
public final static int FCMPL_OP = 149; |
||||||
|
public final static int FCMPG_OP = 150; |
||||||
|
public final static int DCMPL_OP = 151; |
||||||
|
public final static int DCMPG_OP = 152; |
||||||
|
public final static int IFEQ_OP = 153; |
||||||
|
public final static int IFNE_OP = 154; |
||||||
|
public final static int IFLT_OP = 155; |
||||||
|
public final static int IFGE_OP = 156; |
||||||
|
public final static int IFGT_OP = 157; |
||||||
|
public final static int IFLE_OP = 158; |
||||||
|
public final static int IF_ICMPEQ_OP = 159; |
||||||
|
public final static int IF_ICMPNE_OP = 160; |
||||||
|
public final static int IF_ICMPLT_OP = 161; |
||||||
|
public final static int IF_ICMPGE_OP = 162; |
||||||
|
public final static int IF_ICMPGT_OP = 163; |
||||||
|
public final static int IF_ICMPLE_OP = 164; |
||||||
|
public final static int IF_ACMPEQ_OP = 165; |
||||||
|
public final static int IF_ACMPNE_OP = 166; |
||||||
|
public final static int GOTO_OP = 167; |
||||||
|
public final static int JSR_OP = 168; |
||||||
|
public final static int RET_OP = 169; |
||||||
|
public final static int TABLESWITCH_OP = 170; |
||||||
|
public final static int LOOKUPSWITCH_OP = 171; |
||||||
|
public final static int IRETURN_OP = 172; |
||||||
|
public final static int LRETURN_OP = 173; |
||||||
|
public final static int FRETURN_OP = 174; |
||||||
|
public final static int DRETURN_OP = 175; |
||||||
|
public final static int ARETURN_OP = 176; |
||||||
|
public final static int RETURN_OP = 177; |
||||||
|
public final static int GETSTATIC_OP = 178; |
||||||
|
public final static int PUTSTATIC_OP = 179; |
||||||
|
public final static int GETFIELD_OP = 180; |
||||||
|
public final static int PUTFIELD_OP = 181; |
||||||
|
public final static int INVOKEVIRTUAL_OP = 182; |
||||||
|
public final static int INVOKESPECIAL_OP = 183; |
||||||
|
public final static int INVOKESTATIC_OP = 184; |
||||||
|
public final static int INVOKEINTERFACE_OP = 185; |
||||||
|
public final static int NEW_OP = 187; |
||||||
|
public final static int NEWARRAY_OP = 188; |
||||||
|
public final static int ANEWARRAY_OP = 189; |
||||||
|
public final static int ARRAYLENGTH_OP = 190; |
||||||
|
public final static int ATHROW_OP = 191; |
||||||
|
public final static int CHECKCAST_OP = 192; |
||||||
|
public final static int INSTANCEOF_OP = 193; |
||||||
|
public final static int MONITORENTER_OP = 194; |
||||||
|
public final static int MONITOREXIT_OP = 195; |
||||||
|
public final static int WIDE_OP = 196; |
||||||
|
public final static int MULTIANEWARRAY_OP = 197; |
||||||
|
public final static int IFNULL_OP = 198; |
||||||
|
public final static int IFNONNULL_OP = 199; |
||||||
|
public final static int GOTO_W_OP = 200; |
||||||
|
public final static int JSR_W_OP = 201; |
||||||
|
|
||||||
|
public final static Type ALL_INT_TYPE = UnknownType.tUInt; |
||||||
|
public final static Type INT_TYPE = Type.tInt; |
||||||
|
public final static Type LONG_TYPE = Type.tLong; |
||||||
|
public final static Type FLOAT_TYPE = Type.tFloat; |
||||||
|
public final static Type DOUBLE_TYPE = Type.tDouble; |
||||||
|
public final static Type OBJECT_TYPE = UnknownType.tUObject; |
||||||
|
public final static Type BOOLEAN_TYPE = Type.tBoolean; |
||||||
|
public final static Type BYTE_TYPE = Type.tByte; |
||||||
|
public final static Type CHAR_TYPE = Type.tChar; |
||||||
|
public final static Type SHORT_TYPE = Type.tShort; |
||||||
|
|
||||||
|
|
||||||
|
public final static Type types[][] = { |
||||||
|
{ ALL_INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE }, |
||||||
|
{ INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE, |
||||||
|
BYTE_TYPE, CHAR_TYPE, SHORT_TYPE } |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public interface Analyzer { |
||||||
|
public void analyze(); |
||||||
|
public void dumpSource(TabbedPrintWriter writer) throws java.io.IOException; |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package jode; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.io.IOException; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class ClassAnalyzer implements Analyzer { |
||||||
|
BinaryClass cdef; |
||||||
|
JodeEnvironment env; |
||||||
|
Analyzer fields[]; |
||||||
|
|
||||||
|
public ClassAnalyzer(BinaryClass bc, JodeEnvironment e) |
||||||
|
{ |
||||||
|
cdef = bc; |
||||||
|
env = e; |
||||||
|
} |
||||||
|
|
||||||
|
public void analyze() { |
||||||
|
int numFields = 0, i=0; |
||||||
|
|
||||||
|
FieldDefinition f; |
||||||
|
for (f= cdef.getInnerClassField(); f != null; f = f.getNextField()) |
||||||
|
numFields++; |
||||||
|
for (f= cdef.getFirstField(); f != null; f = f.getNextField()) |
||||||
|
numFields++; |
||||||
|
fields = new Analyzer[numFields]; |
||||||
|
for (f= cdef.getInnerClassField(); f != null; f = f.getNextField()) { |
||||||
|
System.err.println("analyzing inner: "+f.getName()); |
||||||
|
fields[i] = new ClassAnalyzer((BinaryClass) f.getInnerClass(), env); |
||||||
|
fields[i++].analyze(); |
||||||
|
} |
||||||
|
for (f= cdef.getFirstField(); f != null; f = f.getNextField()) { |
||||||
|
if (f.getType().getTypeCode() == Constants.TC_METHOD) { |
||||||
|
System.err.println("analyzing method: "+f.getName()); |
||||||
|
fields[i] = new MethodAnalyzer(f, env); |
||||||
|
} else { |
||||||
|
System.err.println("analyzing field: "+f.getName()); |
||||||
|
fields[i] = new FieldAnalyzer(f, env); |
||||||
|
} |
||||||
|
fields[i++].analyze(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) throws IOException |
||||||
|
{ |
||||||
|
if (cdef.getSource() != null) |
||||||
|
writer.println("/* Original source: "+cdef.getSource()+" */"); |
||||||
|
String modif = Modifier.toString(cdef.getModifiers()); |
||||||
|
if (modif.length() > 0) |
||||||
|
writer.print(modif + " "); |
||||||
|
writer.print((cdef.isInterface())?"interface ":"class "); |
||||||
|
writer.println(env.getNickName(cdef.getName().toString())); |
||||||
|
writer.tab(); |
||||||
|
if (cdef.getSuperClass() != null) |
||||||
|
writer.println("extends "+cdef.getSuperClass().getName().toString()); |
||||||
|
ClassDeclaration interfaces[] = cdef.getInterfaces(); |
||||||
|
if (interfaces.length > 0) { |
||||||
|
writer.print("implements "); |
||||||
|
for (int i=0; i < interfaces.length; i++) { |
||||||
|
if (i > 0) |
||||||
|
writer.print(", "); |
||||||
|
writer.print(interfaces[i].getName().toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
writer.untab(); |
||||||
|
writer.println(" {"); |
||||||
|
writer.tab(); |
||||||
|
|
||||||
|
for (int i=0; i< fields.length; i++) |
||||||
|
fields[i].dumpSource(writer); |
||||||
|
writer.untab(); |
||||||
|
writer.println("}"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
|
||||||
|
public class FieldAnalyzer implements Analyzer { |
||||||
|
FieldDefinition fdef; |
||||||
|
JodeEnvironment env; |
||||||
|
|
||||||
|
public FieldAnalyzer(FieldDefinition fd, JodeEnvironment e) |
||||||
|
{ |
||||||
|
fdef = fd; |
||||||
|
env = e; |
||||||
|
} |
||||||
|
|
||||||
|
public void analyze() { |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
String modif = Modifier.toString(fdef.getModifiers()); |
||||||
|
if (modif.length() > 0) |
||||||
|
writer.print(modif+" "); |
||||||
|
|
||||||
|
writer.println(fdef.getType(). |
||||||
|
typeString(fdef.getName().toString(), false, false)+";"); |
||||||
|
// writer.tab();
|
||||||
|
// if (attributes.length > 0) {
|
||||||
|
// writer.println("/* Attributes: "+attributes.length+" */");
|
||||||
|
// for (int i=0; i < attributes.length; i++)
|
||||||
|
// attributes[i].dumpSource(writer);
|
||||||
|
// }
|
||||||
|
// writer.untab();
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,96 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
import sun.tools.util.*; |
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
public class JodeEnvironment extends LoadEnvironment { |
||||||
|
Hashtable imports = new Hashtable(); |
||||||
|
BinaryClass main; |
||||||
|
Identifier pkg; |
||||||
|
|
||||||
|
boolean isVerbose = true; |
||||||
|
|
||||||
|
JodeEnvironment() { |
||||||
|
super(null); |
||||||
|
path = new ClassPath(System.getProperty("java.class.path")); |
||||||
|
} |
||||||
|
|
||||||
|
public BinaryConstantPool getConstantPool() { |
||||||
|
return main.getConstants(); |
||||||
|
} |
||||||
|
|
||||||
|
public Object getConstant(int i) { |
||||||
|
return main.getConstants().getConstant(i, this); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getConstantType(int i) |
||||||
|
throws ClassFormatError |
||||||
|
{ |
||||||
|
int t = main.getConstants().getConstantType(i); |
||||||
|
switch(t) { |
||||||
|
case 3: return Type.tInt ; |
||||||
|
case 4: return Type.tFloat ; |
||||||
|
case 5: return Type.tLong ; |
||||||
|
case 6: return Type.tDouble; |
||||||
|
case 8: return Type.tString; |
||||||
|
default: |
||||||
|
throw new ClassFormatError("invalid constant type: "+t); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getNickName(String string) { |
||||||
|
return string; |
||||||
|
} |
||||||
|
|
||||||
|
public ClassDefinition getClassDefinition() { |
||||||
|
return main; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpHeader(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("/* Decompiled by JoDe (Jochen's Decompiler) */"); |
||||||
|
if (pkg != null && pkg != Constants.idNull) |
||||||
|
writer.println("package "+pkg+";"); |
||||||
|
Enumeration enum = imports.keys(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
Identifier packageName = (Identifier) enum.nextElement(); |
||||||
|
Integer vote = (Integer) imports.get(packageName); |
||||||
|
if (vote.intValue() > 3) |
||||||
|
writer.println("import "+packageName+";"); |
||||||
|
} |
||||||
|
writer.println(""); |
||||||
|
} |
||||||
|
|
||||||
|
public void error(String message) { |
||||||
|
System.err.println(message); |
||||||
|
} |
||||||
|
|
||||||
|
public void doClass(String className) |
||||||
|
{ |
||||||
|
try { |
||||||
|
Identifier ident = Identifier.lookup(className); |
||||||
|
error(ident.toString()); |
||||||
|
if (!classExists(ident)) { |
||||||
|
error("`"+ident+"' not found"); |
||||||
|
return; |
||||||
|
} |
||||||
|
pkg = ident.getQualifier(); |
||||||
|
main = (BinaryClass)getClassDefinition(ident); |
||||||
|
ClassAnalyzer a = new ClassAnalyzer(main, this); |
||||||
|
a.analyze(); |
||||||
|
TabbedPrintWriter writer = |
||||||
|
new TabbedPrintWriter(System.out, " "); |
||||||
|
a.dumpSource(writer); |
||||||
|
} catch (ClassNotFound e) { |
||||||
|
error(e.toString()); |
||||||
|
} catch (java.io.IOException e) { |
||||||
|
error(e.toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected int loadFileFlags() |
||||||
|
{ |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class LocalInfo { |
||||||
|
static int serialnr = 0; |
||||||
|
Identifier name; |
||||||
|
Type type; |
||||||
|
|
||||||
|
public LocalInfo() { |
||||||
|
name = Identifier.lookup("__"+serialnr); |
||||||
|
type = Type.tUnknown; |
||||||
|
serialnr++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,10 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import sun.tools.java.Identifier; |
||||||
|
|
||||||
|
public interface LocalVariable { |
||||||
|
public Identifier getName(int addr); |
||||||
|
public Type getType(int addr); |
||||||
|
public Type setType(int addr, Type type); |
||||||
|
public void combine(int addr1, int addr2); |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import sun.tools.java.Identifier; |
||||||
|
|
||||||
|
public class LocalVariableHash implements LocalVariable { |
||||||
|
Hashtable locals; |
||||||
|
|
||||||
|
private find(int addr) { |
||||||
|
LocalInfo li = (LocalInfo) locals.get(new Integer(addr)); |
||||||
|
if (li == null) { |
||||||
|
li = new LocalInfo(); |
||||||
|
locals.put(new Integer(addr), li); |
||||||
|
} |
||||||
|
return li; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getName(int addr) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
return li.name; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getType(int addr) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
return li.type; |
||||||
|
} |
||||||
|
|
||||||
|
public Type setType(int addr, Type type) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
li.type = UnknownType.commonType(li.type, type); |
||||||
|
return li.type; |
||||||
|
} |
||||||
|
|
||||||
|
public void combine(int addr1, int addr2) { |
||||||
|
LocalInfo li1 = find(addr1); |
||||||
|
LocalInfo li2 = find(addr2); |
||||||
|
li1.type = UnknownType.commonType(li1.type, li2.type); |
||||||
|
Enumeration keys = locals.keys(); |
||||||
|
while (keys.hasMoreElements()) { |
||||||
|
Object key = keys.nextElement(); |
||||||
|
if (locals.get(key) == li2) |
||||||
|
locals.put(key, li1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class LocalVariableRangeList implements LocalVariable { |
||||||
|
|
||||||
|
class MyLocalInfo extends LocalInfo { |
||||||
|
int start; |
||||||
|
int length; |
||||||
|
MyLocalInfo next; |
||||||
|
|
||||||
|
MyLocalInfo(int s, int l, Identifier n, Type t) { |
||||||
|
start = s; |
||||||
|
length = l; |
||||||
|
name = n; |
||||||
|
type = t; |
||||||
|
next = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
MyLocalInfo list = null; |
||||||
|
int slot; |
||||||
|
|
||||||
|
LocalVariableRangeList(int slot) { |
||||||
|
this.slot = slot; |
||||||
|
} |
||||||
|
|
||||||
|
private void add(MyLocalInfo li) { |
||||||
|
MyLocalInfo before = null; |
||||||
|
MyLocalInfo after = list; |
||||||
|
while (after != null && after.start < li.start) { |
||||||
|
before = after; |
||||||
|
after = after.next; |
||||||
|
} |
||||||
|
if (after != null && li.start + li.length > after.start) |
||||||
|
throw new AssertError("non disjoint locals"); |
||||||
|
li.next = after; |
||||||
|
if (before == null) |
||||||
|
list = li; |
||||||
|
else |
||||||
|
before.next = li; |
||||||
|
} |
||||||
|
|
||||||
|
private LocalInfo find(int addr) { |
||||||
|
MyLocalInfo li = list; |
||||||
|
while (li != null && addr > li.start+li.length) |
||||||
|
li = li.next; |
||||||
|
if (li == null || li.start > addr) { |
||||||
|
LocalInfo temp =new LocalInfo(); |
||||||
|
return temp; |
||||||
|
} |
||||||
|
return li; |
||||||
|
} |
||||||
|
|
||||||
|
public void addLocal(int start, int length, |
||||||
|
Identifier name, Type type) { |
||||||
|
MyLocalInfo li = new MyLocalInfo(start,length,name,type); |
||||||
|
add (li); |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getName(int addr) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
return li.name; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getType(int addr) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
return li.type; |
||||||
|
} |
||||||
|
|
||||||
|
public LocalInfo getInfo(int addr) { |
||||||
|
return find(addr); |
||||||
|
} |
||||||
|
|
||||||
|
public Type setType(int addr, Type newType) { |
||||||
|
LocalInfo li = find(addr); |
||||||
|
return commonType(newType, li.type); |
||||||
|
} |
||||||
|
|
||||||
|
public void combine(int addr1, int addr2) { |
||||||
|
throw AssertError("combine called on RangeList"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
import java.io.*; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class LocalVariableTable { |
||||||
|
Vector locals; |
||||||
|
boolean readfromclass; |
||||||
|
|
||||||
|
public LocalVariableTable(int size) { |
||||||
|
locals = new Vector(); |
||||||
|
locals.setSize(size); |
||||||
|
readfromclass = false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isReadFromClass() { |
||||||
|
return readfromclass; |
||||||
|
} |
||||||
|
|
||||||
|
public void read(JodeEnvironment env, DataInputStream stream) |
||||||
|
throws IOException |
||||||
|
{ |
||||||
|
int count = stream.readUnsignedShort(); |
||||||
|
for (int i=0; i<count; i++) { |
||||||
|
int start = stream.readUnsignedShort(); |
||||||
|
int length = stream.readUnsignedShort(); |
||||||
|
int name_i = stream.readUnsignedShort(); |
||||||
|
int desc_i = stream.readUnsignedShort(); |
||||||
|
int slot = stream.readUnsignedShort(); |
||||||
|
LocalVariableRangeList lv = |
||||||
|
(LocalVariableRangeList)locals.elementAt(slot); |
||||||
|
if (lv == null) { |
||||||
|
lv = new LocalVariableRangeList(slot); |
||||||
|
locals.setElementAt(lv, slot); |
||||||
|
} |
||||||
|
lv.addLocal(start, length, |
||||||
|
Identifier.lookup((String) |
||||||
|
env.getConstantPool(). |
||||||
|
getValue(name_i)), |
||||||
|
env.getConstantPool().getType(desc_i)); |
||||||
|
} |
||||||
|
readfromclass = true; |
||||||
|
} |
||||||
|
|
||||||
|
public LocalVariable getLocal(int slot) |
||||||
|
throws ArrayOutOfBoundsException |
||||||
|
{ |
||||||
|
LocalVariable lv = (LocalVariable)locals.elementAt(slot); |
||||||
|
if (lv == null) { |
||||||
|
lv = new LocalVariable(slot); |
||||||
|
locals.setElementAt(lv, slot); |
||||||
|
} |
||||||
|
return lv; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,135 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class MethodAnalyzer implements Analyzer, Constants { |
||||||
|
FieldDefinition mdef; |
||||||
|
JodeEnvironment env; |
||||||
|
CodeAnalyzer code = null; |
||||||
|
LocalVariableTable lvt; |
||||||
|
|
||||||
|
public MethodAnalyzer(FieldDefinition fd, JodeEnvironment e) |
||||||
|
{ |
||||||
|
mdef = fd; |
||||||
|
env = e; |
||||||
|
byte bytecode[] = ((BinaryField) mdef).getAttribute(Constants.idCode); |
||||||
|
if (bytecode != null) { |
||||||
|
BinaryCode bc = |
||||||
|
new BinaryCode(bytecode, |
||||||
|
env.getConstantPool(), |
||||||
|
env); |
||||||
|
lvt = new LocalVariableTable(bc.getMaxLocals()); |
||||||
|
readLVT(bc); |
||||||
|
code = new CodeAnalyzer(this, bc, env); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void readLVT(BinaryCode bc) { |
||||||
|
BinaryAttribute attr = bc.getAttributes(); |
||||||
|
while (attr != null) { |
||||||
|
if (attr.getName() == idLocalVariableTable) { |
||||||
|
DataInputStream stream = |
||||||
|
new DataInputStream |
||||||
|
(new ByteArrayInputStream(attr.getData())); |
||||||
|
try { |
||||||
|
lvt.read(env, stream); |
||||||
|
} catch (IOException ex) { |
||||||
|
throw new ClassFormatError(ex.toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
attr = attr.getNextAttribute(); |
||||||
|
} |
||||||
|
if (!lvt.isReadFromClass()) { |
||||||
|
int offset = 0; |
||||||
|
if (!mdef.isStatic()) { |
||||||
|
LocalInfo li = lvt.getLocal(0); |
||||||
|
li.name = "this"; |
||||||
|
li.type = mdef.getClassDefinition().getType(); |
||||||
|
offset++; |
||||||
|
} |
||||||
|
Type[] paramTypes = mdef.getType().getArgumentTypes(); |
||||||
|
for (int i=0; i< paramTypes.length; i++) { |
||||||
|
LocalInfo li = lvt.getLocal(offset+i); |
||||||
|
li.type = paramTypes[i]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void analyze() |
||||||
|
throws ClassFormatError |
||||||
|
{ |
||||||
|
code.analyze(); |
||||||
|
} |
||||||
|
|
||||||
|
public LocalVariable getLocal(int i) { |
||||||
|
return lvt.getLocal(i); |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getLocalName(int i, int addr) { |
||||||
|
Identifier name = lvt.getLocal(i).getName(addr); |
||||||
|
if (name != null) |
||||||
|
return name; |
||||||
|
if (!mdef.isStatic() && i == 0) |
||||||
|
return idThis; |
||||||
|
return Identifier.lookup("local_"+i+"@"+addr); |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println(""); |
||||||
|
String modif = Modifier.toString(mdef.getModifiers()); |
||||||
|
if (modif.length() > 0) |
||||||
|
writer.print(modif+" "); |
||||||
|
if (mdef.isInitializer()) { |
||||||
|
writer.print(""); /* static block */ |
||||||
|
} else { |
||||||
|
if (mdef.isConstructor()) |
||||||
|
writer.print(mdef.getClassDeclaration().getName().toString()); |
||||||
|
else |
||||||
|
writer.print(mdef.getType().getReturnType().toString()+" "+ |
||||||
|
mdef.getName().toString()); |
||||||
|
writer.print("("); |
||||||
|
Type[] paramTypes = mdef.getType().getArgumentTypes(); |
||||||
|
int offset = mdef.isStatic()?0:1; |
||||||
|
for (int i=0; i<paramTypes.length; i++) { |
||||||
|
if (i>0) |
||||||
|
writer.print(", "); |
||||||
|
writer.print(paramTypes[i]. |
||||||
|
typeString(getLocalName(i+offset, 0).toString(), |
||||||
|
false, false)); |
||||||
|
} |
||||||
|
writer.print(")"); |
||||||
|
} |
||||||
|
IdentifierToken[] exceptions = mdef.getExceptionIds(); |
||||||
|
if (exceptions != null && exceptions.length > 0) { |
||||||
|
writer.println(""); |
||||||
|
writer.print("throws "); |
||||||
|
for (int i= 0; i< exceptions.length; i++) { |
||||||
|
if (exceptions[i] != null) { |
||||||
|
if (i > 0) |
||||||
|
writer.print(", "); |
||||||
|
writer.print(exceptions[i].getName().toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (code != null) { |
||||||
|
writer.println(" {"); |
||||||
|
writer.tab(); |
||||||
|
code.dumpSource(writer); |
||||||
|
writer.untab(); |
||||||
|
writer.println("}"); |
||||||
|
} else |
||||||
|
writer.println(";"); |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
public byte[] getAttribute(Identifier identifier) |
||||||
|
{ |
||||||
|
if (mdef instanceof BinaryField) |
||||||
|
return ((BinaryField)mdef).getAttribute(identifier); |
||||||
|
return null; |
||||||
|
} |
||||||
|
*/ |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package jode; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class TabbedPrintWriter { |
||||||
|
boolean atbol; |
||||||
|
String tabstr; |
||||||
|
StringBuffer indent; |
||||||
|
PrintWriter pw; |
||||||
|
int verbosity=100; |
||||||
|
|
||||||
|
public TabbedPrintWriter (OutputStream os, String tabstr) { |
||||||
|
pw = new PrintWriter(os); |
||||||
|
this.tabstr=tabstr; |
||||||
|
indent = new StringBuffer(); |
||||||
|
atbol = true; |
||||||
|
} |
||||||
|
|
||||||
|
public void tab() { |
||||||
|
indent.append(tabstr); |
||||||
|
} |
||||||
|
|
||||||
|
public void untab() { |
||||||
|
indent.setLength(indent.length()-tabstr.length()); |
||||||
|
} |
||||||
|
|
||||||
|
public void println(String str) throws java.io.IOException { |
||||||
|
if (atbol) { |
||||||
|
pw.print(indent); |
||||||
|
} |
||||||
|
pw.println(str); |
||||||
|
pw.flush(); |
||||||
|
atbol = true; |
||||||
|
} |
||||||
|
|
||||||
|
public void print(String str) throws java.io.IOException { |
||||||
|
if (atbol) { |
||||||
|
pw.print(indent); |
||||||
|
} |
||||||
|
pw.print(str); |
||||||
|
atbol = false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class ArrayLengthOperator extends Operator { |
||||||
|
|
||||||
|
Type arrayType; |
||||||
|
|
||||||
|
public ArrayLengthOperator(int addr, int length) { |
||||||
|
super(addr,length, Type.tInt, 0); |
||||||
|
arrayType = Type.tArray(UnknownType.tUnknown); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 900; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return arrayType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] types) { |
||||||
|
arrayType = UnknownType.commonType(arrayType,types[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + ".length"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import sun.tools.java.ArrayType; |
||||||
|
|
||||||
|
public class ArrayLoadOperator extends SimpleOperator { |
||||||
|
String value; |
||||||
|
|
||||||
|
public ArrayLoadOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, type, 0, 2); |
||||||
|
operandTypes[0] = Type.tArray(type); |
||||||
|
operandTypes[1] = UnknownType.tUIndex; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return (i==0)?950:0; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type type) { |
||||||
|
if (type != this.type) { |
||||||
|
super.setType(type); |
||||||
|
operandTypes[0] = Type.tArray(type); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] t) { |
||||||
|
super.setOperandType(t); |
||||||
|
if (operandTypes[0] instanceof ArrayType) |
||||||
|
type = operandTypes[0].getElementType(); |
||||||
|
else |
||||||
|
type = Type.tError; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0]+"["+operands[1]+"]"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import sun.tools.java.ArrayType; |
||||||
|
|
||||||
|
public class ArrayStoreOperator extends StoreInstruction { |
||||||
|
Type indexType; |
||||||
|
|
||||||
|
public ArrayStoreOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, type); |
||||||
|
indexType = UnknownType.tUIndex; |
||||||
|
} |
||||||
|
|
||||||
|
public ArrayStoreOperator(int addr, int length, Type type, int operator) { |
||||||
|
super(addr,length, type, operator); |
||||||
|
indexType = UnknownType.tUIndex; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean matches(Operator loadop) { |
||||||
|
return loadop instanceof ArrayLoadOperator; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandCount() { |
||||||
|
return 2; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandPriority(int i) { |
||||||
|
if (i == 0) |
||||||
|
return 950; |
||||||
|
else |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getLValueOperandType(int i) { |
||||||
|
if (i == 0) |
||||||
|
return Type.tArray(lvalueType); |
||||||
|
else |
||||||
|
return indexType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLValueOperandType(Type[] t) { |
||||||
|
indexType = UnknownType.commonType(indexType, t[1]); |
||||||
|
Type arraytype = |
||||||
|
UnknownType.commonType(t[0], Type.tArray(lvalueType)); |
||||||
|
System.err.println("lvot: "+t[0]+","+Type.tArray(lvalueType)+ |
||||||
|
" -> "+arraytype); |
||||||
|
if (arraytype instanceof ArrayType) |
||||||
|
lvalueType = arraytype.getElementType(); |
||||||
|
else { |
||||||
|
System.err.println("no array: "+arraytype); |
||||||
|
lvalueType = Type.tError; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getLValueString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0]+"["+operands[1]+"]"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class AssignOperator extends BinaryOperator { |
||||||
|
StoreInstruction store; |
||||||
|
|
||||||
|
public AssignOperator(int addr, int length, int op, |
||||||
|
StoreInstruction store) { |
||||||
|
super(addr,length, store.getLValueType(), op); |
||||||
|
this.store = store; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return store.getOperandCount(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return store.getOperandPriority(i); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return store.getOperandType(i); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type type) { |
||||||
|
boolean result = store.setLValueType(type); |
||||||
|
super.setType(store.getLValueType()); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Overload this method if the resulting type depends on the input types |
||||||
|
*/ |
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
store.setOperandType(inputTypes); |
||||||
|
this.type = store.getLValueType(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return store.toString(ca, operands); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,72 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class BinaryOperator extends Operator { |
||||||
|
protected Type operandType; |
||||||
|
|
||||||
|
public BinaryOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, type, op); |
||||||
|
operandType = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 2; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
switch (operator) { |
||||||
|
case 1: case 2: |
||||||
|
return 610; |
||||||
|
case 3: case 4: case 5: |
||||||
|
return 650; |
||||||
|
case 6: case 7: case 8: |
||||||
|
return 600; |
||||||
|
case 9: |
||||||
|
return 450; |
||||||
|
case 10: |
||||||
|
return 410; |
||||||
|
case 11: |
||||||
|
return 420; |
||||||
|
case 12: case 13: case 14: case 15: case 16: case 17: |
||||||
|
case 18: case 19: case 20: case 21: case 22: case 23: |
||||||
|
return 100; |
||||||
|
case LOG_OR_OP: |
||||||
|
return 310; |
||||||
|
case LOG_AND_OP: |
||||||
|
return 350; |
||||||
|
} |
||||||
|
throw new RuntimeException("Illegal operator"); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority() + i; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return operandType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
operandType = UnknownType.commonType |
||||||
|
(operandType, UnknownType.commonType(inputTypes[0], |
||||||
|
inputTypes[1])); |
||||||
|
type = operandType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type newType) { |
||||||
|
operandType = UnknownType.commonType(operandType, newType); |
||||||
|
if (type != operandType) { |
||||||
|
type = operandType; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + " "+getOperatorString()+" "+ operands[1]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CheckCastOperator extends SimpleOperator { |
||||||
|
public CheckCastOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, type, 0, 1); |
||||||
|
operandTypes[0] = UnknownType.tSubClass(type); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 700; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "("+ca.getTypeString(type) + ")" + operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CompareBinaryOperator extends SimpleOperator { |
||||||
|
public CompareBinaryOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, Type.tBoolean, op, 2); |
||||||
|
operandTypes[0] = operandTypes[1] = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
switch (getOperator()) { |
||||||
|
case 26: |
||||||
|
case 27: |
||||||
|
return 500; |
||||||
|
case 28: |
||||||
|
case 29: |
||||||
|
case 30: |
||||||
|
case 31: |
||||||
|
return 550; |
||||||
|
} |
||||||
|
throw new RuntimeException("Illegal operator"); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority()+i; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
super.setOperandType(inputTypes); |
||||||
|
Type operandType = |
||||||
|
UnknownType.commonType(operandTypes[0],operandTypes[1]); |
||||||
|
operandTypes[0] = operandTypes[1] = operandType; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + " "+opString[operator]+" "+operands[1]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CompareToIntOperator extends BinaryOperator { |
||||||
|
public CompareToIntOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, Type.tInt, op); |
||||||
|
operandType = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
switch (getOperator()) { |
||||||
|
case 25: |
||||||
|
case 26: |
||||||
|
return 500; |
||||||
|
case 27: |
||||||
|
case 28: |
||||||
|
case 29: |
||||||
|
case 30: |
||||||
|
return 550; |
||||||
|
} |
||||||
|
throw new RuntimeException("Illegal operator"); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + " "+opString[operator]+" "+operands[1]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CompareUnaryOperator extends SimpleOperator { |
||||||
|
public CompareUnaryOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, Type.tBoolean, op, 1); |
||||||
|
operandTypes[0] = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
switch (getOperator()) { |
||||||
|
case 26: |
||||||
|
case 27: |
||||||
|
return 500; |
||||||
|
case 28: |
||||||
|
case 29: |
||||||
|
case 30: |
||||||
|
case 31: |
||||||
|
return 550; |
||||||
|
} |
||||||
|
throw new RuntimeException("Illegal operator"); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
if (operandTypes[0] == Type.tBoolean) { |
||||||
|
if (operator == 26) /* xx == false */ |
||||||
|
return "! ("+operands[0]+")"; /*XXX Make operators */ |
||||||
|
else if (operator == 27) /* xx != false */ |
||||||
|
return operands[0]; |
||||||
|
} |
||||||
|
return operands[0] + " "+opString[operator]+" "+ |
||||||
|
(UnknownType.isOfType(operandTypes[0], |
||||||
|
UnknownType.tObject)?"null":"0"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class ConstOperator extends NoArgOperator { |
||||||
|
String value; |
||||||
|
|
||||||
|
public ConstOperator(int addr, int length, Type type, String value) { |
||||||
|
super(addr, length, type); |
||||||
|
this.value = value; |
||||||
|
} |
||||||
|
|
||||||
|
public String getValue() { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 1000; |
||||||
|
} |
||||||
|
|
||||||
|
public String quoted(String str) { |
||||||
|
StringBuffer result = new StringBuffer("\""); |
||||||
|
for (int i=0; i< value.length(); i++) { |
||||||
|
switch (value.charAt(i)) { |
||||||
|
case '\t': |
||||||
|
result.append("\\t"); |
||||||
|
break; |
||||||
|
case '\n': |
||||||
|
result.append("\\n"); |
||||||
|
break; |
||||||
|
case '\\': |
||||||
|
result.append("\\\\"); |
||||||
|
break; |
||||||
|
case '\"': |
||||||
|
result.append("\\\""); |
||||||
|
break; |
||||||
|
default: |
||||||
|
result.append(value.charAt(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
return result.append("\"").toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
if (type == Type.tString) |
||||||
|
return quoted(value); |
||||||
|
if (type == Type.tBoolean) { |
||||||
|
if (value.equals("0")) |
||||||
|
return "false"; |
||||||
|
else if (value.equals("1")) |
||||||
|
return "true"; |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,45 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class ConstructorOperator extends Operator { |
||||||
|
FieldDefinition field; |
||||||
|
|
||||||
|
public ConstructorOperator(int addr, int length, Type type, |
||||||
|
FieldDefinition field) { |
||||||
|
super(addr,length, type, 0); |
||||||
|
this.field = field; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1 + field.getType().getArgumentTypes().length; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
if (i == 0) |
||||||
|
return 950; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
if (i == 0) |
||||||
|
return type; |
||||||
|
return field.getType().getArgumentTypes()[i-1]; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
StringBuffer result = new StringBuffer(operands[0]).append("("); |
||||||
|
for (int i=0; i < field.getType().getArgumentTypes().length; i++) { |
||||||
|
if (i>0) |
||||||
|
result.append(", "); |
||||||
|
result.append(operands[i+1]); |
||||||
|
} |
||||||
|
return result.append(")").toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class ConvertOperator extends Operator { |
||||||
|
Type from; |
||||||
|
|
||||||
|
public ConvertOperator(int addr, int length, Type from, Type to) { |
||||||
|
super(addr,length, to, 0); |
||||||
|
this.from = from; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 700; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 700; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return from; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
from = UnknownType.commonType(from, inputTypes[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) |
||||||
|
{ |
||||||
|
return "("+ca.getTypeString(type)+") "+operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class DupOperator extends Instruction { |
||||||
|
int count, depth; |
||||||
|
|
||||||
|
public DupOperator(int a, int l, int depth, int count) { |
||||||
|
super(a,l); |
||||||
|
this.count = count; |
||||||
|
this.depth = depth; |
||||||
|
} |
||||||
|
|
||||||
|
public int getCount(){ |
||||||
|
return count; |
||||||
|
} |
||||||
|
|
||||||
|
public int getDepth(){ |
||||||
|
return depth; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
tpw.println("dup"+count+"_x"+depth+";"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,128 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class Expression extends Instruction { |
||||||
|
Operator operator; |
||||||
|
Expression[] subExpressions; |
||||||
|
|
||||||
|
protected Expression(int addr, int length) { |
||||||
|
super(addr, length); |
||||||
|
} |
||||||
|
|
||||||
|
public Expression(int addr, int length, Operator op, Expression[] sub) { |
||||||
|
super(addr, length); |
||||||
|
operator = op; |
||||||
|
subExpressions = sub; |
||||||
|
if (op.getOperandCount() > 0) { |
||||||
|
Type types[] = new Type[subExpressions.length]; |
||||||
|
for (int i=0; i < types.length; i++) { |
||||||
|
types[i] = subExpressions[i].getType(); |
||||||
|
} |
||||||
|
operator.setOperandType(types); |
||||||
|
updateSubTypes(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Expression negate() { |
||||||
|
if (operator.operator >= operator.COMPARE_OP && |
||||||
|
operator.operator < operator.COMPARE_OP+6) { |
||||||
|
operator.setOperator(operator.getOperator() ^ 1); |
||||||
|
return this; |
||||||
|
} else if (operator.operator == operator.LOG_AND_OP || |
||||||
|
operator.operator == operator.LOG_OR_OP) { |
||||||
|
operator.setOperator(operator.getOperator() ^ 1); |
||||||
|
for (int i=0; i< subExpressions.length; i++) { |
||||||
|
subExpressions[i] = subExpressions[i].negate(); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} else if (operator.operator == operator.LOG_NOT_OP) { |
||||||
|
return subExpressions[0]; |
||||||
|
} |
||||||
|
|
||||||
|
Operator negop = |
||||||
|
new UnaryOperator(getAddr(), getLength(), |
||||||
|
Type.tBoolean, Operator.LOG_NOT_OP); |
||||||
|
Expression[] e = { this }; |
||||||
|
return new Expression(getAddr(), getLength(), negop, e); |
||||||
|
} |
||||||
|
|
||||||
|
public Operator getOperator() { |
||||||
|
return operator; |
||||||
|
} |
||||||
|
|
||||||
|
public Expression[] getSubExpressions() { |
||||||
|
return subExpressions; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getType() { |
||||||
|
return operator.getType(); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateSubTypes() { |
||||||
|
for (int i=0; i < subExpressions.length; i++) { |
||||||
|
subExpressions[i].setType(operator.getOperandType(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setType(Type type) { |
||||||
|
if (operator.setType(type)) |
||||||
|
updateSubTypes(); |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
return operator.getSuccessors(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isVoid() { |
||||||
|
return operator.getType() == Type.tVoid; |
||||||
|
} |
||||||
|
|
||||||
|
String toString(CodeAnalyzer ca, int minPriority) { |
||||||
|
String[] expr = new String[subExpressions.length]; |
||||||
|
for (int i=0; i<subExpressions.length; i++) { |
||||||
|
expr[i] = subExpressions[i]. |
||||||
|
toString(ca, operator.getOperandPriority(i)); |
||||||
|
} |
||||||
|
String result = operator.toString(ca, expr); |
||||||
|
if (operator.getPriority() < minPriority) { |
||||||
|
result = "("+result+")"; |
||||||
|
} |
||||||
|
if (operator.casts.indexOf("/*",0) >= 0 || |
||||||
|
operator.casts.indexOf("<-",0) >= 0 && false) |
||||||
|
result = "<"+operator.casts+" "+result+">"; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Expression expr) { |
||||||
|
if (this == expr) |
||||||
|
return true; |
||||||
|
if (!operator.equals(expr.operator) || |
||||||
|
subExpressions.length != expr.subExpressions.length) |
||||||
|
return false; |
||||||
|
for (int i=0; i<subExpressions.length; i++) { |
||||||
|
if (subExpressions[i] != expr.subExpressions[i]) |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (writer.verbosity > 6) { |
||||||
|
writer.print("< "+ |
||||||
|
ca.getTypeString(operator.getType())+" "+ |
||||||
|
operator.getClass().getName()+"("); |
||||||
|
for (int i=0; i< subExpressions.length; i++) { |
||||||
|
if (i>0) |
||||||
|
writer.print(", "); |
||||||
|
writer.print("("+ca.getTypeString(operator.getOperandType(i))+ |
||||||
|
") "+ca.getTypeString(subExpressions[i].getType())); |
||||||
|
} |
||||||
|
writer.println(") >"); |
||||||
|
} |
||||||
|
if (!isVoid()) |
||||||
|
writer.print("push "); |
||||||
|
writer.println(toString(ca, 0)+";"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class GetFieldOperator extends Operator { |
||||||
|
boolean staticFlag; |
||||||
|
FieldDefinition field; |
||||||
|
|
||||||
|
public GetFieldOperator(int addr, int length, boolean staticFlag, |
||||||
|
FieldDefinition field) { |
||||||
|
super(addr, length, field.getType(), 0); |
||||||
|
this.staticFlag = staticFlag; |
||||||
|
this.field = field; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return staticFlag?0:1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
if (staticFlag) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("Field is static"); |
||||||
|
} |
||||||
|
return 900; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
if (staticFlag) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("Field is static"); |
||||||
|
} |
||||||
|
return field.getClassDeclaration().getType(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
String object; |
||||||
|
if (staticFlag) { |
||||||
|
if (field.getClassDefinition() == ca.getClassDefinition()) |
||||||
|
return field.getName().toString(); |
||||||
|
object = |
||||||
|
ca.getTypeString(field.getClassDeclaration().getType()); |
||||||
|
} else { |
||||||
|
if (operands[0].equals("this")) |
||||||
|
return field.getName().toString(); |
||||||
|
object = operands[0]; |
||||||
|
} |
||||||
|
return object + "." + field.getName(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class GotoOperator extends JumpInstruction { |
||||||
|
protected int destination; |
||||||
|
|
||||||
|
public GotoOperator(int addr, int length, int dest) { |
||||||
|
super(addr,length); |
||||||
|
this.destination = dest; |
||||||
|
} |
||||||
|
|
||||||
|
public int getDestination() { |
||||||
|
return destination; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
int [] result = { destination }; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "goto addr_" + destination; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class IfGotoOperator extends JumpInstruction { |
||||||
|
protected int destination; |
||||||
|
|
||||||
|
public IfGotoOperator(int addr, int length, int dest) { |
||||||
|
super(addr,length); |
||||||
|
destination = dest; |
||||||
|
} |
||||||
|
|
||||||
|
public int getDestination() { |
||||||
|
return destination; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 200; /* force parentheses around assignments */ |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return Type.tBoolean; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
int [] result = { destination, getAddr() + getLength() }; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "if ("+operands[0]+") goto addr_" + destination; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class IfThenElseOperator extends SimpleOperator { |
||||||
|
public IfThenElseOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, type, 0, 3); |
||||||
|
operandTypes[0] = Type.tBoolean; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 3; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 200; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
switch (i) { |
||||||
|
case 0: |
||||||
|
return 201; |
||||||
|
case 1: |
||||||
|
return 0; |
||||||
|
case 2: |
||||||
|
return 200; |
||||||
|
default: |
||||||
|
throw new AssertError("ifthenelse with operand "+i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
super.setOperandType(inputTypes); |
||||||
|
Type operandType = |
||||||
|
UnknownType.commonType(operandTypes[1],operandTypes[2]); |
||||||
|
type = operandTypes[1] = operandTypes[2] = operandType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type newType) { |
||||||
|
Type operandType = |
||||||
|
UnknownType.commonType(operandTypes[1], newType); |
||||||
|
if (type != operandType) { |
||||||
|
type = operandTypes[1] = operandTypes[2] = operandType; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + " ? "+operands[1]+" : "+ operands[2]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class InstanceOfOperator extends SimpleOperator { |
||||||
|
Type classType; |
||||||
|
|
||||||
|
public InstanceOfOperator(int addr, int length, Type type) { |
||||||
|
super(addr, length, Type.tBoolean, 0, 1); |
||||||
|
this.operandTypes[0] = UnknownType.tSubClass(type); |
||||||
|
this.classType = type; |
||||||
|
} |
||||||
|
public int getOperandCount() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 550; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + " instanceof "+ca.getTypeString(classType); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public abstract class Instruction { |
||||||
|
int addr,length; |
||||||
|
|
||||||
|
Instruction(int a, int l) { |
||||||
|
addr = a; |
||||||
|
length = l; |
||||||
|
} |
||||||
|
|
||||||
|
public int getAddr() { |
||||||
|
return addr; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAddr(int addr) { |
||||||
|
this.addr = addr; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLength() { |
||||||
|
return length; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLength(int length) { |
||||||
|
this.length = length; |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
int[] result = { addr + length }; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException; |
||||||
|
} |
@ -0,0 +1,110 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class InvokeOperator extends Operator { |
||||||
|
boolean staticFlag; |
||||||
|
boolean specialFlag; |
||||||
|
FieldDefinition field; |
||||||
|
|
||||||
|
public InvokeOperator(int addr, int length, |
||||||
|
boolean staticFlag, boolean specialFlag, |
||||||
|
FieldDefinition field) { |
||||||
|
super(addr,length, field.getType().getReturnType(), 0); |
||||||
|
this.staticFlag = staticFlag; |
||||||
|
this.specialFlag = specialFlag; |
||||||
|
this.field = field; |
||||||
|
} |
||||||
|
|
||||||
|
public FieldDefinition getField() { |
||||||
|
return field; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getClassType() { |
||||||
|
return field.getClassDeclaration().getType(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return (staticFlag?0:1) + field.getType().getArgumentTypes().length; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
if (!staticFlag && i == 0) |
||||||
|
return 950; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
if (!staticFlag) { |
||||||
|
if (i == 0) |
||||||
|
return field.getClassDeclaration().getType(); |
||||||
|
i--; |
||||||
|
} |
||||||
|
return field.getType().getArgumentTypes()[i]; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isConstructor() { |
||||||
|
return field.isConstructor(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
String object; |
||||||
|
int arg = 0; |
||||||
|
if (staticFlag) { |
||||||
|
if (field.getClassDefinition() == ca.getClassDefinition()) |
||||||
|
object = ""; |
||||||
|
else |
||||||
|
object = ca. |
||||||
|
getTypeString(field.getClassDeclaration().getType()); |
||||||
|
} else { |
||||||
|
if (operands[arg].equals("this")) { |
||||||
|
if (specialFlag && |
||||||
|
(field.getClassDeclaration() == |
||||||
|
ca.getClassDefinition().getSuperClass() || |
||||||
|
(field.getClassDeclaration().getName() == |
||||||
|
Constants.idJavaLangObject && |
||||||
|
ca.getClassDefinition().getSuperClass() == null))) |
||||||
|
object = "super"; |
||||||
|
else if (specialFlag) |
||||||
|
object = "(("+ca.getTypeString |
||||||
|
(field.getClassDeclaration().getType())+ |
||||||
|
") this)"; |
||||||
|
else |
||||||
|
object = ""; |
||||||
|
} else { |
||||||
|
if (specialFlag) |
||||||
|
object = "(("+ca.getTypeString |
||||||
|
(field.getClassDeclaration().getType())+ |
||||||
|
") "+operands[arg]+")"; |
||||||
|
else |
||||||
|
object = operands[arg]; |
||||||
|
} |
||||||
|
arg++; |
||||||
|
} |
||||||
|
String method; |
||||||
|
if (isConstructor()) { |
||||||
|
if (object.length() == 0) |
||||||
|
method = "this"; |
||||||
|
else |
||||||
|
method = object; |
||||||
|
} else { |
||||||
|
if (object.length() == 0) |
||||||
|
method = field.getName().toString(); |
||||||
|
else |
||||||
|
method = object+"."+field.getName().toString(); |
||||||
|
} |
||||||
|
StringBuffer params = new StringBuffer(); |
||||||
|
for (int i=0; i < field.getType().getArgumentTypes().length; i++) { |
||||||
|
if (i>0) |
||||||
|
params.append(", "); |
||||||
|
params.append(operands[arg++]); |
||||||
|
} |
||||||
|
return method+"("+params+")"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class JsrOperator extends Instruction { |
||||||
|
int destination; |
||||||
|
|
||||||
|
public JsrOperator(int addr, int length, int dest) { |
||||||
|
super(addr,length); |
||||||
|
this.destination = dest; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("jsr addr_"+destination+";"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public abstract class JumpInstruction extends Operator { |
||||||
|
public JumpInstruction(int addr, int length) { |
||||||
|
super(addr, length, Type.tVoid, 0); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class LoadOperator extends ConstOperator { |
||||||
|
LocalVariable slot; |
||||||
|
|
||||||
|
public LoadOperator(int addr, int length, Type type, LocalVariable slot) { |
||||||
|
super(addr,length, |
||||||
|
UnknownType.commonType(type,slot.getType(addr)), ""); |
||||||
|
this.slot = slot; |
||||||
|
} |
||||||
|
|
||||||
|
public LocalVariable getSlot() { |
||||||
|
return slot; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return slot.getName(getAddr()).toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
return (o instanceof LoadOperator && |
||||||
|
((LoadOperator) o).slot == slot); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class MonitorEnterOperator extends SimpleOperator { |
||||||
|
public MonitorEnterOperator(int a, int l) { |
||||||
|
super(a,l, Type.tVoid, 0, 1); |
||||||
|
operandTypes[0] = Type.tObject; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "monitorenter "+operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class MonitorExitOperator extends SimpleOperator { |
||||||
|
public MonitorExitOperator(int a, int l) { |
||||||
|
super(a,l,Type.tVoid, 0, 1); |
||||||
|
operandTypes[0] = Type.tObject; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return UnknownType.tObject; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "monitorexit "+operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class NewArrayOperator extends SimpleOperator { |
||||||
|
Type baseType; |
||||||
|
|
||||||
|
public NewArrayOperator(int addr, int length, |
||||||
|
Type baseType, int dimensions) { |
||||||
|
super(addr, length, baseType, 0, dimensions); |
||||||
|
this.baseType = baseType; |
||||||
|
for (int i=0; i< dimensions; i++) { |
||||||
|
this.type = Type.tArray(this.type); |
||||||
|
operandTypes[i] = UnknownType.tUIndex; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public NewArrayOperator(int addr, int length, Type baseType) { |
||||||
|
this(addr, length, baseType, 1); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 900; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
StringBuffer result |
||||||
|
= new StringBuffer("new ").append(ca.getTypeString(baseType)); |
||||||
|
for (int i=0; i< getOperandCount(); i++) { |
||||||
|
result.append("[").append(operands[i]).append("]"); |
||||||
|
} |
||||||
|
return result.toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class NewConstructorOperator extends NoArgOperator { |
||||||
|
Expression constructor; |
||||||
|
|
||||||
|
public NewConstructorOperator(int addr, int length, Type type, |
||||||
|
Expression expr) { |
||||||
|
super(addr,length, type); |
||||||
|
this.constructor = expr; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "new "+constructor.toString(ca, 0); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class NewOperator extends NoArgOperator { |
||||||
|
|
||||||
|
public NewOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, type); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "new "+getType().toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public abstract class NoArgOperator extends Operator { |
||||||
|
|
||||||
|
public NoArgOperator(int addr, int length, Type type) { |
||||||
|
super(addr, length, type, 0); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] types) { |
||||||
|
throw new AssertError("This operator has no operands"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,13 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class NopOperator extends Instruction { |
||||||
|
public NopOperator(int a, int l) { |
||||||
|
super(a,l); |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
tpw.println("nop;"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,111 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public abstract class Operator extends Instruction { |
||||||
|
public final static int ADD_OP = 1; |
||||||
|
public final static int NEG_OP = 2; |
||||||
|
public final static int SHIFT_OP = 6; |
||||||
|
public final static int ASSIGN_OP = 12; |
||||||
|
public final static int OPASSIGN_OP= 12; |
||||||
|
public final static int INC_OP = 24; |
||||||
|
public final static int COMPARE_OP = 26; /* must be even! */ |
||||||
|
public final static int LOG_AND_OP = 32; /* must be even! */ |
||||||
|
public final static int LOG_OR_OP = 33; |
||||||
|
public final static int LOG_NOT_OP = 34; |
||||||
|
static String opString[] = { |
||||||
|
"", "+","-","*","/","%", "<<", ">>", ">>>", "&", "|", "^", |
||||||
|
"=","+=","-=","*=","/=","%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=", |
||||||
|
"++", "--", |
||||||
|
"==","!=","<",">=",">", "<=", "&&", "||", |
||||||
|
"~", "!" |
||||||
|
}; |
||||||
|
|
||||||
|
protected Type type; |
||||||
|
protected int operator; |
||||||
|
|
||||||
|
String casts; |
||||||
|
|
||||||
|
Operator (int addr, int length, Type type, int op) { |
||||||
|
super(addr,length); |
||||||
|
this.type = type; |
||||||
|
this.operator = op; |
||||||
|
if (type == null) |
||||||
|
throw new AssertError("type == null"); |
||||||
|
casts = type.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperator() { |
||||||
|
return operator; |
||||||
|
} |
||||||
|
public void setOperator(int op) { |
||||||
|
operator = op; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type type) { |
||||||
|
if (!UnknownType.isOfType(type, this.type)) { |
||||||
|
casts = type.toString()+"/*invalid*/ <- " + casts; |
||||||
|
} else if (type != this.type) { |
||||||
|
casts = type.toString()+" <- " + casts; |
||||||
|
} |
||||||
|
this.type = type; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public final Type getType() { |
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
public String getOperatorString() { |
||||||
|
return opString[operator]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get priority of the operator. |
||||||
|
* Currently this priorities are known: |
||||||
|
* <ul><li> 1000 constant |
||||||
|
* </li><li> 950 new, .(field access), [] |
||||||
|
* </li><li> 900 new[] |
||||||
|
* </li><li> 800 ++,-- (post) |
||||||
|
* </li><li> 700 ++,--(pre), +,-(unary), ~, !, cast |
||||||
|
* </li><li> 650 *,/, % |
||||||
|
* </li><li> 610 +,- |
||||||
|
* </li><li> 600 <<, >>, >>> |
||||||
|
* </li><li> 550 >, <, >=, <=, instanceof |
||||||
|
* </li><li> 500 ==, != |
||||||
|
* </li><li> 450 & |
||||||
|
* </li><li> 420 ^ |
||||||
|
* </li><li> 410 | |
||||||
|
* </li><li> 350 && |
||||||
|
* </li><li> 310 || |
||||||
|
* </li><li> 200 ?: |
||||||
|
* </li><li> 100 =, +=, -=, etc. |
||||||
|
* </li></ul> |
||||||
|
*/ |
||||||
|
public abstract int getPriority(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get minimum priority of the nth operand. |
||||||
|
* @see getPriority |
||||||
|
*/ |
||||||
|
public abstract int getOperandPriority(int i); |
||||||
|
public abstract Type getOperandType(int i); |
||||||
|
public abstract int getOperandCount(); |
||||||
|
public abstract void setOperandType(Type[] inputTypes); |
||||||
|
public abstract String toString(CodeAnalyzer ca, String[] operands); |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (type == null) |
||||||
|
throw new AssertError("type == null"); |
||||||
|
String[] operands = new String[getOperandCount()]; |
||||||
|
for (int i=0; i< operands.length; i++) { |
||||||
|
operands[i] = "stack_"+(operands.length-i-1); |
||||||
|
} |
||||||
|
writer.println(toString(ca, operands)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class PopOperator extends SimpleOperator { |
||||||
|
int count; |
||||||
|
|
||||||
|
public PopOperator(int a, int l, int count) { |
||||||
|
super(a,l, Type.tVoid, 0, 1); |
||||||
|
operandTypes[0] = UnknownType.tUnknown; |
||||||
|
this.count = count; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class PostFixOperator extends SimpleOperator { |
||||||
|
public PostFixOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, type, op, 1); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 800; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type type) { |
||||||
|
super.setType(type); |
||||||
|
Type newOpType = UnknownType.commonType(type, operandTypes[0]); |
||||||
|
if (newOpType != operandTypes[0]) { |
||||||
|
operandTypes[0] = newOpType; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return operands[0] + getOperatorString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.*; |
||||||
|
|
||||||
|
public class PutFieldOperator extends StoreInstruction { |
||||||
|
boolean staticFlag; |
||||||
|
FieldDefinition field; |
||||||
|
|
||||||
|
public PutFieldOperator(int addr, int length, boolean staticFlag, |
||||||
|
FieldDefinition field) { |
||||||
|
super(addr, length, field.getType()); |
||||||
|
this.staticFlag = staticFlag; |
||||||
|
this.field = field; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean matches(Operator loadop) { |
||||||
|
return loadop instanceof GetFieldOperator && |
||||||
|
((GetFieldOperator)loadop).field == field; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandCount() { |
||||||
|
return staticFlag?0:1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandPriority(int i) { |
||||||
|
if (staticFlag) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("Field is static"); |
||||||
|
} |
||||||
|
return 900; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getLValueOperandType(int i) { |
||||||
|
if (staticFlag) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new AssertError("Field is static"); |
||||||
|
} |
||||||
|
return field.getClassDefinition().getType(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setLValueOperandType(Type[] t) { |
||||||
|
if (staticFlag) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new AssertError("Field is static"); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
public String getLValueString(CodeAnalyzer ca, String[] operands) { |
||||||
|
String object; |
||||||
|
if (staticFlag) { |
||||||
|
if (field.getClassDefinition() == ca.getClassDefinition()) |
||||||
|
return field.getName().toString(); |
||||||
|
object = |
||||||
|
ca.getTypeString(field.getClassDeclaration().getType())+"."; |
||||||
|
} else { |
||||||
|
if (operands[0].equals("this")) |
||||||
|
return field.getName().toString(); |
||||||
|
object = operands[0]; |
||||||
|
} |
||||||
|
return object + "." + field.getName(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class RetOperator extends Instruction { |
||||||
|
int slot; |
||||||
|
|
||||||
|
public RetOperator(int addr, int length, int slot) { |
||||||
|
super(addr,length); |
||||||
|
this.slot = slot; |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
return new int[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("ret;"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class ReturnOperator extends SimpleOperator { |
||||||
|
public ReturnOperator(int addr, int length, Type type) { |
||||||
|
super(addr,length, Type.tVoid, 0, (type == Type.tVoid)?0:1); |
||||||
|
if (type != Type.tVoid) |
||||||
|
operandTypes[0] = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
return new int[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
StringBuffer result = new StringBuffer("return"); |
||||||
|
if (getOperandCount() != 0) |
||||||
|
result.append(" ").append(operands[0]); |
||||||
|
return result.toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* ShiftOpcodes are special, because their second operand is an UIndex |
||||||
|
*/ |
||||||
|
public class ShiftOperator extends BinaryOperator { |
||||||
|
protected Type shiftType; |
||||||
|
|
||||||
|
public ShiftOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, type, op); |
||||||
|
shiftType = UnknownType.tUIndex; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return (i==0)?operandType:shiftType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] inputTypes) { |
||||||
|
operandType = UnknownType.commonType(operandType, inputTypes[0]); |
||||||
|
shiftType = UnknownType.commonType(shiftType, inputTypes[1]); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public abstract class SimpleOperator extends Operator { |
||||||
|
protected Type[] operandTypes; |
||||||
|
|
||||||
|
public SimpleOperator(int addr, int length, Type type, int operator, |
||||||
|
int operandCount) { |
||||||
|
super(addr, length, type, operator); |
||||||
|
operandTypes = new Type[operandCount]; |
||||||
|
for (int i=0; i< operandCount; i++) { |
||||||
|
operandTypes[i] = type; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return operandTypes.length; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return operandTypes[i]; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] t) { |
||||||
|
for (int i=0; i< operandTypes.length; i++) { |
||||||
|
if (UnknownType.commonType(operandTypes[i], t[i]) == Type.tError) |
||||||
|
System.err.println("Error: "+operandTypes[i]+","+t[i]); |
||||||
|
operandTypes[i] = UnknownType.commonType(operandTypes[i], t[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public abstract class StoreInstruction extends Operator { |
||||||
|
|
||||||
|
public String lvCasts; |
||||||
|
Type lvalueType; |
||||||
|
|
||||||
|
public StoreInstruction(int addr, int length, Type type) { |
||||||
|
this (addr,length, type, ASSIGN_OP); |
||||||
|
} |
||||||
|
|
||||||
|
public StoreInstruction(int addr, int length, Type type, int operator) { |
||||||
|
super(addr,length, Type.tVoid, operator); |
||||||
|
lvalueType = type; |
||||||
|
lvCasts = lvalueType.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getLValueType() { |
||||||
|
return lvalueType; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract boolean matches(Operator loadop); |
||||||
|
public abstract int getLValueOperandCount(); |
||||||
|
public abstract int getLValueOperandPriority(int i); |
||||||
|
public abstract Type getLValueOperandType(int i); |
||||||
|
public abstract void setLValueOperandType(Type [] t); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the type of the lvalue (and rvalue). |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setLValueType(Type type) { |
||||||
|
if (!UnknownType.isOfType(type, this.lvalueType)) { |
||||||
|
lvCasts = type.toString()+"/*invalid*/ <- " + lvCasts; |
||||||
|
} else if (type != this.lvalueType) { |
||||||
|
lvCasts = type.toString()+" <- " + lvCasts; |
||||||
|
} |
||||||
|
this.lvalueType = type; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract String getLValueString(CodeAnalyzer ca, String[] operands); |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 100; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
if (i == getLValueOperandCount()) |
||||||
|
return 100; |
||||||
|
else |
||||||
|
return getLValueOperandPriority(i); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
if (i == getLValueOperandCount()) |
||||||
|
return getLValueType(); |
||||||
|
else |
||||||
|
return getLValueOperandType(i); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type[] t) { |
||||||
|
if (getLValueOperandCount() > 0) |
||||||
|
setLValueOperandType(t); |
||||||
|
setLValueType |
||||||
|
(UnknownType.commonType(lvalueType, t[getLValueOperandCount()])); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1 + getLValueOperandCount(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) |
||||||
|
{ |
||||||
|
return "{"+lvCasts+" "+getLValueString(ca, operands) + "} "+ |
||||||
|
getOperatorString() +" "+ |
||||||
|
operands[getLValueOperandCount()]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class StoreOperator extends StoreInstruction { |
||||||
|
LocalVariable slot; |
||||||
|
|
||||||
|
public StoreOperator(int addr, int length, Type type, |
||||||
|
LocalVariable slot, int operator) { |
||||||
|
super(addr,length, |
||||||
|
UnknownType.commonType(type,slot.getType(addr+length)), |
||||||
|
operator); |
||||||
|
this.slot = slot; |
||||||
|
} |
||||||
|
|
||||||
|
public LocalVariable getSlot() { |
||||||
|
return slot; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean matches(Operator loadop) { |
||||||
|
return loadop instanceof LoadOperator && |
||||||
|
((LoadOperator)loadop).getSlot() == slot; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandCount() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLValueOperandPriority(int i) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("StoreOperator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getLValueOperandType(int i) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("StoreOperator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public void setLValueOperandType(Type []t) { |
||||||
|
/* shouldn't be called */ |
||||||
|
throw new RuntimeException("StoreOperator has no operands"); |
||||||
|
} |
||||||
|
|
||||||
|
public String getLValueString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return slot.getName(getAddr()+getLength()).toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class SwapOperator extends Instruction { |
||||||
|
public SwapOperator(int a, int l) { |
||||||
|
super(a,l); |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("swap;"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class SwitchOperator extends JumpInstruction { |
||||||
|
int[] cases; |
||||||
|
int[] destinations; |
||||||
|
Type operandType; |
||||||
|
|
||||||
|
public SwitchOperator(int addr, int length, int[] cases, int[] dests) { |
||||||
|
super(addr,length); |
||||||
|
this.cases = cases; |
||||||
|
this.destinations = dests; |
||||||
|
this.operandType = UnknownType.tUInt; |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getCases() { |
||||||
|
return cases; |
||||||
|
} |
||||||
|
|
||||||
|
public int[] getSuccessors() { |
||||||
|
return destinations; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandCount() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getOperandType(int i) { |
||||||
|
return operandType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOperandType(Type types[]) { |
||||||
|
operandType = UnknownType.commonType(operandType, types[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean setType(Type t) { |
||||||
|
super.setType(type); |
||||||
|
if (type != operandType) { |
||||||
|
operandType = type; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "switch ("+operands[0]+") "; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("switch(stack_0) {"); |
||||||
|
writer.tab(); |
||||||
|
for (int i=0; i< cases.length; i++) { |
||||||
|
writer.println("case "+cases[i]+ |
||||||
|
": goto addr_"+destinations[i]+";"); |
||||||
|
} |
||||||
|
writer.println("default: goto addr_"+destinations[cases.length]); |
||||||
|
writer.untab(); |
||||||
|
writer.println("}"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class ThrowOperator extends ReturnOperator { |
||||||
|
|
||||||
|
public ThrowOperator(int addr, int length) { |
||||||
|
super(addr,length, UnknownType.tUObject); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return "throw " + operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class UnaryOperator extends SimpleOperator { |
||||||
|
public UnaryOperator(int addr, int length, Type type, int op) { |
||||||
|
super(addr,length, type, op, 1); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 700; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return getPriority(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the return type of this operator. |
||||||
|
* @return true if the operand types changed |
||||||
|
*/ |
||||||
|
public boolean setType(Type type) { |
||||||
|
super.setType(type); |
||||||
|
Type newOpType = UnknownType.commonType(type, operandTypes[0]); |
||||||
|
if (newOpType != operandTypes[0]) { |
||||||
|
operandTypes[0] = newOpType; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(CodeAnalyzer ca, String[] operands) { |
||||||
|
return getOperatorString() + operands[0]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class UnknownSubType extends UnknownType { |
||||||
|
Type elemType; |
||||||
|
|
||||||
|
public UnknownSubType(Type type) { |
||||||
|
super(103, "<"); |
||||||
|
elemType = type; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getElementType() |
||||||
|
{ |
||||||
|
return elemType; |
||||||
|
} |
||||||
|
|
||||||
|
public String typeString(String string, boolean flag1, boolean flag2) |
||||||
|
{ |
||||||
|
return "<superclass of "+ |
||||||
|
String.valueOf(elemType.typeString(string, flag1, flag2))+">"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,204 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import java.util.Hashtable; |
||||||
|
|
||||||
|
public class UnknownType extends Type { |
||||||
|
static Hashtable subclasses = new Hashtable(); |
||||||
|
|
||||||
|
public static Type tUnknown = new UnknownType(100, "x"); |
||||||
|
public static Type tUInt = new UnknownType(101, "i"); |
||||||
|
public static Type tUIndex = new UnknownType(104, "["); |
||||||
|
public static Type tUObject = new UnknownType(102, "*"); |
||||||
|
public static Type tSubClass(Type type) { |
||||||
|
Type subtype = (Type) subclasses.get(type); |
||||||
|
if (subtype == null) { |
||||||
|
subtype = new UnknownSubType(type); |
||||||
|
subclasses.put(type, subtype); |
||||||
|
} |
||||||
|
return subtype; |
||||||
|
} |
||||||
|
|
||||||
|
protected UnknownType(int i, String str) { |
||||||
|
super (i, str); |
||||||
|
} |
||||||
|
|
||||||
|
public int stackSize() |
||||||
|
{ |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public String typeString(String var, boolean flag1, boolean flag2) |
||||||
|
{ |
||||||
|
String typeStr; |
||||||
|
switch (typeCode) { |
||||||
|
case 100: typeStr="<unknown>"; break; |
||||||
|
case 101: typeStr="<int>"; break; /*XXX*/ |
||||||
|
case 102: typeStr="<Object>"; break; |
||||||
|
case 104: typeStr="<arrindex>"; break; /*XXX*/ |
||||||
|
default: |
||||||
|
throw new RuntimeException("Wrong typeCode "+typeCode); |
||||||
|
} |
||||||
|
if (var.length() > 0) |
||||||
|
return typeStr+" "+var; |
||||||
|
return typeStr; |
||||||
|
} |
||||||
|
|
||||||
|
public static Type commonType(Type t1, Type t2) { |
||||||
|
if (t1 == t2 || t2 == tUnknown) |
||||||
|
return t1; |
||||||
|
|
||||||
|
switch (t1.getTypeCode()) { |
||||||
|
case 0: /* boolean*/ |
||||||
|
case 1: /* byte */ |
||||||
|
case 2: /* char */ |
||||||
|
case 3: /* short */ |
||||||
|
case 4: /* int */ |
||||||
|
if (t2.getTypeCode() <= 4) { |
||||||
|
if (t2.getTypeCode() > t1.getTypeCode()) |
||||||
|
return t2; |
||||||
|
else |
||||||
|
return t1; |
||||||
|
} |
||||||
|
if (t2 == tUInt || t2 == tUIndex) |
||||||
|
return t1; |
||||||
|
break; |
||||||
|
|
||||||
|
case 5: /* long */ |
||||||
|
case 6: /* float */ |
||||||
|
case 7: /* double */ |
||||||
|
case 8: /* null? */ |
||||||
|
case 11: /* void */ |
||||||
|
case 12: /* method */ |
||||||
|
case 13: /* error */ |
||||||
|
break; |
||||||
|
|
||||||
|
case 9: /* array */ |
||||||
|
if (t2 == tUObject) |
||||||
|
return t1; |
||||||
|
if (t2.getTypeCode() == 9) /* array, array case */ |
||||||
|
return tArray(commonType(t1.getElementType(), |
||||||
|
t2.getElementType())); |
||||||
|
break; |
||||||
|
|
||||||
|
case 10: /* class */ |
||||||
|
if (t2 == tUObject) |
||||||
|
return t1; |
||||||
|
if (t2.getTypeCode() == 103) { |
||||||
|
/* find suitable subclass of t2 */ |
||||||
|
return t2; /*XXX*/ |
||||||
|
} |
||||||
|
if (t2.getTypeCode() == 10) { |
||||||
|
return t1; /*XXX*/ |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
case 100: /* unknown */ |
||||||
|
return t2; |
||||||
|
|
||||||
|
case 101: /* unknown int */ |
||||||
|
if ((t2.getTypeCode() >= 0 && t2.getTypeCode() <= 4) || |
||||||
|
t2 == tUIndex) |
||||||
|
return t2; |
||||||
|
break; |
||||||
|
case 104: /* unknown index */ |
||||||
|
if (t2.getTypeCode() >= 1 && t2.getTypeCode() <= 4) |
||||||
|
return t2; |
||||||
|
if (t2 == tUInt) |
||||||
|
return t1; |
||||||
|
break; |
||||||
|
|
||||||
|
case 102: /* unknown object */ |
||||||
|
if (t2.getTypeCode() == 9 || t2.getTypeCode() == 10 || |
||||||
|
t2.getTypeCode() == 103) |
||||||
|
return t2; |
||||||
|
break; |
||||||
|
|
||||||
|
case 103: /* unknown super class */ |
||||||
|
if (t2.getTypeCode() == 10 || t2.getTypeCode() == 103) |
||||||
|
return t2; /*XXX*/ |
||||||
|
if (t2 == tUObject) |
||||||
|
return t1; |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
throw new AssertError("Wrong typeCode "+t1.getTypeCode()); |
||||||
|
} |
||||||
|
return tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if t1 is a t2. |
||||||
|
* @return true if t1 is a more specific type than t2, e.g. |
||||||
|
* if t2 is a superclass of t1 |
||||||
|
*/ |
||||||
|
public static boolean isOfType(Type t1, Type t2) { |
||||||
|
if ((t1 == t2 || t2 == tUnknown) && t1 != tError) |
||||||
|
return true; |
||||||
|
|
||||||
|
switch (t1.getTypeCode()) { |
||||||
|
case 0: /* boolean*/ |
||||||
|
case 1: /* byte */ |
||||||
|
case 2: /* char */ |
||||||
|
case 3: /* short */ |
||||||
|
case 4: /* int */ |
||||||
|
|
||||||
|
/* JavaC thinks, that this is okay. */ |
||||||
|
if (t2.getTypeCode() >= 0 && t2.getTypeCode() <=4) |
||||||
|
return true; |
||||||
|
|
||||||
|
/* fallthrough */ |
||||||
|
case 104: /* unknown index */ |
||||||
|
if (t2 == tUInt || t2 == tUIndex) |
||||||
|
return true; |
||||||
|
break; |
||||||
|
|
||||||
|
case 5: /* long */ |
||||||
|
case 6: /* float */ |
||||||
|
case 7: /* double */ |
||||||
|
case 8: /* null? */ |
||||||
|
case 11: /* void */ |
||||||
|
case 12: /* method */ |
||||||
|
case 13: /* error */ |
||||||
|
case 100: /* unknown */ |
||||||
|
case 101: /* unknown int */ |
||||||
|
case 102: /* unknown object */ |
||||||
|
break; |
||||||
|
|
||||||
|
case 9: /* array */ |
||||||
|
if (t2 == tUObject) |
||||||
|
return true; |
||||||
|
if (t2.getTypeCode() == 9) /* array,array case */ |
||||||
|
return isOfType(t1.getElementType(), t2.getElementType()); |
||||||
|
break; |
||||||
|
|
||||||
|
case 10: /* class */ |
||||||
|
if (t2 == tUObject) |
||||||
|
return true; |
||||||
|
if (t2.getTypeCode() == 103) |
||||||
|
/* Always true because t2 may be an Object XXX I think not*/ |
||||||
|
return true; |
||||||
|
if (t2.getTypeCode() == 10) |
||||||
|
/* true if t2 is a superclass of t1 */ |
||||||
|
return true; /*XXX*/ |
||||||
|
break; |
||||||
|
|
||||||
|
case 103: /* unknown super class */ |
||||||
|
if (t2.getTypeCode() == 103) |
||||||
|
/* Always true because t2 may be an Object XXX I think not*/ |
||||||
|
return true; |
||||||
|
|
||||||
|
if (t2.getTypeCode() == 10) { |
||||||
|
/* true if t2 is a real super class
|
||||||
|
(or interface) of t1.getElementType() */ |
||||||
|
return true; /*XXX*/ |
||||||
|
} |
||||||
|
if (t2 == tUObject) |
||||||
|
return true; |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
throw new AssertError("Wrong typeCode "+t1.getTypeCode()); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue