* src/net/sf/jode/jvm/SyntheticAnalyzer.java (checkGetClass):

Handle jdk1.4 class$ methods.

Fixed some javadocs.

Added changes (except obfuscator changes) from jode-1.1 tree up to
2001-07-08


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1378 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 21 years ago
parent 2872b22195
commit 338feb1f61
  1. 36
      jode/src/net/sf/jode/bytecode/BasicBlockReader.java
  2. 25
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  3. 1
      jode/src/net/sf/jode/expr/CompareToIntOperator.java
  4. 10
      jode/src/net/sf/jode/expr/StoreInstruction.java
  5. 13
      jode/src/net/sf/jode/flow/CatchBlock.java
  6. 6
      jode/src/net/sf/jode/flow/CompleteSynchronized.java
  7. 2
      jode/src/net/sf/jode/flow/CreateAssignExpression.java
  8. 1
      jode/src/net/sf/jode/flow/CreateExpression.java
  9. 2
      jode/src/net/sf/jode/flow/CreateIfThenElseOperator.java
  10. 1
      jode/src/net/sf/jode/flow/TransformConstructors.java
  11. 7
      jode/src/net/sf/jode/jvm/CodeVerifier.java
  12. 4
      jode/src/net/sf/jode/jvm/RuntimeEnvironment.java
  13. 16
      jode/src/net/sf/jode/jvm/SyntheticAnalyzer.java

@ -856,6 +856,13 @@ class BasicBlockReader implements Opcodes {
handlers[i].type = (index == 0) ? null handlers[i].type = (index == 0) ? null
: cp.getClassName(index); : cp.getClassName(index);
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
GlobalOptions.err.println("Handler "+handlers[i].start
+"-"+handlers[i].end
+" @"+handlers[i].catcher
+ ": "+handlers[i].type);
if (infos[handlers[i].catcher].instr.getOpcode() == opc_athrow) { if (infos[handlers[i].catcher].instr.getOpcode() == opc_athrow) {
/* There is an obfuscator, which inserts bogus /* There is an obfuscator, which inserts bogus
* exception entries jumping directly to a throw * exception entries jumping directly to a throw
@ -864,6 +871,35 @@ class BasicBlockReader implements Opcodes {
handlersLength--; handlersLength--;
i--; i--;
} }
if (handlers[i].start <= handlers[i].catcher
&& handlers[i].end > handlers[i].catcher)
{
/* Javac 1.4 is a bit paranoid with finally and
* synchronize blocks and even breaks the JLS.
* We fix it here. Hopefully this won't produce
* any other problems.
*/
if (handlers[i].start == handlers[i].catcher) {
handlersLength--;
i--;
} else {
handlers[i].end = handlers[i].catcher;
}
}
if (infos[handlers[i].end].instr.getOpcode() >= opc_ireturn
&& infos[handlers[i].end].instr.getOpcode() <= opc_return) {
/* JDK 1.4 sometimes doesn't put return instruction into try
* block, which breaks the decompiler later. The return
* instruction can't throw exceptions so it doesn't really
* matter.
*
* FIXME: This may break other things if the return
* instruction is reachable from outside the try block.
*/
handlers[i].end++;
}
} }
if (handlersLength < handlers.length) { if (handlersLength < handlers.length) {
HandlerEntry[] newHandlers = new HandlerEntry[handlersLength]; HandlerEntry[] newHandlers = new HandlerEntry[handlersLength];

@ -240,6 +240,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
private ClassPath classpath; private ClassPath classpath;
private int modifiers = -1; private int modifiers = -1;
private boolean deprecatedFlag;
private String name; private String name;
private String className; private String className;
private boolean methodScoped; private boolean methodScoped;
@ -560,6 +561,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} else if (howMuch >= ClassInfo.OUTERCLASS } else if (howMuch >= ClassInfo.OUTERCLASS
&& name.equals("InnerClasses")) { && name.equals("InnerClasses")) {
readInnerClassesAttribute(length, cp, input); readInnerClassesAttribute(length, cp, input);
} else if (name.equals("Deprecated")) {
deprecatedFlag = true;
if (length != 0)
throw new ClassFormatException
("Deprecated attribute has wrong length");
} else } else
super.readAttribute(name, length, cp, input, howMuch); super.readAttribute(name, length, cp, input, howMuch);
} }
@ -848,6 +854,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
gcp.putUTF8(ci.className); gcp.putUTF8(ci.className);
} }
} }
if (deprecatedFlag)
gcp.putUTF8("Deprecated");
prepareAttributes(gcp); prepareAttributes(gcp);
} }
@ -911,6 +919,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
output.writeShort(ci.modifiers); output.writeShort(ci.modifiers);
} }
} }
if (deprecatedFlag) {
output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0);
}
} }
@ -1191,6 +1203,15 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return Modifier.isInterface(getModifiers()); return Modifier.isInterface(getModifiers());
} }
/**
* Checks whether this class was declared as deprecated. In bytecode
* this is represented by a special attribute.
* @return true if this class info represents a deprecated class.
*/
public boolean isDeprecated() {
return deprecatedFlag;
}
/** /**
* Searches for a field with given name and type signature. * Searches for a field with given name and type signature.
* @param name the name of the field. * @param name the name of the field.
@ -1324,6 +1345,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
modified = true; modified = true;
} }
public void setDeprecated(boolean flag) {
deprecatedFlag = flag;
}
public void setMethods(MethodInfo[] mi) { public void setMethods(MethodInfo[] mi) {
methods = mi; methods = mi;
status = ALL; status = ALL;

@ -54,6 +54,7 @@ public class CompareToIntOperator extends Operator {
throws java.io.IOException throws java.io.IOException
{ {
subExpressions[0].dumpExpression(writer, 550); subExpressions[0].dumpExpression(writer, 550);
writer.breakOp();
writer.print(" <=>"); writer.print(" <=>");
if (allowsNaN) if (allowsNaN)
writer.print(greaterOnNaN ? "g" : "l"); writer.print(greaterOnNaN ? "g" : "l");

@ -25,7 +25,7 @@ import net.sf.jode.decompiler.TabbedPrintWriter;
public class StoreInstruction extends Operator public class StoreInstruction extends Operator
implements CombineableOperator { implements CombineableOperator {
boolean isOpAssign = false; boolean opAssign = false;
public StoreInstruction(LValueExpression lvalue) { public StoreInstruction(LValueExpression lvalue) {
super(Type.tVoid, ASSIGN_OP); super(Type.tVoid, ASSIGN_OP);
@ -41,7 +41,11 @@ public class StoreInstruction extends Operator
setOperatorIndex(operatorIndex); setOperatorIndex(operatorIndex);
if (subExpressions[1] instanceof NopOperator) if (subExpressions[1] instanceof NopOperator)
subExpressions[1].type = Type.tUnknown; subExpressions[1].type = Type.tUnknown;
isOpAssign = true; opAssign = true;
}
public boolean isOpAssign() {
return opAssign;
} }
/** /**
@ -72,7 +76,7 @@ public class StoreInstruction extends Operator
Type newType; Type newType;
if (!isOpAssign) { if (!opAssign) {
/* An opassign (+=, -=, etc.) doesn't merge rvalue type. */ /* An opassign (+=, -=, etc.) doesn't merge rvalue type. */
Type lvalueType = subExpressions[0].getType(); Type lvalueType = subExpressions[0].getType();
Type rvalueType = subExpressions[1].getType(); Type rvalueType = subExpressions[1].getType();

@ -24,6 +24,7 @@ import net.sf.jode.decompiler.Declarable;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.LocalLoadOperator; import net.sf.jode.expr.LocalLoadOperator;
import net.sf.jode.expr.LocalStoreOperator; import net.sf.jode.expr.LocalStoreOperator;
import net.sf.jode.expr.NopOperator;
import net.sf.jode.expr.StoreInstruction; import net.sf.jode.expr.StoreInstruction;
import net.sf.jode.util.SimpleSet; import net.sf.jode.util.SimpleSet;
@ -220,18 +221,20 @@ public class CatchBlock extends StructuredBlock {
} else if (firstInstr instanceof InstructionBlock) { } else if (firstInstr instanceof InstructionBlock) {
Expression instr = Expression instr =
((InstructionBlock) firstInstr).getInstruction(); ((InstructionBlock) firstInstr).getInstruction();
if (instr instanceof StoreInstruction if (instr instanceof StoreInstruction) {
&& (((StoreInstruction)instr).getLValue() StoreInstruction store = (StoreInstruction) instr;
instanceof LocalStoreOperator)) { if (store.getOperatorIndex() == store.OPASSIGN_OP
&& store.getSubExpressions()[1] instanceof NopOperator
&& store.getLValue() instanceof LocalStoreOperator) {
/* The exception is stored in a local variable */ /* The exception is stored in a local variable */
exceptionLocal = ((LocalStoreOperator) exceptionLocal = ((LocalStoreOperator) store.getLValue())
((StoreInstruction)instr).getLValue())
.getLocalInfo(); .getLocalInfo();
exceptionLocal.setType(exceptionType); exceptionLocal.setType(exceptionType);
firstInstr.removeBlock(); firstInstr.removeBlock();
return true; return true;
} }
} }
}
return false; return false;
} }
} }

@ -24,8 +24,7 @@ import net.sf.jode.expr.*;
public class CompleteSynchronized { public class CompleteSynchronized {
/** /**
* This combines the monitorenter into a synchronized statement * This combines the monitorenter into a synchronized statement.
* @param flow The FlowBlock that is transformed
*/ */
public static boolean enter(SynchronizedBlock synBlock, public static boolean enter(SynchronizedBlock synBlock,
StructuredBlock last) { StructuredBlock last) {
@ -63,8 +62,7 @@ public class CompleteSynchronized {
/** /**
* This combines the initial expression describing the object * This combines the initial expression describing the object
* into a synchronized statement * into a synchronized statement.
* @param flow The FlowBlock that is transformed
*/ */
public static boolean combineObject(SynchronizedBlock synBlock, public static boolean combineObject(SynchronizedBlock synBlock,
StructuredBlock last) { StructuredBlock last) {

@ -56,7 +56,7 @@ public class CreateAssignExpression {
SequentialBlock opBlock = (SequentialBlock) last.outer; SequentialBlock opBlock = (SequentialBlock) last.outer;
StoreInstruction store = (StoreInstruction) ic.getInstruction(); StoreInstruction store = (StoreInstruction) ic.getInstruction();
if (!store.isFreeOperator()) if (!store.isFreeOperator() || store.isOpAssign())
return false; return false;
Expression lvalue = store.getSubExpressions()[0]; Expression lvalue = store.getSubExpressions()[0];
int lvalueCount = lvalue.getFreeOperandCount(); int lvalueCount = lvalue.getFreeOperandCount();

@ -35,7 +35,6 @@ public class CreateExpression {
/** /**
* This does the transformation. * This does the transformation.
* @param FlowBlock the flow block to transform.
* @return true if flow block was simplified. * @return true if flow block was simplified.
*/ */
public static boolean transform(InstructionContainer ic, public static boolean transform(InstructionContainer ic,

@ -141,7 +141,6 @@ public class CreateIfThenElseOperator {
* *
* Also note that the produced code is suboptimal: The push-0 could * Also note that the produced code is suboptimal: The push-0 could
* sometimes be better replaced with a correct jump. * sometimes be better replaced with a correct jump.
* @param flow The FlowBlock that is transformed
*/ */
public static boolean createFunny(ConditionalBlock cb, public static boolean createFunny(ConditionalBlock cb,
StructuredBlock last) { StructuredBlock last) {
@ -188,7 +187,6 @@ public class CreateIfThenElseOperator {
* -&gt;push cond ? e1 : e2 * -&gt;push cond ? e1 : e2
* </pre> * </pre>
* The <code>-&gt;</code> points to the lastModified block. * The <code>-&gt;</code> points to the lastModified block.
* @param flow The FlowBlock that is transformed
*/ */
public static boolean create(InstructionContainer ic, public static boolean create(InstructionContainer ic,
StructuredBlock last) { StructuredBlock last) {

@ -106,6 +106,7 @@ public class TransformConstructors {
this.clazzAnalyzer = clazzAnalyzer; this.clazzAnalyzer = clazzAnalyzer;
this.isStatic = isStatic; this.isStatic = isStatic;
this.cons = cons; this.cons = cons;
if (!isStatic)
this.outerValues = clazzAnalyzer.getOuterValues(); this.outerValues = clazzAnalyzer.getOuterValues();
lookForConstructorCall(); lookForConstructorCall();
} }

@ -1120,8 +1120,13 @@ public class CodeVerifier implements Opcodes {
if (!info.pop().isOfType(tType(type))) if (!info.pop().isOfType(tType(type)))
throw new VerifyException(instr.getDescription()); throw new VerifyException(instr.getDescription());
Type classType = tType(ref.getClazz()); Type classType = tType(ref.getClazz());
if (!info.pop().isOfType(classType)) Type classOnStack = info.pop();
if (!classOnStack.isOfType(classType)) {
/* Sometimes synthetic code writes to uninitialized classes. */
classType = tType("N" + ref.getClazz().substring(1));
if (!classOnStack.isOfType(classType))
throw new VerifyException(instr.getDescription()); throw new VerifyException(instr.getDescription());
}
break; break;
} }
case opc_invokevirtual: case opc_invokevirtual:

@ -109,13 +109,13 @@ public interface RuntimeEnvironment {
/** /**
* Enter a monitor. * Enter a monitor.
* @param object the object whose monitor should be taken. * @param obj the object whose monitor should be taken.
*/ */
public void enterMonitor(Object obj) public void enterMonitor(Object obj)
throws InterpreterException; throws InterpreterException;
/** /**
* Exit a monitor. * Exit a monitor.
* @param object the object whose monitor should be freed. * @param obj the object whose monitor should be freed.
*/ */
public void exitMonitor(Object obj) public void exitMonitor(Object obj)
throws InterpreterException; throws InterpreterException;

@ -111,7 +111,8 @@ public class SyntheticAnalyzer implements Opcodes {
Block startBlock = bb.getStartBlock(); Block startBlock = bb.getStartBlock();
Handler[] excHandlers = bb.getExceptionHandlers(); Handler[] excHandlers = bb.getExceptionHandlers();
if (startBlock == null if (startBlock == null
|| startBlock.getInstructions().length != 3 || startBlock.getInstructions().length < 2
|| startBlock.getInstructions().length > 3
|| excHandlers.length != 1 || excHandlers.length != 1
|| excHandlers[0].getStart() != startBlock || excHandlers[0].getStart() != startBlock
|| excHandlers[0].getEnd() != startBlock || excHandlers[0].getEnd() != startBlock
@ -119,7 +120,7 @@ public class SyntheticAnalyzer implements Opcodes {
.equals(excHandlers[0].getType())) .equals(excHandlers[0].getType()))
return false; return false;
for (int i=0; i< 3; i++) { for (int i=0; i< 2; i++) {
Instruction instr = startBlock.getInstructions()[i]; Instruction instr = startBlock.getInstructions()[i];
if (instr.getOpcode() != getClassOpcodes[i]) if (instr.getOpcode() != getClassOpcodes[i])
return false; return false;
@ -132,6 +133,17 @@ public class SyntheticAnalyzer implements Opcodes {
if (i == 0 && instr.getLocalSlot() != 0) if (i == 0 && instr.getLocalSlot() != 0)
return false; return false;
} }
if (startBlock.getInstructions().length == 2) {
/* JDK 1.4: The return is outside of startBlock */
Block nextBlock = startBlock.getSuccs()[0];
Instruction[] instrs = nextBlock.getInstructions();
if (instrs[0].getOpcode() != opc_areturn)
return false;
} else {
/* JDK 1.3 */
if (startBlock.getInstructions()[2].getOpcode() != opc_areturn)
return false;
}
Block catchBlock = excHandlers[0].getCatcher(); Block catchBlock = excHandlers[0].getCatcher();
if (catchBlock.getInstructions().length != 7) if (catchBlock.getInstructions().length != 7)

Loading…
Cancel
Save