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; |
||||
import java.util.Vector; |
||||
import sun.tools.java.BinaryExceptionHandler; |
||||
import sun.tools.java.Type; |
||||
|
||||
/** |
||||
* This class is the end point of the InstructionHeader list. |
||||
* @author Jochen Hoenicke |
||||
*/ |
||||
public class MethodInstructionHeader extends InstructionHeader { |
||||
InstructionHeader first, last; |
||||
|
||||
/** |
||||
* Create a new InstructionHeader. |
||||
* @param addr The address of this Instruction. |
||||
* @param length The length of this Instruction. |
||||
* @param instr The underlying Instruction. |
||||
*/ |
||||
public MethodInstructionHeader(InstructionHeader[] instr) { |
||||
super(-1,1,null); |
||||
nextInstruction = instr[0]; |
||||
nextInstruction.predecessors.addElement(this); |
||||
for (int addr = 0; addr < instr.length; ) { |
||||
public MethodInstructionHeader(JodeEnvironment env, |
||||
InstructionHeader[] instr, |
||||
BinaryExceptionHandler[] handlers) { |
||||
super(METHOD, 0, instr.length, new InstructionHeader[0], null); |
||||
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); |
||||
if (instr[addr].succs.length == 0) |
||||
predecessors.addElement(instr[addr]); |
||||
addr = instr[addr].getNextAddr(); |
||||
|
||||
if (instr[addr].flowType == RETURN) { |
||||
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; |
||||
} |
||||
|
||||
} |
||||
for (int i=0; i<handlers.length; i++) { |
||||
InstructionHeader tryIH = instr[handlers[i].startPC]; |
||||
if (tryIH.flowType != TRY) |
||||
instr[handlers[i].startPC] = tryIH = |
||||
new TryInstructionHeader(tryIH, this); |
||||
|
||||
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; |
||||
} |
||||
|
||||
/** |
||||
* Resolve the successors and predecessors and build a doubly |
||||
* linked list. |
||||
* @param instHeaders an array of the InstructionHeaders, indexed |
||||
* by addresses. |
||||
*/ |
||||
public void resolveSuccessors(InstructionHeader[] instHeaders) { |
||||
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