git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@9 379699f6-c40d-0410-875b-85095c16579estable
parent
e776825477
commit
6951265a2d
@ -0,0 +1,37 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Vector; |
||||||
|
import sun.tools.java.Identifier; |
||||||
|
|
||||||
|
public class CombineCatchLocal implements Transformation{ |
||||||
|
|
||||||
|
static Identifier idException = Identifier.lookup("exception"); |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
CatchInstructionHeader catchIH; |
||||||
|
LocalInfo local; |
||||||
|
try { |
||||||
|
catchIH = (CatchInstructionHeader)ih; |
||||||
|
ih = ih.nextInstruction; |
||||||
|
if (ih.getPredecessors().size() != 1) |
||||||
|
return null; |
||||||
|
Instruction instr = ih.getInstruction(); |
||||||
|
if (instr instanceof PopOperator) { |
||||||
|
local = new LocalInfo(99); |
||||||
|
local.setName(idException); |
||||||
|
} else if (instr instanceof LocalStoreOperator) { |
||||||
|
local = ((LocalStoreOperator) instr).getLocalInfo(); |
||||||
|
local.setName(idException); |
||||||
|
} else |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (!catchIH.combineWithLocal(local)) |
||||||
|
return null; |
||||||
|
if(Decompiler.isVerbose) |
||||||
|
System.err.print("c"); |
||||||
|
return catchIH; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CreateConstantArray implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
Expression[] consts; |
||||||
|
int count; |
||||||
|
Type type; |
||||||
|
try { |
||||||
|
if (ih.getInstruction() instanceof DupOperator) |
||||||
|
/* this is not the end of the array assign */ |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
ArrayStoreOperator store = |
||||||
|
(ArrayStoreOperator) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression lastconst = (Expression) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression lastindexexpr = (Expression) ih.getInstruction(); |
||||||
|
ConstOperator lastindexop = |
||||||
|
(ConstOperator) lastindexexpr.getOperator(); |
||||||
|
if (!MyType.isOfType(lastindexop.getType(), MyType.tInt)) |
||||||
|
return null; |
||||||
|
int lastindex = Integer.parseInt(lastindexop.getValue()); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
DupOperator dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getDepth() != 0 || |
||||||
|
dup.getCount() != store.getLValueType().stackSize()) |
||||||
|
return null; |
||||||
|
consts = new Expression[lastindex+1]; |
||||||
|
consts[lastindex] = lastconst; |
||||||
|
count = 1; |
||||||
|
while (lastindex-- > 0) { |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
ArrayStoreOperator store2 = |
||||||
|
(ArrayStoreOperator) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
lastconst = (Expression) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression indexexpr = (Expression) ih.getInstruction(); |
||||||
|
ConstOperator indexop = |
||||||
|
(ConstOperator) indexexpr.getOperator(); |
||||||
|
if (!MyType.isOfType(indexop.getType(), MyType.tUInt)) |
||||||
|
return null; |
||||||
|
int index = Integer.parseInt(indexop.getValue()); |
||||||
|
if (index > lastindex) |
||||||
|
return null; |
||||||
|
while (index < lastindex) { |
||||||
|
consts[lastindex] = new Expression |
||||||
|
(new ConstOperator(MyType.tUnknown, ""), |
||||||
|
new Expression[0]); |
||||||
|
lastindex--; |
||||||
|
} |
||||||
|
consts[lastindex] = lastconst; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getDepth() != 0 || |
||||||
|
dup.getCount() != store.getLValueType().stackSize()) |
||||||
|
return null; |
||||||
|
count++; |
||||||
|
} |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression newArrayExpr = (Expression) ih.getInstruction(); |
||||||
|
NewArrayOperator newArrayOp = |
||||||
|
(NewArrayOperator) newArrayExpr.getOperator(); |
||||||
|
type = newArrayOp.getType(); |
||||||
|
if (newArrayOp.getOperandCount() != 1) |
||||||
|
return null; |
||||||
|
Expression countexpr = |
||||||
|
(Expression) newArrayExpr.getSubExpressions()[0]; |
||||||
|
ConstOperator countop = |
||||||
|
(ConstOperator) countexpr.getOperator(); |
||||||
|
if (!MyType.isOfType(countop.getType(), MyType.tUInt)) |
||||||
|
return null; |
||||||
|
if (Integer.parseInt(countop.getValue()) != consts.length) |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Operator op = new ConstantArrayOperator(type, consts.length); |
||||||
|
return ih.combine(4*count+1, new Expression(op, consts)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateIfStatements implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ifgoto) { |
||||||
|
if (ifgoto.getFlowType() != ifgoto.IFGOTO || |
||||||
|
ifgoto.nextInstruction == null || |
||||||
|
ifgoto.getSuccessors()[1].getAddress() <= |
||||||
|
ifgoto.getSuccessors()[0].getAddress()) |
||||||
|
return null; |
||||||
|
|
||||||
|
InstructionHeader next = ifgoto.getSuccessors()[1]; |
||||||
|
InstructionHeader endBlock = next; |
||||||
|
if (ifgoto.outer != next.outer) { |
||||||
|
if (ifgoto.outer.endBlock != next) |
||||||
|
return null; |
||||||
|
next = null; |
||||||
|
} |
||||||
|
|
||||||
|
InstructionHeader thenStart = ifgoto.nextInstruction; |
||||||
|
InstructionHeader thenEnd; |
||||||
|
for (thenEnd = thenStart; |
||||||
|
thenEnd != null && thenEnd.nextInstruction != next; |
||||||
|
thenEnd = thenEnd.nextInstruction) { |
||||||
|
} |
||||||
|
if (thenEnd == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
InstructionHeader elseStart = null; |
||||||
|
InstructionHeader elseEnd = null; |
||||||
|
if (next != null && |
||||||
|
thenEnd.getFlowType() == thenEnd.GOTO && |
||||||
|
thenEnd.successors[0].getAddress() > next.getAddress()) { |
||||||
|
elseStart = next; |
||||||
|
endBlock = next = thenEnd.successors[0]; |
||||||
|
if (ifgoto.outer != next.outer) { |
||||||
|
if (ifgoto.outer.endBlock != next) |
||||||
|
return null; |
||||||
|
next = null; |
||||||
|
} |
||||||
|
for (elseEnd = elseStart; |
||||||
|
elseEnd != null && elseEnd.nextInstruction != next; |
||||||
|
elseEnd = elseEnd.nextInstruction) { |
||||||
|
} |
||||||
|
/* XXX return error or create if-then? |
||||||
|
*/ |
||||||
|
if (elseEnd == null) |
||||||
|
return null; |
||||||
|
} |
||||||
|
if(Decompiler.isVerbose) |
||||||
|
System.err.print("i"); |
||||||
|
return new IfInstructionHeader |
||||||
|
(ifgoto, elseStart != null, thenEnd, elseEnd, endBlock); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,42 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateNewConstructor implements Transformation{ |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
InvokeOperator constrCall; |
||||||
|
Expression exprs[]; |
||||||
|
try { |
||||||
|
constrCall = (InvokeOperator) ih.getInstruction(); |
||||||
|
if (!constrCall.isConstructor()) |
||||||
|
return null; |
||||||
|
int params = constrCall.getOperandCount(); |
||||||
|
exprs = new Expression[params]; |
||||||
|
for (int i = params-1; i>0; i--) { |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
exprs[i] = (Expression) ih.getInstruction(); |
||||||
|
if (exprs[i].isVoid()) |
||||||
|
return null; /* XXX */ |
||||||
|
} |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
DupOperator dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getCount() != 1 && dup.getDepth() != 0) |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
exprs[0] = (Expression) ih.getInstruction(); |
||||||
|
if (exprs[0].isVoid()) |
||||||
|
return null; |
||||||
|
NewOperator op = (NewOperator) exprs[0].getOperator(); |
||||||
|
if (constrCall.getClassType() != op.getType()) |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
ConstructorOperator conOp = |
||||||
|
new ConstructorOperator(constrCall.getClassType(), |
||||||
|
constrCall.getField()); |
||||||
|
|
||||||
|
return ih.combine(exprs.length+2, new Expression(conOp, exprs)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateTryCatchStatements implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader tryIH) { |
||||||
|
if (tryIH.getFlowType() != tryIH.TRY || |
||||||
|
tryIH.successors.length == 1 || |
||||||
|
tryIH.nextInstruction == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
/* find handler with largest end address |
||||||
|
* and count the catches. |
||||||
|
*/ |
||||||
|
InstructionHeader endIH = tryIH; |
||||||
|
int index = 0, count = 0; |
||||||
|
for (int i=1; i < tryIH.successors.length; i+=2) { |
||||||
|
if (tryIH.successors[i] == endIH) |
||||||
|
count++; |
||||||
|
else if (tryIH.successors[i].addr > endIH.addr) { |
||||||
|
endIH = tryIH.successors[i]; |
||||||
|
count = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
if (count == 0 || endIH.outer != tryIH.outer) |
||||||
|
return null; |
||||||
|
|
||||||
|
/* now find all corresponding catches */ |
||||||
|
InstructionHeader[] catchIH = new InstructionHeader[count+1]; |
||||||
|
InstructionHeader[] remaining = |
||||||
|
new InstructionHeader[tryIH.successors.length-2*count]; |
||||||
|
int index1 = 0, index2=0; |
||||||
|
remaining[index2++] = tryIH.successors[0]; |
||||||
|
catchIH[index1++] = tryIH; |
||||||
|
for (int i=1; i < tryIH.successors.length; i+=2) { |
||||||
|
if (tryIH.successors[i] == endIH) { |
||||||
|
/* assume that the catches are already sorted */ |
||||||
|
if (tryIH.successors[i+1].outer != tryIH.outer || |
||||||
|
tryIH.successors[i+1].flowType != InstructionHeader.CATCH) |
||||||
|
return null; |
||||||
|
catchIH[index1] = tryIH.successors[i+1]; |
||||||
|
index1++; |
||||||
|
} else { |
||||||
|
remaining[index2++] = tryIH.successors[i]; |
||||||
|
remaining[index2++] = tryIH.successors[i+1]; |
||||||
|
} |
||||||
|
} |
||||||
|
InstructionHeader endBlock = tryIH.outer.endBlock; |
||||||
|
if (endIH != catchIH[1]) { |
||||||
|
if ((endIH.flowType != endIH.RETURN || |
||||||
|
endIH.getInstruction().getType() != MyType.tVoid) && |
||||||
|
endIH.flowType != endIH.GOTO) |
||||||
|
return null; |
||||||
|
|
||||||
|
if (endIH.successors[0].outer == tryIH.outer) |
||||||
|
endBlock = endIH.successors[0]; |
||||||
|
else if (endIH.successors[0] != endBlock) |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (Decompiler.isVerbose) |
||||||
|
System.err.print("t"); |
||||||
|
return new TryCatchInstructionHeader |
||||||
|
(catchIH, endIH, remaining, endBlock); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,26 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateWhileStatements implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader gotoIH) { |
||||||
|
|
||||||
|
if (gotoIH.flowType != gotoIH.GOTO || gotoIH.nextInstruction == null || |
||||||
|
gotoIH.successors[0].addr < gotoIH.nextInstruction.addr) |
||||||
|
return null; |
||||||
|
|
||||||
|
InstructionHeader block = gotoIH.nextInstruction; |
||||||
|
if (block == null) |
||||||
|
block = gotoIH.outer.endBlock; |
||||||
|
|
||||||
|
InstructionHeader ifgoto = gotoIH.successors[0]; |
||||||
|
|
||||||
|
if (ifgoto.getFlowType() != ifgoto.IFGOTO || |
||||||
|
ifgoto.successors[1] != block || |
||||||
|
ifgoto.outer != block.outer) |
||||||
|
return null; |
||||||
|
|
||||||
|
if(Decompiler.isVerbose) |
||||||
|
System.err.print("w"); |
||||||
|
return new WhileInstructionHeader(gotoIH, ifgoto, block); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class RemoveNop implements Transformation { |
||||||
|
public InstructionHeader transform (InstructionHeader ih) { |
||||||
|
Instruction pred; |
||||||
|
try { |
||||||
|
NopOperator op = (NopOperator) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
pred = ih.getInstruction(); |
||||||
|
if (pred == null) |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return ih.combine(2, pred); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public interface Transformation { |
||||||
|
public InstructionHeader transform(InstructionHeader ih); |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class CatchInstructionHeader extends InstructionHeader { |
||||||
|
|
||||||
|
Type type; |
||||||
|
String typeString; |
||||||
|
LocalInfo local; |
||||||
|
|
||||||
|
CatchInstructionHeader(Type type, String typeString, |
||||||
|
InstructionHeader firstInstr, |
||||||
|
InstructionHeader outer) { |
||||||
|
super(CATCH, firstInstr.addr, firstInstr.addr, |
||||||
|
new InstructionHeader[1], outer); |
||||||
|
|
||||||
|
movePredecessors(firstInstr); |
||||||
|
successors[0] = firstInstr; |
||||||
|
firstInstr.predecessors = new Vector(); |
||||||
|
firstInstr.predecessors.addElement(this); |
||||||
|
|
||||||
|
prevInstruction = firstInstr.prevInstruction; |
||||||
|
if (prevInstruction != null) |
||||||
|
prevInstruction.nextInstruction = this; |
||||||
|
|
||||||
|
nextInstruction = firstInstr; |
||||||
|
firstInstr.prevInstruction = this; |
||||||
|
|
||||||
|
this.type = type; |
||||||
|
this.typeString = typeString; |
||||||
|
} |
||||||
|
|
||||||
|
public LocalInfo getLocal() { |
||||||
|
return local; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Combines this catch instruction header with the next instruction |
||||||
|
* header which should containt only a LocalStoreOperator or a pop |
||||||
|
* according to the parameter. (This is where the exception gets |
||||||
|
* stored. |
||||||
|
* @param local The local where the exception is stored. |
||||||
|
* @return true if the operation succeeded. |
||||||
|
*/ |
||||||
|
public boolean combineWithLocal(LocalInfo local) { |
||||||
|
InstructionHeader next = nextInstruction; |
||||||
|
if (this.local != null || successors[0] != next) |
||||||
|
return false; |
||||||
|
|
||||||
|
this.local = local; |
||||||
|
successors = next.successors; |
||||||
|
nextInstruction = next.nextInstruction; |
||||||
|
if (nextInstruction != null) |
||||||
|
nextInstruction.prevInstruction = this; |
||||||
|
|
||||||
|
for (int i=0; i< successors.length; i++) { |
||||||
|
successors[i].predecessors.removeElement(next); |
||||||
|
successors[i].predecessors.addElement(this); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) |
||||||
|
dumpDebugging(writer); |
||||||
|
|
||||||
|
writer.println("} catch ("+typeString+" "+ |
||||||
|
(local != null ? local.getName() |
||||||
|
: (Object) "stack_0") + ") {"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,51 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class CombineIfGotoExpressions implements Transformation{ |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih2) { |
||||||
|
InstructionHeader ih1; |
||||||
|
Expression[] e; |
||||||
|
int operator; |
||||||
|
try { |
||||||
|
if (ih2.getFlowType() != ih2.IFGOTO) |
||||||
|
return null; |
||||||
|
InstructionHeader[] dests2 = ih2.getSuccessors(); |
||||||
|
|
||||||
|
/* if ih2.getSimpleUniquePredecessor.getOperator().isVoid() XXX */ |
||||||
|
|
||||||
|
Vector predec = ih2.getPredecessors(); |
||||||
|
if (predec.size() != 1) |
||||||
|
return null; |
||||||
|
|
||||||
|
ih1 = (InstructionHeader) predec.elementAt(0); |
||||||
|
if (ih1.getFlowType() != ih1.IFGOTO) |
||||||
|
return null; |
||||||
|
InstructionHeader[] dests1 = ih1.getSuccessors(); |
||||||
|
if (dests1[0] != ih2) |
||||||
|
return null; |
||||||
|
|
||||||
|
if (dests1[1] == dests2[0]) { |
||||||
|
e = new Expression[2]; |
||||||
|
operator = Operator.LOG_AND_OP; |
||||||
|
e[1] = (Expression)ih2.getInstruction(); |
||||||
|
e[0] = ((Expression)ih1.getInstruction()).negate(); |
||||||
|
} else if (dests1[1] == dests2[1]) { |
||||||
|
e = new Expression[2]; |
||||||
|
operator = Operator.LOG_OR_OP; |
||||||
|
e[1] = (Expression)ih2.getInstruction(); |
||||||
|
e[0] = (Expression)ih1.getInstruction(); |
||||||
|
} else |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
Expression cond = |
||||||
|
new Expression(new BinaryOperator(MyType.tBoolean, operator), e); |
||||||
|
|
||||||
|
return ih1.combineConditional(cond); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateAssignExpression implements Transformation{ |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
InstructionHeader next = createAssignOp(ih); |
||||||
|
if (next != null) |
||||||
|
return next; |
||||||
|
return createAssignExpression(ih); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader createAssignOp(InstructionHeader ih) { |
||||||
|
Expression rightHandSide; |
||||||
|
StoreInstruction store; |
||||||
|
BinaryOperator binop; |
||||||
|
try { |
||||||
|
store = (StoreInstruction) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
binop = (BinaryOperator) ih.getInstruction(); |
||||||
|
if (binop.getOperator() < binop.ADD_OP || |
||||||
|
binop.getOperator() >= binop.ASSIGN_OP) |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
rightHandSide = (Expression) ih.getInstruction(); |
||||||
|
if (rightHandSide.isVoid()) |
||||||
|
return null; /* XXX */ |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Operator load = (Operator) ih.getInstruction(); |
||||||
|
if (!store.matches(load)) |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
DupOperator dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getDepth() != 0 && |
||||||
|
dup.getCount() != store.getLValueOperandCount()) |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
ih = ih.combine(3, rightHandSide); |
||||||
|
InstructionHeader storeIH = ih.getNextInstruction(); |
||||||
|
store.setOperator(store.OPASSIGN_OP+binop.getOperator()); |
||||||
|
store.setLValueType(MyType.intersection(binop.getType(), |
||||||
|
store.getLValueType())); |
||||||
|
storeIH.combine(2, store); |
||||||
|
return ih; |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader createAssignExpression(InstructionHeader ih) { |
||||||
|
StoreInstruction store; |
||||||
|
try { |
||||||
|
store = (StoreInstruction) ih.getInstruction(); |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
|
||||||
|
DupOperator dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getDepth() != store.getLValueOperandCount() && |
||||||
|
dup.getCount() != store.getLValueType().stackSize()) |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return ih.combine(2, new AssignOperator(Operator.ASSIGN_OP, store)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class CreateExpression implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
Operator op; |
||||||
|
Expression exprs[]; |
||||||
|
int params; |
||||||
|
try { |
||||||
|
op = (Operator) ih.getInstruction(); |
||||||
|
params = op.getOperandCount(); |
||||||
|
exprs = new Expression[params]; |
||||||
|
for (int i = params-1; i>=0; i--) { |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
exprs[i] = (Expression) ih.getInstruction(); |
||||||
|
if (exprs[i].isVoid()) { |
||||||
|
if (i == params-1) |
||||||
|
return null; |
||||||
|
Expression e = exprs[i+1].tryToCombine(exprs[i]); |
||||||
|
if (e == null) |
||||||
|
return null; |
||||||
|
i++; |
||||||
|
exprs[i] = e; |
||||||
|
ih = ih.combine(2, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if(Decompiler.isVerbose && params > 0) |
||||||
|
System.err.print("x"); |
||||||
|
return ih.combine(params+1, new Expression(op, exprs)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class CreateIfThenElseOperator implements Transformation{ |
||||||
|
|
||||||
|
public InstructionHeader createFunny(InstructionHeader ih) { |
||||||
|
Expression cond = null; |
||||||
|
try { |
||||||
|
InstructionHeader ifHeader= ih; |
||||||
|
if (ifHeader.getFlowType() != ifHeader.IFGOTO) |
||||||
|
return null; |
||||||
|
CompareUnaryOperator compare = |
||||||
|
(CompareUnaryOperator) ifHeader.getInstruction(); |
||||||
|
if ((compare.getOperator() & ~1) != compare.EQUALS_OP) |
||||||
|
return null; |
||||||
|
Enumeration enum = ih.getPredecessors().elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
try { |
||||||
|
ih = (InstructionHeader) enum.nextElement(); |
||||||
|
Expression zeroExpr = (Expression) ih.getInstruction(); |
||||||
|
ConstOperator zero = |
||||||
|
(ConstOperator) zeroExpr.getOperator(); |
||||||
|
if (!zero.getValue().equals("0")) |
||||||
|
continue; |
||||||
|
|
||||||
|
ih = ih.getUniquePredecessor(); |
||||||
|
if (ih.getFlowType() != ih.IFGOTO) |
||||||
|
continue; |
||||||
|
|
||||||
|
if (compare.getOperator() == compare.EQUALS_OP && |
||||||
|
ih.getSuccessors()[1] != ifHeader.getSuccessors()[0] |
||||||
|
|| compare.getOperator() == compare.NOTEQUALS_OP && |
||||||
|
ih.getSuccessors()[1] != ifHeader.getSuccessors()[1]) |
||||||
|
continue; |
||||||
|
|
||||||
|
cond = (Expression) ih.getInstruction(); |
||||||
|
break; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (cond == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
InstructionHeader next = ih.nextInstruction; |
||||||
|
ih.successors[1].predecessors.removeElement(ih); |
||||||
|
next.instr = ih.instr; |
||||||
|
next.movePredecessors(ih); |
||||||
|
return next; |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader create(InstructionHeader ih) { |
||||||
|
InstructionHeader ifHeader; |
||||||
|
Expression e[] = new Expression[3]; |
||||||
|
InstructionHeader[] succs; |
||||||
|
try { |
||||||
|
Vector predec = ih.getPredecessors(); |
||||||
|
|
||||||
|
if (predec.size() != 1) |
||||||
|
return null; |
||||||
|
ifHeader = (InstructionHeader) predec.elementAt(0); |
||||||
|
if (ifHeader.getFlowType() != ifHeader.IFGOTO) |
||||||
|
return null; |
||||||
|
succs = ifHeader.getSuccessors(); |
||||||
|
if (succs[1] != ih || |
||||||
|
succs[0].getNextInstruction() != succs[1] || |
||||||
|
succs[0].getSuccessors().length != 1 || |
||||||
|
succs[1].getSuccessors().length != 1 || |
||||||
|
succs[0].getSuccessors()[0] != succs[1].getSuccessors()[0]) |
||||||
|
return null; |
||||||
|
|
||||||
|
e[0] = ((Expression) ifHeader.getInstruction()).negate(); |
||||||
|
e[1] = (Expression) succs[0].getInstruction(); |
||||||
|
if (e[1].isVoid()) |
||||||
|
return null; |
||||||
|
e[2] = (Expression) succs[1].getInstruction(); |
||||||
|
if (e[2].isVoid()) |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
IfThenElseOperator iteo = new IfThenElseOperator |
||||||
|
(MyType.intersection(e[1].getType(),e[2].getType())); |
||||||
|
|
||||||
|
ih.instr = new Expression(iteo, e); |
||||||
|
ih.movePredecessors(ifHeader); |
||||||
|
ih.nextInstruction.predecessors.removeElement(ifHeader.successors[0]); |
||||||
|
return ih; |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
InstructionHeader next = createFunny(ih); |
||||||
|
if (next != null) |
||||||
|
return next; |
||||||
|
return create(ih); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
package jode; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
|
public class CreatePostIncExpression implements Transformation { |
||||||
|
|
||||||
|
public InstructionHeader transform(InstructionHeader ih) |
||||||
|
{ |
||||||
|
InstructionHeader next = createLocalPostInc(ih); |
||||||
|
if (next != null) |
||||||
|
return next; |
||||||
|
return createPostInc(ih); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader createLocalPostInc(InstructionHeader ih) { |
||||||
|
IIncOperator iinc; |
||||||
|
int op; |
||||||
|
Type type; |
||||||
|
try { |
||||||
|
Expression iincExpr = (Expression) ih.getInstruction(); |
||||||
|
iinc = (IIncOperator) iincExpr.getOperator(); |
||||||
|
if (iinc.getOperator() == iinc.ADD_OP + iinc.OPASSIGN_OP) |
||||||
|
op = Operator.INC_OP; |
||||||
|
else if (iinc.getOperator() == iinc.NEG_OP + iinc.OPASSIGN_OP) |
||||||
|
op = Operator.DEC_OP; |
||||||
|
else |
||||||
|
return null; |
||||||
|
if (!iinc.getValue().equals("1") && |
||||||
|
!iinc.getValue().equals("-1")) |
||||||
|
return null; |
||||||
|
if (iinc.getValue().equals("-1")) |
||||||
|
op ^= 1; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression loadExpr = (Expression) ih.getInstruction(); |
||||||
|
LocalLoadOperator load = |
||||||
|
(LocalLoadOperator)loadExpr.getOperator(); |
||||||
|
if (!iinc.matches(load)) |
||||||
|
return null; |
||||||
|
|
||||||
|
type = MyType.intersection(load.getType(), MyType.tUInt); |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Operator postop = new LocalPostFixOperator(type, op, iinc); |
||||||
|
return ih.combine(2, postop); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader createPostInc(InstructionHeader ih) { |
||||||
|
StoreInstruction store; |
||||||
|
int op; |
||||||
|
Type type; |
||||||
|
try { |
||||||
|
store = (StoreInstruction) ih.getInstruction(); |
||||||
|
if (store.getLValueOperandCount() == 0) |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
BinaryOperator binOp = (BinaryOperator) ih.getInstruction(); |
||||||
|
if (binOp.getOperator() == store.ADD_OP) |
||||||
|
op = Operator.INC_OP; |
||||||
|
else if (store.getOperator() == store.NEG_OP) |
||||||
|
op = Operator.DEC_OP; |
||||||
|
else |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Expression expr = (Expression) ih.getInstruction(); |
||||||
|
ConstOperator constOp = (ConstOperator) expr.getOperator(); |
||||||
|
if (!constOp.getValue().equals("1") && |
||||||
|
!constOp.getValue().equals("-1")) |
||||||
|
return null; |
||||||
|
if (constOp.getValue().equals("-1")) |
||||||
|
op ^= 1; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
DupOperator dup = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup.getCount() != store.getLValueType().stackSize() || |
||||||
|
dup.getDepth() != store.getLValueOperandCount()) |
||||||
|
return null; |
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
Operator load = (Operator) ih.getInstruction(); |
||||||
|
|
||||||
|
if (!store.matches(load)) |
||||||
|
return null; |
||||||
|
|
||||||
|
ih = ih.getSimpleUniquePredecessor(); |
||||||
|
DupOperator dup2 = (DupOperator) ih.getInstruction(); |
||||||
|
if (dup2.getCount() != store.getLValueOperandCount() || |
||||||
|
dup2.getDepth() != 0) |
||||||
|
return null; |
||||||
|
|
||||||
|
type = MyType.intersection(load.getType(), store.getLValueType()); |
||||||
|
} catch (NullPointerException ex) { |
||||||
|
return null; |
||||||
|
} catch (ClassCastException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Operator postop = new PostFixOperator(type, op, store); |
||||||
|
return ih.combine(6, postop); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,173 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Enumeration; |
||||||
|
|
||||||
|
/** |
||||||
|
* This instruction header represents an if instruction. The |
||||||
|
* linkage of the instructions is as follow: |
||||||
|
* <pre> |
||||||
|
* A: .... |
||||||
|
* <p> |
||||||
|
* prev = A, next = H, pred = normal, succ = {C,E} |
||||||
|
* B: if ( instr ) { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* C: then-instr 1 |
||||||
|
* <p> |
||||||
|
* prev = C, next = H!, pred = normal succ = normal |
||||||
|
* D: instructions of then part |
||||||
|
* <p> |
||||||
|
* } else { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* E: else-instr 1 |
||||||
|
* <p> |
||||||
|
* prev = E, next = null, pred = normal, succ = normal |
||||||
|
* F: instructions of then part |
||||||
|
* <p> |
||||||
|
* } |
||||||
|
* prev = B, ..., pred = normal, succ = normal |
||||||
|
* H: ... |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
public class IfInstructionHeader extends InstructionHeader { |
||||||
|
|
||||||
|
boolean hasElsePart; |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a new if statement. There are several conditions that |
||||||
|
* must be met: |
||||||
|
* <ul> |
||||||
|
* <li><code> ifHeader.successors[0] == thenStart |
||||||
|
* </code></li> |
||||||
|
* <li><code> ifHeader.successors[1] == thenEnd.nextInstruction |
||||||
|
* </code></li> |
||||||
|
* <li><code> elseStart == null || (thenEnd.flowType = GOTO && |
||||||
|
* elseEnd.nextInstruction == thenEnd.successors[0]) |
||||||
|
* </code></li> |
||||||
|
* <li><code> elseStart == null || elseStart = thenEnd.nextInstruction |
||||||
|
* </code></li> |
||||||
|
* <li><code> thenStart.nextInstruction....nextInstruction = thenEnd |
||||||
|
* </code></li> |
||||||
|
* <li><code> elseStart.nextInstruction....nextInstruction = elseEnd |
||||||
|
* </code></li> |
||||||
|
* </ul> |
||||||
|
* @param ifHeader the instruction header whichs contains the |
||||||
|
* if goto statement. |
||||||
|
* @param thenStart the start of the then part. |
||||||
|
* @param thenEnd the end of the then part. |
||||||
|
* @param elseStart the start of the else part. |
||||||
|
* @param elseEnd the end of the then part. |
||||||
|
* @param next the next instruction after the if statement. |
||||||
|
*/ |
||||||
|
public IfInstructionHeader(InstructionHeader ifHeader, |
||||||
|
boolean hasElsePart, |
||||||
|
InstructionHeader thenEnd, |
||||||
|
InstructionHeader elseEnd, |
||||||
|
InstructionHeader endBlock) { |
||||||
|
|
||||||
|
super(IFSTATEMENT, ifHeader.addr, endBlock.addr, |
||||||
|
ifHeader.successors, ifHeader.outer); |
||||||
|
|
||||||
|
this.instr = ((Expression)ifHeader.getInstruction()).negate(); |
||||||
|
|
||||||
|
this.movePredecessors(ifHeader); |
||||||
|
this.outer = ifHeader.outer; |
||||||
|
this.endBlock = endBlock; |
||||||
|
successors[0].predecessors.removeElement(ifHeader); |
||||||
|
successors[1].predecessors.removeElement(ifHeader); |
||||||
|
successors[0].predecessors.addElement(this); |
||||||
|
successors[1].predecessors.addElement(this); |
||||||
|
|
||||||
|
successors[0].prevInstruction = null; |
||||||
|
InstructionHeader next = thenEnd.nextInstruction; |
||||||
|
thenEnd.nextInstruction = null; |
||||||
|
|
||||||
|
for (InstructionHeader ih = successors[0]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
if (ih.outer == outer) |
||||||
|
ih.outer = this; |
||||||
|
|
||||||
|
this.hasElsePart = hasElsePart; |
||||||
|
if (hasElsePart) { |
||||||
|
thenEnd.flowType = thenEnd.NORMAL; |
||||||
|
|
||||||
|
successors[1].prevInstruction = null; |
||||||
|
next = elseEnd.nextInstruction; |
||||||
|
elseEnd.nextInstruction = null; |
||||||
|
|
||||||
|
for (InstructionHeader ih = successors[1]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
if (ih.outer == outer) |
||||||
|
ih.outer = this; |
||||||
|
} |
||||||
|
|
||||||
|
this.nextInstruction = next; |
||||||
|
if (next != null) |
||||||
|
next.prevInstruction = this; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) { |
||||||
|
dumpDebugging(writer); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
if (needsLabel()) { |
||||||
|
writer.untab(); |
||||||
|
writer.println(getLabel()+": "); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
boolean braces = successors[0].flowType != NORMAL || |
||||||
|
successors[0].nextInstruction != null; |
||||||
|
writer.println("if (" + instr.toString() + ")" + (braces ? " {": "")); |
||||||
|
|
||||||
|
writer.tab(); |
||||||
|
for (InstructionHeader ih = successors[0]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
writer.untab(); |
||||||
|
|
||||||
|
if (hasElsePart) { |
||||||
|
if (braces) |
||||||
|
writer.print("} "); |
||||||
|
|
||||||
|
braces = successors[1].flowType != NORMAL || |
||||||
|
successors[1].nextInstruction != null; |
||||||
|
|
||||||
|
if (!braces && successors[1].flowType == IFSTATEMENT) { |
||||||
|
writer.print("else "); |
||||||
|
successors[1].dumpSource(writer); |
||||||
|
} else { |
||||||
|
writer.println("else" + (braces ? " {": "")); |
||||||
|
writer.tab(); |
||||||
|
for (InstructionHeader ih = successors[1]; |
||||||
|
ih != null; ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
} |
||||||
|
if (braces) |
||||||
|
writer.println("} "); |
||||||
|
|
||||||
|
if (Decompiler.isDebugging) |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader doTransformations(Transformation[] trafo) { |
||||||
|
InstructionHeader next; |
||||||
|
for (InstructionHeader ih = successors[0]; ih != null; ih = next) { |
||||||
|
if ((next = ih.doTransformations(trafo)) == null) |
||||||
|
next = ih.getNextInstruction(); |
||||||
|
} |
||||||
|
if (hasElsePart) { |
||||||
|
for (InstructionHeader ih = successors[1]; ih != null; ih = next) { |
||||||
|
if ((next = ih.doTransformations(trafo)) == null) |
||||||
|
next = ih.getNextInstruction(); |
||||||
|
} |
||||||
|
} |
||||||
|
return super.doTransformations(trafo); |
||||||
|
} |
||||||
|
} |
@ -1,35 +1,91 @@ |
|||||||
package jode; |
package jode; |
||||||
import java.util.Vector; |
import java.util.Vector; |
||||||
|
import sun.tools.java.BinaryExceptionHandler; |
||||||
|
import sun.tools.java.Type; |
||||||
|
|
||||||
/** |
/** |
||||||
* This class is the end point of the InstructionHeader list. |
* This class is the end point of the InstructionHeader list. |
||||||
* @author Jochen Hoenicke |
* @author Jochen Hoenicke |
||||||
*/ |
*/ |
||||||
public class MethodInstructionHeader extends InstructionHeader { |
public class MethodInstructionHeader extends InstructionHeader { |
||||||
|
InstructionHeader first, last; |
||||||
|
|
||||||
/** |
/** |
||||||
* Create a new InstructionHeader. |
* Create a new InstructionHeader. |
||||||
* @param addr The address of this Instruction. |
* @param addr The address of this Instruction. |
||||||
* @param length The length of this Instruction. |
* @param length The length of this Instruction. |
||||||
* @param instr The underlying Instruction. |
* @param instr The underlying Instruction. |
||||||
*/ |
*/ |
||||||
public MethodInstructionHeader(InstructionHeader[] instr) { |
public MethodInstructionHeader(JodeEnvironment env, |
||||||
super(-1,1,null); |
InstructionHeader[] instr, |
||||||
nextInstruction = instr[0]; |
BinaryExceptionHandler[] handlers) { |
||||||
nextInstruction.predecessors.addElement(this); |
super(METHOD, 0, instr.length, new InstructionHeader[0], null); |
||||||
for (int addr = 0; addr < instr.length; ) { |
first = new InstructionHeader(EMPTY, 0, this); |
||||||
|
last = new InstructionHeader(EMPTY, instr.length, this); |
||||||
|
|
||||||
|
first.nextInstruction = instr[0]; |
||||||
|
instr[0].prevInstruction = first; |
||||||
|
|
||||||
|
for (int addr = 0; ; addr = instr[addr].nextAddr) { |
||||||
|
|
||||||
|
instr[addr].outer = this; |
||||||
instr[addr].resolveSuccessors(instr); |
instr[addr].resolveSuccessors(instr); |
||||||
if (instr[addr].succs.length == 0) |
|
||||||
predecessors.addElement(instr[addr]); |
if (instr[addr].flowType == RETURN) { |
||||||
addr = instr[addr].getNextAddr(); |
InstructionHeader[] lastArr = { last }; |
||||||
|
instr[addr].successors = lastArr; |
||||||
|
last.predecessors.addElement(instr[addr]); |
||||||
} |
} |
||||||
|
|
||||||
|
if (instr[addr].nextAddr == instr.length) { |
||||||
|
instr[addr].nextInstruction = last; |
||||||
|
last.prevInstruction = instr[addr]; |
||||||
|
break; |
||||||
} |
} |
||||||
|
|
||||||
/** |
} |
||||||
* Resolve the successors and predecessors and build a doubly |
for (int i=0; i<handlers.length; i++) { |
||||||
* linked list. |
InstructionHeader tryIH = instr[handlers[i].startPC]; |
||||||
* @param instHeaders an array of the InstructionHeaders, indexed |
if (tryIH.flowType != TRY) |
||||||
* by addresses. |
instr[handlers[i].startPC] = tryIH = |
||||||
*/ |
new TryInstructionHeader(tryIH, this); |
||||||
public void resolveSuccessors(InstructionHeader[] instHeaders) { |
|
||||||
|
Type type = handlers[i].exceptionClass.getType(); |
||||||
|
instr[handlers[i].handlerPC] = |
||||||
|
new CatchInstructionHeader |
||||||
|
(type, env.getTypeString(type), |
||||||
|
instr[handlers[i].handlerPC], this); |
||||||
|
|
||||||
|
InstructionHeader endIH = instr[handlers[i].endPC]; |
||||||
|
InstructionHeader catchIH = instr[handlers[i].handlerPC]; |
||||||
|
((TryInstructionHeader)tryIH).addHandler(endIH, catchIH); |
||||||
|
} |
||||||
|
endBlock = last; |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader getFirst() { |
||||||
|
return first.nextInstruction; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector getReturns() { |
||||||
|
return last.predecessors; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
for (InstructionHeader ih = first.nextInstruction; |
||||||
|
ih != last; ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader doTransformations(Transformation[] trafo) { |
||||||
|
InstructionHeader next; |
||||||
|
for (InstructionHeader ih = first.nextInstruction; |
||||||
|
ih != last; ih = next) { |
||||||
|
if ((next = ih.doTransformations(trafo)) == null) |
||||||
|
next = ih.getNextInstruction(); |
||||||
|
} |
||||||
|
return null; |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -0,0 +1,61 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is an InstructionHeader for simple switch statements. Simple |
||||||
|
* means that this is without blocks. |
||||||
|
* @author Jochen Hoenicke |
||||||
|
*/ |
||||||
|
public class SimpleSwitchInstructionHeader extends InstructionHeader { |
||||||
|
|
||||||
|
/** |
||||||
|
* The case labels of a switch instruction header. |
||||||
|
*/ |
||||||
|
int[] cases; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create an InstructionHeader for a conditional or unconditional |
||||||
|
* Switch. |
||||||
|
* @param addr The address of this instruction. |
||||||
|
* @param nextAddr The address of the next instruction header. |
||||||
|
* @param instr The underlying Instruction, the type of must be |
||||||
|
* an integer type. |
||||||
|
* @param cases The value of the cases. |
||||||
|
* @param dests The destination addresses belonging to the cases |
||||||
|
* plus the default destination address. |
||||||
|
*/ |
||||||
|
public SimpleSwitchInstructionHeader(int addr, int nextAddr, |
||||||
|
Instruction instr, |
||||||
|
int[] cases, int[] dests) { |
||||||
|
super(SWITCH, addr, nextAddr, instr, dests); |
||||||
|
this.cases = cases; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) { |
||||||
|
dumpDebugging(writer); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
if (needsLabel()) { |
||||||
|
writer.untab(); |
||||||
|
writer.println(getLabel()+": "); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
writer.println("switch ("+instr.toString()+") {"); |
||||||
|
writer.tab(); |
||||||
|
for (int i=0; i<cases.length; i++) |
||||||
|
writer.println("case "+cases[i]+": goto "+ |
||||||
|
successors[i].getLabel()); |
||||||
|
writer.println("default: "+ |
||||||
|
successors[successors.length-1].getLabel()); |
||||||
|
writer.println("}"); |
||||||
|
writer.untab(); |
||||||
|
|
||||||
|
if (Decompiler.isDebugging) |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,9 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
public class SimplifyExpression implements Transformation { |
||||||
|
public InstructionHeader transform(InstructionHeader ih) { |
||||||
|
if (ih.getInstruction() != null) |
||||||
|
ih.setInstruction(ih.getInstruction().simplify()); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
/** |
||||||
|
* This instruction header represents an if instruction. The |
||||||
|
* linkage of the instructions is as follow: |
||||||
|
* <pre> |
||||||
|
* A: .... |
||||||
|
* <p> |
||||||
|
* prev = A, next = H, pred = normal, succ = {C,E} |
||||||
|
* B: try { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* C: then-instr 1 |
||||||
|
* <p> |
||||||
|
* prev = C, next = H!, pred = normal succ = normal |
||||||
|
* D: instructions of then part |
||||||
|
* <p> |
||||||
|
* } catch (...) { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* E: else-instr 1 |
||||||
|
* <p> |
||||||
|
* prev = E, next = null, pred = normal, succ = normal |
||||||
|
* F: instructions of then part |
||||||
|
* <p> |
||||||
|
* } |
||||||
|
* prev = B, ..., pred = normal, succ = normal |
||||||
|
* H: ... |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* TODO: Implement finally. |
||||||
|
*/ |
||||||
|
public class TryCatchInstructionHeader extends InstructionHeader { |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a try catch statement. There are several conditions that |
||||||
|
* must be met: |
||||||
|
* <ul> |
||||||
|
* <li><code> |
||||||
|
* </code></li> |
||||||
|
* </ul> |
||||||
|
* @param successors the successors of this try, that is |
||||||
|
* the try header and the catch headers. |
||||||
|
* @param endHeader the end hader of the first try block. |
||||||
|
* This must be successors[1] or a single goto or return |
||||||
|
* statement jumping to endBlock. |
||||||
|
* @param remaining the remaining successors of the old try header. |
||||||
|
* @param endBlock the endBlock of this try statement |
||||||
|
*/ |
||||||
|
public TryCatchInstructionHeader(InstructionHeader[] successors, |
||||||
|
InstructionHeader endHeader, |
||||||
|
InstructionHeader[] remaining, |
||||||
|
InstructionHeader endBlock) { |
||||||
|
|
||||||
|
super(TRYCATCHBLOCK, successors[0].addr, endBlock.addr, |
||||||
|
successors, successors[0].outer); |
||||||
|
|
||||||
|
InstructionHeader tryHeader = successors[0]; |
||||||
|
this.movePredecessors(tryHeader); |
||||||
|
if (remaining.length > 1) { |
||||||
|
tryHeader.predecessors = new Vector(); |
||||||
|
tryHeader.predecessors.addElement(this); |
||||||
|
tryHeader.prevInstruction = null; |
||||||
|
tryHeader.successors = remaining; |
||||||
|
} else { |
||||||
|
successors[0] = tryHeader.nextInstruction; |
||||||
|
if (successors[0] != null) { |
||||||
|
successors[0].prevInstruction = null; |
||||||
|
successors[0].predecessors.addElement(this); |
||||||
|
} |
||||||
|
} |
||||||
|
this.endBlock = endBlock; |
||||||
|
this.nextInstruction = (endBlock.outer == outer) ? endBlock : null; |
||||||
|
if (nextInstruction != null) |
||||||
|
endBlock.prevInstruction = this; |
||||||
|
|
||||||
|
if (endHeader != successors[1]) |
||||||
|
endHeader.successors[0].predecessors.removeElement(endHeader); |
||||||
|
|
||||||
|
for (int i=1; i< successors.length; i++) { |
||||||
|
endHeader.predecessors.removeElement(tryHeader); |
||||||
|
successors[i].predecessors.removeElement(tryHeader); |
||||||
|
successors[i].predecessors.addElement(this); |
||||||
|
} |
||||||
|
|
||||||
|
for (InstructionHeader ih = successors[0]; ih != null; |
||||||
|
ih = ih.nextInstruction) { |
||||||
|
if (ih.outer == outer) |
||||||
|
ih.outer = this; |
||||||
|
if (ih.nextInstruction == endHeader) |
||||||
|
ih.nextInstruction = null; |
||||||
|
} |
||||||
|
for (int i=1; i< successors.length; i++) { |
||||||
|
for (InstructionHeader ih = successors[i]; ih != null; |
||||||
|
ih = ih.nextInstruction) { |
||||||
|
if (ih.outer == outer) |
||||||
|
ih.outer = this; |
||||||
|
if ((i < successors.length-1 && |
||||||
|
ih.nextInstruction == successors[i+1]) |
||||||
|
|| ih.nextInstruction == endBlock) |
||||||
|
|
||||||
|
ih.nextInstruction = null; |
||||||
|
|
||||||
|
if (ih.nextInstruction == null && |
||||||
|
(ih.flowType == GOTO || |
||||||
|
(ih.flowType == RETURN && |
||||||
|
ih.getInstruction().getType() == MyType.tVoid)) && |
||||||
|
ih.successors[0] == endBlock) |
||||||
|
|
||||||
|
ih.flowType = NORMAL; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) { |
||||||
|
dumpDebugging(writer); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
if (needsLabel()) { |
||||||
|
writer.untab(); |
||||||
|
writer.println(getLabel()+": "); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
writer.println("try {"); |
||||||
|
writer.tab(); |
||||||
|
if (successors[0] == null) |
||||||
|
writer.print("/* empty */"); |
||||||
|
else { |
||||||
|
for (InstructionHeader ih = successors[0]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
} |
||||||
|
writer.untab(); |
||||||
|
|
||||||
|
for (int i=1; i< successors.length; i++) { |
||||||
|
InstructionHeader catchIH = successors[i]; |
||||||
|
catchIH.dumpSource(writer); |
||||||
|
|
||||||
|
writer.tab(); |
||||||
|
if (catchIH.nextInstruction == null) |
||||||
|
writer.println("/* empty */"); |
||||||
|
else { |
||||||
|
for (InstructionHeader ih = catchIH.nextInstruction; |
||||||
|
ih != null; ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
} |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
writer.println("} "); |
||||||
|
|
||||||
|
if (Decompiler.isDebugging) |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader doTransformations(Transformation[] trafo) { |
||||||
|
InstructionHeader next; |
||||||
|
for (int i=0; i < successors.length; i++) { |
||||||
|
for (InstructionHeader ih = successors[i]; ih != null; ih = next) { |
||||||
|
if ((next = ih.doTransformations(trafo)) == null) |
||||||
|
next = ih.getNextInstruction(); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class TryInstructionHeader extends InstructionHeader { |
||||||
|
|
||||||
|
TryInstructionHeader(InstructionHeader firstInstr, |
||||||
|
InstructionHeader outer) { |
||||||
|
super(TRY, firstInstr.addr, firstInstr.addr, |
||||||
|
new InstructionHeader[1], outer); |
||||||
|
|
||||||
|
movePredecessors(firstInstr); |
||||||
|
successors[0] = firstInstr; |
||||||
|
firstInstr.predecessors = new Vector(); |
||||||
|
firstInstr.predecessors.addElement(this); |
||||||
|
|
||||||
|
prevInstruction = firstInstr.prevInstruction; |
||||||
|
if (prevInstruction != null) |
||||||
|
prevInstruction.nextInstruction = this; |
||||||
|
|
||||||
|
nextInstruction = firstInstr; |
||||||
|
firstInstr.prevInstruction = this; |
||||||
|
} |
||||||
|
|
||||||
|
public void addHandler(InstructionHeader endInstr, |
||||||
|
InstructionHeader catchInstr) { |
||||||
|
InstructionHeader[] newSuccessors = |
||||||
|
new InstructionHeader[successors.length+2]; |
||||||
|
System.arraycopy(successors, 0, newSuccessors, 0, successors.length); |
||||||
|
successors = newSuccessors; |
||||||
|
successors[successors.length-2] = endInstr; |
||||||
|
successors[successors.length-1] = catchInstr; |
||||||
|
endInstr.predecessors.addElement(this); |
||||||
|
catchInstr.predecessors.addElement(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) |
||||||
|
dumpDebugging(writer); |
||||||
|
|
||||||
|
if (successors.length > 1) { |
||||||
|
writer.print ("try: "); |
||||||
|
for (int i=1; i<successors.length; i+=2) |
||||||
|
writer.print("to "+successors[i].getLabel()+ |
||||||
|
" catch "+successors[i+1].getLabel()+"; "); |
||||||
|
writer.println(""); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,133 @@ |
|||||||
|
package jode; |
||||||
|
import java.util.Enumeration; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* This instruction header represents an if instruction. The |
||||||
|
* linkage of the instructions is as follow: |
||||||
|
* <pre> |
||||||
|
* A: .... |
||||||
|
* <p> |
||||||
|
* prev = A, next = H or null, pred = normal, succ = {H,C} |
||||||
|
* B: while ( instr ) { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* C: first block-instr |
||||||
|
* <p> |
||||||
|
* prev = C, next = E, pred = normal succ = normal |
||||||
|
* D: ... |
||||||
|
* <p> |
||||||
|
* prev = D, next = null, pred = normal succ = {B} |
||||||
|
* E: last block-instr |
||||||
|
* } |
||||||
|
* <p> |
||||||
|
* prev = B, ..., pred = (normal+{G}) \ {C..F}, succ = normal |
||||||
|
* H: ... |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
public class WhileInstructionHeader extends InstructionHeader { |
||||||
|
/** |
||||||
|
* Creates a new while statement. |
||||||
|
* @param prev the goto instruction in front of this while loop. |
||||||
|
* @param ifHeader the instruction header which contains the |
||||||
|
* if-goto statement. |
||||||
|
* @param blockStart the start of the inner block. |
||||||
|
* @param blockEnd the end of the inner block. |
||||||
|
* @param next the instruction header after this if block. |
||||||
|
*/ |
||||||
|
public WhileInstructionHeader(InstructionHeader prev, |
||||||
|
InstructionHeader ifHeader, |
||||||
|
InstructionHeader block) { |
||||||
|
|
||||||
|
super(WHILESTATEMENT, |
||||||
|
ifHeader.successors[1].addr, ifHeader.successors[0].addr, |
||||||
|
ifHeader.successors, ifHeader.outer); |
||||||
|
|
||||||
|
this.instr = ifHeader.instr; |
||||||
|
|
||||||
|
this.outer = ifHeader.outer; |
||||||
|
this.endBlock = this; |
||||||
|
|
||||||
|
this.movePredecessors(ifHeader); |
||||||
|
this.addr = successors[1].addr; |
||||||
|
prev.flowType = NORMAL; |
||||||
|
|
||||||
|
this.prevInstruction = successors[1].prevInstruction; |
||||||
|
if (prevInstruction != null) |
||||||
|
prevInstruction.nextInstruction = this; |
||||||
|
|
||||||
|
this.nextInstruction = ifHeader.nextInstruction; |
||||||
|
if (nextInstruction != null) |
||||||
|
nextInstruction.prevInstruction = this; |
||||||
|
|
||||||
|
successors[1].prevInstruction = null; |
||||||
|
ifHeader.prevInstruction.nextInstruction = null; |
||||||
|
|
||||||
|
successors[0].predecessors.removeElement(ifHeader); |
||||||
|
successors[1].predecessors.removeElement(ifHeader); |
||||||
|
successors[0].predecessors.addElement(this); |
||||||
|
successors[1].predecessors.addElement(this); |
||||||
|
|
||||||
|
for (InstructionHeader ih = successors[1]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
if (ih.outer == outer) |
||||||
|
ih.outer = this; |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (Decompiler.isDebugging) { |
||||||
|
dumpDebugging(writer); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
if (needsLabel()) { |
||||||
|
writer.untab(); |
||||||
|
writer.println(getLabel()+": "); |
||||||
|
writer.tab(); |
||||||
|
} |
||||||
|
|
||||||
|
boolean braces = successors[1].nextInstruction != null; |
||||||
|
writer.println("while (" + instr.toString() + ")" + |
||||||
|
(braces ? " {": "")); |
||||||
|
|
||||||
|
writer.tab(); |
||||||
|
for (InstructionHeader ih = successors[1]; ih != null; |
||||||
|
ih = ih.nextInstruction) |
||||||
|
ih.dumpSource(writer); |
||||||
|
writer.untab(); |
||||||
|
|
||||||
|
if (braces) |
||||||
|
writer.println("} "); |
||||||
|
|
||||||
|
if (Decompiler.isDebugging) |
||||||
|
writer.untab(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the InstructionHeader where a break of this instruction |
||||||
|
* would jump to. Does only make sense for do/while/for-loops and |
||||||
|
* switch instructions. |
||||||
|
*/ |
||||||
|
public InstructionHeader getBreak() { |
||||||
|
return successors[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the InstructionHeader where a continue of this instruction |
||||||
|
* would jump to. Does only make sense for do/while/for-loops. |
||||||
|
*/ |
||||||
|
public InstructionHeader getContinue() { |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public InstructionHeader doTransformations(Transformation[] trafo) { |
||||||
|
InstructionHeader next; |
||||||
|
for (InstructionHeader ih = successors[1]; ih != null; ih = next) { |
||||||
|
if ((next = ih.doTransformations(trafo)) == null) |
||||||
|
next = ih.getNextInstruction(); |
||||||
|
} |
||||||
|
return super.doTransformations(trafo); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue