use of soot.jimple.ThrowStmt in project robovm by robovm.
the class MethodCompiler method doCompile.
protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
function = createMethodFunction(method);
moduleBuilder.addFunction(function);
this.moduleBuilder = moduleBuilder;
env = function.getParameterRef(0);
trapsAt = new HashMap<Unit, List<Trap>>();
Body body = method.retrieveActiveBody();
NopStmt prependedNop = null;
if (method.isStatic() && !body.getUnits().getFirst().getBoxesPointingToThis().isEmpty()) {
// Fix for issue #1. This prevents an NPE in Soot's ArrayBoundsCheckerAnalysis. The NPE
// occurs for static methods which start with a unit that is the target of some other
// unit. We work around this by inserting a nop statement as the first unit in such
// methods. See http://www.sable.mcgill.ca/listarchives/soot-list/msg01397.html.
Unit insertionPoint = body.getUnits().getFirst();
prependedNop = Jimple.v().newNopStmt();
body.getUnits().getNonPatchingChain().insertBefore(prependedNop, insertionPoint);
}
PackManager.v().getPack("jtp").apply(body);
PackManager.v().getPack("jop").apply(body);
PackManager.v().getPack("jap").apply(body);
if (body.getUnits().getFirst() == prependedNop && prependedNop.getBoxesPointingToThis().isEmpty()) {
// Remove the nop we inserted above to work around the bug in Soot's
// ArrayBoundsCheckerAnalysis which has now been run.
body.getUnits().getNonPatchingChain().removeFirst();
}
PatchingChain<Unit> units = body.getUnits();
Map<Unit, List<Unit>> branchTargets = getBranchTargets(body);
Map<Unit, Integer> trapHandlers = getTrapHandlers(body);
Map<Unit, Integer> selChanges = new HashMap<Unit, Integer>();
int multiANewArrayMaxDims = 0;
Set<Local> locals = new HashSet<Local>();
boolean emitCheckStackOverflow = false;
for (Unit unit : units) {
if (unit instanceof DefinitionStmt) {
DefinitionStmt stmt = (DefinitionStmt) unit;
if (stmt.getLeftOp() instanceof Local) {
Local local = (Local) stmt.getLeftOp();
if (!locals.contains(local)) {
Type type = getLocalType(local.getType());
Alloca alloca = new Alloca(function.newVariable(local.getName(), type), type);
alloca.attach(local);
function.add(alloca);
locals.add(local);
}
}
if (stmt.getRightOp() instanceof NewMultiArrayExpr) {
NewMultiArrayExpr expr = (NewMultiArrayExpr) stmt.getRightOp();
multiANewArrayMaxDims = Math.max(multiANewArrayMaxDims, expr.getSizeCount());
}
if (stmt.getRightOp() instanceof InvokeExpr) {
emitCheckStackOverflow = true;
}
}
if (unit instanceof InvokeStmt) {
emitCheckStackOverflow = true;
}
}
dims = null;
if (multiANewArrayMaxDims > 0) {
dims = function.newVariable("dims", new PointerType(new ArrayType(multiANewArrayMaxDims, I32)));
function.add(new Alloca(dims, new ArrayType(multiANewArrayMaxDims, I32)));
}
if (emitCheckStackOverflow) {
call(CHECK_STACK_OVERFLOW);
}
Value trycatchContext = null;
if (!body.getTraps().isEmpty()) {
List<List<Trap>> recordedTraps = new ArrayList<List<Trap>>();
for (Unit unit : units) {
// Calculate the predecessor units of unit
Set<Unit> incoming = new HashSet<Unit>();
if (units.getFirst() != unit && units.getPredOf(unit).fallsThrough()) {
incoming.add(units.getPredOf(unit));
}
if (branchTargets.keySet().contains(unit)) {
incoming.addAll(branchTargets.get(unit));
}
if (unit == units.getFirst() || trapHandlers.containsKey(unit) || trapsDiffer(unit, incoming)) {
List<Trap> traps = getTrapsAt(unit);
if (traps.isEmpty()) {
selChanges.put(unit, 0);
} else {
int index = recordedTraps.indexOf(traps);
if (index == -1) {
index = recordedTraps.size();
recordedTraps.add(traps);
}
selChanges.put(unit, index + 1);
}
}
}
StructureConstantBuilder landingPadsPtrs = new StructureConstantBuilder();
for (List<Trap> traps : recordedTraps) {
StructureConstantBuilder landingPads = new StructureConstantBuilder();
for (Trap trap : traps) {
SootClass exClass = trap.getException();
StructureConstantBuilder landingPad = new StructureConstantBuilder();
if ("java.lang.Throwable".equals(exClass.getName()) || exClass.isPhantom()) {
landingPad.add(new NullConstant(I8_PTR));
} else {
catches.add(getInternalName(exClass));
if (exClass == sootClass) {
/*
* The class being compiled is an exception class
* with a catch clause which catches itself. We
* cannot reference the info struct directly since
* we don't know the type of it and it hasn't been
* emitted by ClassCompiler yet. Use the internal
* i8* alias instead which ClassCompiler will emit.
* See #1007.
*/
landingPad.add(new AliasRef(Symbols.infoStructSymbol(getInternalName(exClass)) + "_i8ptr", I8_PTR));
} else {
Global g = new Global(Symbols.infoStructSymbol(getInternalName(exClass)), I8_PTR, true);
if (!moduleBuilder.hasSymbol(g.getName())) {
moduleBuilder.addGlobal(g);
}
landingPad.add(g.ref());
}
}
landingPad.add(new IntegerConstant(trapHandlers.get(trap.getHandlerUnit()) + 1));
landingPads.add(landingPad.build());
}
landingPads.add(new StructureConstantBuilder().add(new NullConstant(I8_PTR)).add(new IntegerConstant(0)).build());
Global g = moduleBuilder.newGlobal(landingPads.build(), true);
landingPadsPtrs.add(new ConstantBitcast(g.ref(), I8_PTR));
}
Global g = moduleBuilder.newGlobal(landingPadsPtrs.build(), true);
Variable ctx = function.newVariable(TRYCATCH_CONTEXT_PTR);
Variable bcCtx = function.newVariable(BC_TRYCATCH_CONTEXT_PTR);
function.add(new Alloca(bcCtx, BC_TRYCATCH_CONTEXT));
Variable selPtr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(selPtr, bcCtx.ref(), 0, 0, 1));
function.add(new Store(new IntegerConstant(0), selPtr.ref()));
Variable bcCtxLandingPadsPtr = function.newVariable(I8_PTR_PTR);
function.add(new Getelementptr(bcCtxLandingPadsPtr, bcCtx.ref(), 0, 1));
function.add(new Store(new ConstantBitcast(g.ref(), I8_PTR), bcCtxLandingPadsPtr.ref()));
function.add(new Bitcast(ctx, bcCtx.ref(), TRYCATCH_CONTEXT_PTR));
trycatchContext = ctx.ref();
Value result = call(RVM_TRYCATCH_ENTER, env, trycatchContext);
Map<IntegerConstant, BasicBlockRef> alt = new TreeMap<IntegerConstant, BasicBlockRef>();
for (Entry<Unit, Integer> entry : trapHandlers.entrySet()) {
alt.put(new IntegerConstant(entry.getValue() + 1), function.newBasicBlockRef(new Label(entry.getKey())));
}
function.add(new Switch(result, function.newBasicBlockRef(new Label(units.getFirst())), alt));
if (!branchTargets.containsKey(units.getFirst())) {
function.newBasicBlock(new Label(units.getFirst()));
}
}
if ("<clinit>".equals(method.getName())) {
initializeClassFields();
}
for (Unit unit : units) {
if (branchTargets.containsKey(unit) || trapHandlers.containsKey(unit)) {
BasicBlock oldBlock = function.getCurrentBasicBlock();
function.newBasicBlock(new Label(unit));
if (oldBlock != null) {
Instruction last = oldBlock.last();
if (last == null || !isTerminator(last)) {
oldBlock.add(new Br(function.newBasicBlockRef(new Label(unit))));
}
}
}
if (selChanges.containsKey(unit)) {
int sel = selChanges.get(unit);
// trycatchContext->sel = sel
Variable selPtr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(selPtr, trycatchContext, 0, 1)).attach(unit);
function.add(new Store(new IntegerConstant(sel), selPtr.ref())).attach(unit);
}
if (unit instanceof DefinitionStmt) {
assign((DefinitionStmt) unit);
} else if (unit instanceof ReturnStmt) {
if (!body.getTraps().isEmpty()) {
trycatchLeave(function);
}
return_((ReturnStmt) unit);
} else if (unit instanceof ReturnVoidStmt) {
if (!body.getTraps().isEmpty()) {
trycatchLeave(function);
}
returnVoid((ReturnVoidStmt) unit);
} else if (unit instanceof IfStmt) {
if_((IfStmt) unit);
} else if (unit instanceof LookupSwitchStmt) {
lookupSwitch((LookupSwitchStmt) unit);
} else if (unit instanceof TableSwitchStmt) {
tableSwitch((TableSwitchStmt) unit);
} else if (unit instanceof GotoStmt) {
goto_((GotoStmt) unit);
} else if (unit instanceof ThrowStmt) {
throw_((ThrowStmt) unit);
} else if (unit instanceof InvokeStmt) {
invoke((InvokeStmt) unit);
} else if (unit instanceof EnterMonitorStmt) {
enterMonitor((EnterMonitorStmt) unit);
} else if (unit instanceof ExitMonitorStmt) {
exitMonitor((ExitMonitorStmt) unit);
} else if (unit instanceof NopStmt) {
nop((NopStmt) unit);
} else {
throw new IllegalArgumentException("Unknown Unit type: " + unit.getClass());
}
}
if (this.className.equals("java/lang/Object") && "<init>".equals(method.getName())) {
// If it is the object will be registered for finalization.
for (BasicBlock bb : function.getBasicBlocks()) {
if (bb.last() instanceof Ret) {
// Insert a call to register_finalizable() before this ret
Call call = new Call(REGISTER_FINALIZABLE, env, function.getParameterRef(1));
call.attach(bb.last().getAttachment(Unit.class));
bb.insertBefore(bb.last(), call);
}
}
}
return function;
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class AsmMethodSource method convertInsn.
private void convertInsn(InsnNode insn) {
int op = insn.getOpcode();
if (op == NOP) {
/*
* We can ignore NOP instructions, but
* for completeness, we handle them
*/
if (!units.containsKey(insn))
units.put(insn, Jimple.v().newNopStmt());
} else if (op >= ACONST_NULL && op <= DCONST_1) {
convertConstInsn(insn);
} else if (op >= IALOAD && op <= SALOAD) {
convertArrayLoadInsn(insn);
} else if (op >= IASTORE && op <= SASTORE) {
convertArrayStoreInsn(insn);
} else if (op == POP) {
popImmediate();
} else if (op == POP2) {
popImmediate();
if (peek() == DWORD_DUMMY)
pop();
else
popImmediate();
} else if (op >= DUP && op <= DUP2_X2) {
convertDupInsn((InsnNode) insn);
} else if (op == SWAP) {
Operand o1 = popImmediate();
Operand o2 = popImmediate();
push(o1);
push(o2);
} else if ((op >= IADD && op <= DREM) || (op >= ISHL && op <= LXOR) || (op >= LCMP && op <= DCMPG)) {
convertBinopInsn((InsnNode) insn);
} else if ((op >= INEG && op <= DNEG) || op == ARRAYLENGTH) {
convertUnopInsn(insn);
} else if (op >= I2L && op <= I2S) {
convertPrimCastInsn(insn);
} else if (op >= IRETURN && op <= ARETURN) {
convertReturnInsn(insn);
} else if (op == RETURN) {
if (!units.containsKey(insn))
setUnit(insn, Jimple.v().newReturnVoidStmt());
} else if (op == ATHROW) {
StackFrame frame = getFrame(insn);
Operand opr;
if (!units.containsKey(insn)) {
opr = popImmediate();
ThrowStmt ts = Jimple.v().newThrowStmt(opr.stackOrValue());
opr.addBox(ts.getOpBox());
frame.in(opr);
frame.out(opr);
frame.boxes(ts.getOpBox());
setUnit(insn, ts);
} else {
opr = pop();
frame.mergeIn(opr);
}
push(opr);
} else if (op == MONITORENTER || op == MONITOREXIT) {
StackFrame frame = getFrame(insn);
if (!units.containsKey(insn)) {
Operand opr = popStackConst();
MonitorStmt ts = op == MONITORENTER ? Jimple.v().newEnterMonitorStmt(opr.stackOrValue()) : Jimple.v().newExitMonitorStmt(opr.stackOrValue());
opr.addBox(ts.getOpBox());
frame.in(opr);
frame.boxes(ts.getOpBox());
setUnit(insn, ts);
} else {
frame.mergeIn(pop());
}
} else {
throw new AssertionError("Unknown insn op: " + op);
}
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class MethodNodeFactory method handleStmt.
/**
* Adds the edges required for this statement to the graph.
*/
public final void handleStmt(Stmt s) {
// We only consider reflective class creation when it is enabled
if (s.containsInvokeExpr()) {
if (!pag.getCGOpts().types_for_invoke())
return;
InvokeExpr iexpr = s.getInvokeExpr();
if (iexpr instanceof VirtualInvokeExpr) {
if (!isReflectionNewInstance(iexpr))
return;
} else if (!(iexpr instanceof StaticInvokeExpr))
return;
}
s.apply(new AbstractStmtSwitch() {
@Override
public final void caseAssignStmt(AssignStmt as) {
Value l = as.getLeftOp();
Value r = as.getRightOp();
if (!(l.getType() instanceof RefLikeType))
return;
assert r.getType() instanceof RefLikeType : "Type mismatch in assignment " + as + " in method " + method.getSignature();
l.apply(MethodNodeFactory.this);
Node dest = getNode();
r.apply(MethodNodeFactory.this);
Node src = getNode();
if (l instanceof InstanceFieldRef) {
((InstanceFieldRef) l).getBase().apply(MethodNodeFactory.this);
pag.addDereference((VarNode) getNode());
}
if (r instanceof InstanceFieldRef) {
((InstanceFieldRef) r).getBase().apply(MethodNodeFactory.this);
pag.addDereference((VarNode) getNode());
} else if (r instanceof StaticFieldRef) {
StaticFieldRef sfr = (StaticFieldRef) r;
SootFieldRef s = sfr.getFieldRef();
if (pag.getOpts().empties_as_allocs()) {
if (s.declaringClass().getName().equals("java.util.Collections")) {
if (s.name().equals("EMPTY_SET")) {
src = pag.makeAllocNode(RefType.v("java.util.HashSet"), RefType.v("java.util.HashSet"), method);
} else if (s.name().equals("EMPTY_MAP")) {
src = pag.makeAllocNode(RefType.v("java.util.HashMap"), RefType.v("java.util.HashMap"), method);
} else if (s.name().equals("EMPTY_LIST")) {
src = pag.makeAllocNode(RefType.v("java.util.LinkedList"), RefType.v("java.util.LinkedList"), method);
}
} else if (s.declaringClass().getName().equals("java.util.Hashtable")) {
if (s.name().equals("emptyIterator")) {
src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyIterator"), RefType.v("java.util.Hashtable$EmptyIterator"), method);
} else if (s.name().equals("emptyEnumerator")) {
src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyEnumerator"), RefType.v("java.util.Hashtable$EmptyEnumerator"), method);
}
}
}
}
mpag.addInternalEdge(src, dest);
}
@Override
public final void caseReturnStmt(ReturnStmt rs) {
if (!(rs.getOp().getType() instanceof RefLikeType))
return;
rs.getOp().apply(MethodNodeFactory.this);
Node retNode = getNode();
mpag.addInternalEdge(retNode, caseRet());
}
@Override
public final void caseIdentityStmt(IdentityStmt is) {
if (!(is.getLeftOp().getType() instanceof RefLikeType))
return;
Value leftOp = is.getLeftOp();
Value rightOp = is.getRightOp();
leftOp.apply(MethodNodeFactory.this);
Node dest = getNode();
rightOp.apply(MethodNodeFactory.this);
Node src = getNode();
mpag.addInternalEdge(src, dest);
// in case library mode is activated add allocations to any
// possible type of this local and
// parameters of accessible methods
int libOption = pag.getCGOpts().library();
if (libOption != CGOptions.library_disabled && (accessibilityOracle.isAccessible(method))) {
if (rightOp instanceof IdentityRef) {
Type rt = rightOp.getType();
rt.apply(new SparkLibraryHelper(pag, src, method));
}
}
}
@Override
public final void caseThrowStmt(ThrowStmt ts) {
ts.getOp().apply(MethodNodeFactory.this);
mpag.addOutEdge(getNode(), pag.nodeFactory().caseThrow());
}
});
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class DalvikTyper method assignType.
@Override
public void assignType(final Body b) {
// Debug.printDbg("assignTypes: before: \n", b);
constraints.clear();
localObjList.clear();
final Set<Unit> todoUnits = new HashSet<Unit>();
// put constraints:
for (Unit u : b.getUnits()) {
StmtSwitch ss = new StmtSwitch() {
@Override
public void caseBreakpointStmt(BreakpointStmt stmt) {
// nothing
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
// add constraint
DalvikTyper.v().setInvokeType(stmt.getInvokeExpr());
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
// add constraint
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
// size in new array expression is of tye integer
if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
ValueBox sb = nae.getSizeBox();
if (sb.getValue() instanceof Local) {
DalvikTyper.v().setType(sb, IntType.v(), true);
}
}
// array index is of type integer
if (stmt.containsArrayRef()) {
ArrayRef ar = stmt.getArrayRef();
ValueBox sb = ar.getIndexBox();
if (sb.getValue() instanceof Local) {
DalvikTyper.v().setType(sb, IntType.v(), true);
}
}
if (l instanceof Local && r instanceof Local) {
DalvikTyper.v().addConstraint(stmt.getLeftOpBox(), stmt.getRightOpBox());
return;
}
if (stmt.containsInvokeExpr()) {
DalvikTyper.v().setInvokeType(stmt.getInvokeExpr());
}
if (r instanceof Local) {
// l NOT local
Type leftType = stmt.getLeftOp().getType();
if (l instanceof ArrayRef && leftType instanceof UnknownType) {
// find type later
todoUnits.add(stmt);
return;
}
DalvikTyper.v().setType(stmt.getRightOpBox(), leftType, true);
return;
}
if (l instanceof Local) {
if (r instanceof UntypedConstant)
return;
for (Tag t : stmt.getTags()) {
if (r instanceof CastExpr) {
// do not check tag, since the tag is for the operand of the cast
break;
}
// Debug.printDbg("assign stmt tag: ", stmt, t);
if (t instanceof IntOpTag) {
checkExpr(r, IntType.v());
DalvikTyper.v().setType(stmt.getLeftOpBox(), IntType.v(), false);
return;
} else if (t instanceof FloatOpTag) {
checkExpr(r, FloatType.v());
DalvikTyper.v().setType(stmt.getLeftOpBox(), FloatType.v(), false);
return;
} else if (t instanceof DoubleOpTag) {
checkExpr(r, DoubleType.v());
DalvikTyper.v().setType(stmt.getLeftOpBox(), DoubleType.v(), false);
return;
} else if (t instanceof LongOpTag) {
checkExpr(r, LongType.v());
DalvikTyper.v().setType(stmt.getLeftOpBox(), LongType.v(), false);
return;
}
}
Type rightType = stmt.getRightOp().getType();
if (r instanceof ArrayRef && rightType instanceof UnknownType) {
// find type later
todoUnits.add(stmt);
return;
} else if (r instanceof CastExpr) {
CastExpr ce = (CastExpr) r;
Type castType = ce.getCastType();
if (castType instanceof PrimType) {
// check incoming primitive type
for (Tag t : stmt.getTags()) {
// Debug.printDbg("assign primitive type from stmt tag: ", stmt, t);
if (t instanceof IntOpTag) {
DalvikTyper.v().setType(ce.getOpBox(), IntType.v(), false);
return;
} else if (t instanceof FloatOpTag) {
DalvikTyper.v().setType(ce.getOpBox(), FloatType.v(), false);
return;
} else if (t instanceof DoubleOpTag) {
DalvikTyper.v().setType(ce.getOpBox(), DoubleType.v(), false);
return;
} else if (t instanceof LongOpTag) {
DalvikTyper.v().setType(ce.getOpBox(), LongType.v(), false);
return;
}
}
} else {
// incoming type is object
DalvikTyper.v().setType(ce.getOpBox(), RefType.v("java.lang.Object"), false);
}
}
DalvikTyper.v().setType(stmt.getLeftOpBox(), rightType, false);
return;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
DalvikTyper.v().setType(stmt.getLeftOpBox(), stmt.getRightOp().getType(), false);
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
}
@Override
public void caseGotoStmt(GotoStmt stmt) {
// nothing
}
@Override
public void caseIfStmt(IfStmt stmt) {
// add constraint
Value c = stmt.getCondition();
if (c instanceof BinopExpr) {
BinopExpr bo = (BinopExpr) c;
Value op1 = bo.getOp1();
Value op2 = bo.getOp2();
if (op1 instanceof Local && op2 instanceof Local) {
DalvikTyper.v().addConstraint(bo.getOp1Box(), bo.getOp2Box());
}
}
}
@Override
public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getKeyBox(), IntType.v(), true);
}
@Override
public void caseNopStmt(NopStmt stmt) {
// nothing
}
@Override
public void caseRetStmt(RetStmt stmt) {
// nothing
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getOpBox(), b.getMethod().getReturnType(), true);
}
@Override
public void caseReturnVoidStmt(ReturnVoidStmt stmt) {
// nothing
}
@Override
public void caseTableSwitchStmt(TableSwitchStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getKeyBox(), IntType.v(), true);
}
@Override
public void caseThrowStmt(ThrowStmt stmt) {
// add constraint
DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
}
@Override
public void defaultCase(Object obj) {
throw new RuntimeException("error: unknown statement: " + obj);
}
};
u.apply(ss);
}
// <com.admob.android.ads.q: void a(android.os.Bundle,java.lang.String,java.lang.Object)>
if (!todoUnits.isEmpty()) {
// propagate array types
UnitGraph ug = new ExceptionalUnitGraph(b);
SimpleLocalDefs sld = new SimpleLocalDefs(ug);
SimpleLocalUses slu = new SimpleLocalUses(b, sld);
for (Unit u : b.getUnits()) {
if (u instanceof DefinitionStmt) {
// Debug.printDbg("U: ", u);
DefinitionStmt ass = (DefinitionStmt) u;
Value r = ass.getRightOp();
if (r instanceof UntypedConstant)
continue;
Type rType = r.getType();
if (rType instanceof ArrayType && ass.getLeftOp() instanceof Local) {
// Debug.printDbg("propagate-array: checking ", u);
// propagate array type through aliases
Set<Unit> done = new HashSet<Unit>();
Set<DefinitionStmt> toDo = new HashSet<DefinitionStmt>();
toDo.add(ass);
while (!toDo.isEmpty()) {
DefinitionStmt currentUnit = toDo.iterator().next();
if (done.contains(currentUnit)) {
toDo.remove(currentUnit);
continue;
}
done.add(currentUnit);
for (UnitValueBoxPair uvbp : slu.getUsesOf(currentUnit)) {
Unit use = uvbp.unit;
Value l2 = null;
Value r2 = null;
if (use instanceof AssignStmt) {
AssignStmt ass2 = (AssignStmt) use;
l2 = ass2.getLeftOp();
r2 = ass2.getRightOp();
if (!(l2 instanceof Local) || !(r2 instanceof Local || r2 instanceof ArrayRef)) {
// Debug.printDbg("propagate-array: skipping ", use);
continue;
}
Type newType = null;
if (r2 instanceof Local) {
List<LocalObj> lobjs = local2Obj.get(r2);
newType = lobjs.get(0).t;
} else if (r2 instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r2;
// skip if use is in index
if (ar.getIndex() == currentUnit.getLeftOp()) {
// Debug.printDbg("skipping since local is used as index...");
continue;
}
Local arBase = (Local) ar.getBase();
List<LocalObj> lobjs = local2Obj.get(arBase);
Type baseT = lobjs.get(0).t;
if (baseT.toString().equals(("java.lang.Object"))) {
// look for an array type, because an TTT[] is also an Object...
ArrayType aTypeOtherThanObject = null;
for (LocalObj lo : local2Obj.get(arBase)) {
if (lo.t instanceof ArrayType) {
aTypeOtherThanObject = (ArrayType) lo.t;
}
}
if (aTypeOtherThanObject == null) {
throw new RuntimeException("error: did not found array type for base " + arBase + " " + local2Obj.get(arBase) + " \n " + b);
}
baseT = aTypeOtherThanObject;
}
ArrayType at = (ArrayType) baseT;
newType = at.getElementType();
} else {
throw new RuntimeException("error: expected Local or ArrayRef. Got " + r2);
}
toDo.add((DefinitionStmt) use);
DalvikTyper.v().setType(ass2.getLeftOpBox(), newType, true);
}
}
}
}
}
}
for (Unit u : todoUnits) {
// Debug.printDbg("todo unit: ", u);
}
while (!todoUnits.isEmpty()) {
Unit u = todoUnits.iterator().next();
if (!(u instanceof AssignStmt)) {
throw new RuntimeException("error: expecting assign stmt. Got " + u);
}
AssignStmt ass = (AssignStmt) u;
Value l = ass.getLeftOp();
Value r = ass.getRightOp();
ArrayRef ar = null;
Local loc = null;
if (l instanceof ArrayRef) {
ar = (ArrayRef) l;
loc = (Local) r;
} else if (r instanceof ArrayRef) {
ar = (ArrayRef) r;
loc = (Local) l;
} else {
throw new RuntimeException("error: expecting an array ref. Got " + u);
}
Local baselocal = (Local) ar.getBase();
if (!local2Obj.containsKey(baselocal)) {
// Debug.printDbg("b: ", b.getMethod(), " \n", b);
throw new RuntimeException("oups");
}
Type baseT = local2Obj.get(baselocal).get(0).t;
if (baseT.toString().equals(("java.lang.Object"))) {
// look for an array type, because an TTT[] is also an Object...
ArrayType aTypeOtherThanObject = null;
for (LocalObj lo : local2Obj.get(baselocal)) {
if (lo.t instanceof ArrayType) {
aTypeOtherThanObject = (ArrayType) lo.t;
}
}
if (aTypeOtherThanObject == null) {
throw new RuntimeException("did not found array type for base " + baselocal + " " + local2Obj.get(baselocal) + " \n " + b);
}
baseT = aTypeOtherThanObject;
}
ArrayType basetype = (ArrayType) baseT;
// Debug.printDbg("v: ", ar, " base:", ar.getBase(), " base type: ", basetype, " type: ", ar.getType());
Type t = basetype.getElementType();
if (t instanceof UnknownType) {
todoUnits.add(u);
continue;
} else {
DalvikTyper.v().setType(ar == l ? ass.getRightOpBox() : ass.getLeftOpBox(), t, true);
todoUnits.remove(u);
}
}
// throw new RuntimeException("ouppppp");
}
// Debug.printDbg(IDalvikTyper.DEBUG, "list of constraints:");
List<ValueBox> vbList = b.getUseAndDefBoxes();
// clear constraints after local splitting and dead code eliminator
List<Constraint> toRemove = new ArrayList<Constraint>();
for (Constraint c : constraints) {
if (!vbList.contains(c.l)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "warning: ", c.l, " not in locals! removing...");
toRemove.add(c);
continue;
}
if (!vbList.contains(c.r)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "warning: ", c.r, " not in locals! removing...");
toRemove.add(c);
continue;
}
}
for (Constraint c : toRemove) constraints.remove(c);
// keep only valid locals
for (LocalObj lo : localObjList) {
if (!vbList.contains(lo.vb)) {
// Debug.printDbg(IDalvikTyper.DEBUG, " -- removing vb: ", lo.vb, " with type ", lo.t);
continue;
}
Local l = lo.getLocal();
Type t = lo.t;
if (localTemp.contains(l) && lo.isUse) {
// Debug.printDbg(IDalvikTyper.DEBUG, " /!\\ def already added for local ", l, "! for vb: ", lo.vb);
} else {
// Debug.printDbg(IDalvikTyper.DEBUG, " * add type ", t, " to local ", l, " for vb: ", lo.vb);
localTemp.add(l);
typed.put(lo.vb, t);
}
}
for (ValueBox vb : typed.keySet()) {
if (vb.getValue() instanceof Local) {
Local l = (Local) vb.getValue();
localTyped.put(l, typed.get(vb));
}
}
for (Constraint c : constraints) // Debug.printDbg(IDalvikTyper.DEBUG, " -> constraint: ", c);
for (ValueBox vb : typed.keySet()) {
// Debug.printDbg(IDalvikTyper.DEBUG, " typed: ", vb, " -> ", typed.get(vb));
}
for (Local l : localTyped.keySet()) {
// Debug.printDbg(IDalvikTyper.DEBUG, " localTyped: ", l, " -> ", localTyped.get(l));
}
while (!constraints.isEmpty()) {
boolean update = false;
for (Constraint c : constraints) {
// Debug.printDbg(IDalvikTyper.DEBUG, "current constraint: ", c);
Value l = c.l.getValue();
Value r = c.r.getValue();
if (l instanceof Local && r instanceof Constant) {
Constant cst = (Constant) r;
if (!localTyped.containsKey(l))
continue;
Type lt = localTyped.get(l);
// Debug.printDbg(IDalvikTyper.DEBUG, "would like to set type ", lt, " to constant: ", c);
Value newValue = null;
if (lt instanceof IntType || lt instanceof BooleanType || lt instanceof ShortType || lt instanceof CharType || lt instanceof ByteType) {
UntypedIntOrFloatConstant uf = (UntypedIntOrFloatConstant) cst;
newValue = uf.toIntConstant();
} else if (lt instanceof FloatType) {
UntypedIntOrFloatConstant uf = (UntypedIntOrFloatConstant) cst;
newValue = uf.toFloatConstant();
} else if (lt instanceof DoubleType) {
UntypedLongOrDoubleConstant ud = (UntypedLongOrDoubleConstant) cst;
newValue = ud.toDoubleConstant();
} else if (lt instanceof LongType) {
UntypedLongOrDoubleConstant ud = (UntypedLongOrDoubleConstant) cst;
newValue = ud.toLongConstant();
} else {
if (cst instanceof UntypedIntOrFloatConstant && ((UntypedIntOrFloatConstant) cst).value == 0) {
newValue = NullConstant.v();
// Debug.printDbg("new null constant for constraint ", c, " with l type: ", localTyped.get(l));
} else {
throw new RuntimeException("unknow type for constance: " + lt);
}
}
c.r.setValue(newValue);
// Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
constraints.remove(c);
update = true;
break;
} else if (l instanceof Local && r instanceof Local) {
Local leftLocal = (Local) l;
Local rightLocal = (Local) r;
if (localTyped.containsKey(leftLocal)) {
Type leftLocalType = localTyped.get(leftLocal);
if (!localTyped.containsKey(rightLocal)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "set type ", leftLocalType, " to local ", rightLocal);
rightLocal.setType(leftLocalType);
setLocalTyped(rightLocal, leftLocalType);
}
// Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
constraints.remove(c);
update = true;
break;
} else if (localTyped.containsKey(rightLocal)) {
Type rightLocalType = localTyped.get(rightLocal);
if (!localTyped.containsKey(leftLocal)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "set type ", rightLocalType, " to local ", leftLocal);
leftLocal.setType(rightLocalType);
setLocalTyped(leftLocal, rightLocalType);
}
// Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
constraints.remove(c);
update = true;
break;
}
} else if (l instanceof ArrayRef && r instanceof Local) {
Local rightLocal = (Local) r;
ArrayRef ar = (ArrayRef) l;
Local base = (Local) ar.getBase();
// Debug.printDbg(IDalvikTyper.DEBUG, "index: ", ar.getIndex());
if (localTyped.containsKey(base)) {
Type t = localTyped.get(base);
// Debug.printDbg(IDalvikTyper.DEBUG, "type of local1: ", t, " ", t.getClass());
Type elementType = null;
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
elementType = at.getArrayElementType();
} else {
continue;
}
if (!localTyped.containsKey(rightLocal)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "set type ", elementType, " to local ", r);
rightLocal.setType(elementType);
setLocalTyped(rightLocal, elementType);
}
// Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
constraints.remove(c);
update = true;
break;
}
} else if (l instanceof Local && r instanceof ArrayRef) {
Local leftLocal = (Local) l;
ArrayRef ar = (ArrayRef) r;
Local base = (Local) ar.getBase();
if (localTyped.containsKey(base)) {
Type t = localTyped.get(base);
// Debug.printDbg(IDalvikTyper.DEBUG, "type of local2: ", t, " ", t.getClass());
Type elementType = null;
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
elementType = at.getArrayElementType();
} else {
continue;
}
if (!localTyped.containsKey(leftLocal)) {
// Debug.printDbg(IDalvikTyper.DEBUG, "set type ", elementType, " to local ", l);
leftLocal.setType(elementType);
setLocalTyped(leftLocal, elementType);
}
// Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
constraints.remove(c);
update = true;
break;
}
} else {
throw new RuntimeException("error: do not handling this kind of constraint: " + c);
}
}
if (!update)
break;
}
for (Unit u : b.getUnits()) {
if (!(u instanceof AssignStmt))
continue;
AssignStmt ass = (AssignStmt) u;
if (!(ass.getLeftOp() instanceof Local))
continue;
if (!(ass.getRightOp() instanceof UntypedConstant))
continue;
UntypedConstant uc = (UntypedConstant) ass.getRightOp();
ass.setRightOp(uc.defineType(localTyped.get(ass.getLeftOp())));
}
//
for (Constraint c : constraints) {
// Debug.printDbg(IDalvikTyper.DEBUG, "current constraint: ", c);
Value l = c.l.getValue();
Value r = c.r.getValue();
if (l instanceof Local && r instanceof Constant) {
if (r instanceof UntypedIntOrFloatConstant) {
UntypedIntOrFloatConstant cst = (UntypedIntOrFloatConstant) r;
Value newValue = null;
if (cst.value != 0) {
// Debug.printDbg(IDalvikTyper.DEBUG, "[untyped constaints] set type int to non zero constant: ", c, " = ", cst.value);
newValue = cst.toIntConstant();
} else {
// check if used in cast, just in case...
for (Unit u : b.getUnits()) {
for (ValueBox vb1 : u.getUseBoxes()) {
Value v1 = vb1.getValue();
if (v1 == l) {
// Debug.printDbg("local used in ", u);
if (u instanceof AssignStmt) {
AssignStmt a = (AssignStmt) u;
Value right = a.getRightOp();
if (right instanceof CastExpr) {
newValue = NullConstant.v();
} else {
newValue = cst.toIntConstant();
}
} else if (u instanceof IfStmt) {
// TODO check this better
newValue = cst.toIntConstant();
}
}
}
}
}
if (newValue == null) {
throw new RuntimeException("error: no type found for local: " + l);
}
c.r.setValue(newValue);
} else if (r instanceof UntypedLongOrDoubleConstant) {
// Debug.printDbg(IDalvikTyper.DEBUG, "[untyped constaints] set type long to constant: ", c);
Value newValue = ((UntypedLongOrDoubleConstant) r).toLongConstant();
c.r.setValue(newValue);
}
}
}
// fix untypedconstants which have flown to an array index
for (Unit u : b.getUnits()) {
StmtSwitch sw = new StmtSwitch() {
@Override
public void caseBreakpointStmt(BreakpointStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
changeUntypedConstantsInInvoke(stmt.getInvokeExpr());
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
if (stmt.getRightOp() instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) stmt.getRightOp();
if (nae.getSize() instanceof UntypedConstant) {
UntypedIntOrFloatConstant uc = (UntypedIntOrFloatConstant) nae.getSize();
nae.setSize(uc.defineType(IntType.v()));
}
} else if (stmt.getRightOp() instanceof UntypedConstant) {
UntypedConstant uc = (UntypedConstant) stmt.getRightOp();
Value l = stmt.getLeftOp();
Type lType = null;
if (l instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) l;
Local baseLocal = (Local) ar.getBase();
ArrayType arrayType = (ArrayType) localTyped.get(baseLocal);
lType = arrayType.getElementType();
} else {
lType = l.getType();
}
stmt.setRightOp(uc.defineType(lType));
} else if (stmt.getRightOp() instanceof InvokeExpr) {
changeUntypedConstantsInInvoke((InvokeExpr) stmt.getRightOp());
}
if (!stmt.containsArrayRef()) {
return;
}
ArrayRef ar = stmt.getArrayRef();
if ((ar.getIndex() instanceof UntypedConstant)) {
UntypedIntOrFloatConstant uc = (UntypedIntOrFloatConstant) ar.getIndex();
ar.setIndex(uc.toIntConstant());
}
if (stmt.getLeftOp() instanceof ArrayRef && stmt.getRightOp() instanceof UntypedConstant) {
UntypedConstant uc = (UntypedConstant) stmt.getRightOp();
Local baseLocal = (Local) stmt.getArrayRef().getBase();
ArrayType lType = (ArrayType) localTyped.get(baseLocal);
Type elemType = lType.getElementType();
stmt.setRightOp(uc.defineType(elemType));
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseGotoStmt(GotoStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseIfStmt(IfStmt stmt) {
Value c = stmt.getCondition();
if (c instanceof BinopExpr) {
BinopExpr be = (BinopExpr) c;
Value op1 = be.getOp1();
Value op2 = be.getOp2();
if (op1 instanceof UntypedConstant || op2 instanceof UntypedConstant) {
if (op1 instanceof Local) {
Type t = localTyped.get(op1);
// Debug.printDbg("if op1 type: ", t);
UntypedConstant uc = (UntypedConstant) op2;
be.setOp2(uc.defineType(t));
} else if (op2 instanceof Local) {
Type t = localTyped.get(op2);
// Debug.printDbg("if op2 type: ", t);
UntypedConstant uc = (UntypedConstant) op1;
be.setOp1(uc.defineType(t));
} else if (op1 instanceof UntypedConstant && op2 instanceof UntypedConstant) {
if (op1 instanceof UntypedIntOrFloatConstant && op2 instanceof UntypedIntOrFloatConstant) {
UntypedIntOrFloatConstant uc1 = (UntypedIntOrFloatConstant) op1;
UntypedIntOrFloatConstant uc2 = (UntypedIntOrFloatConstant) op2;
// to int or float, it does not matter
be.setOp1(uc1.toIntConstant());
be.setOp2(uc2.toIntConstant());
} else if (op1 instanceof UntypedLongOrDoubleConstant && op2 instanceof UntypedLongOrDoubleConstant) {
UntypedLongOrDoubleConstant uc1 = (UntypedLongOrDoubleConstant) op1;
UntypedLongOrDoubleConstant uc2 = (UntypedLongOrDoubleConstant) op2;
// to long or double, it does not matter
be.setOp1(uc1.toLongConstant());
be.setOp2(uc2.toLongConstant());
} else {
throw new RuntimeException("error: expected same type of untyped constants. Got " + stmt);
}
} else if (op1 instanceof UntypedConstant || op2 instanceof UntypedConstant) {
if (op1 instanceof UntypedConstant) {
UntypedConstant uc = (UntypedConstant) op1;
be.setOp1(uc.defineType(op2.getType()));
} else if (op2 instanceof UntypedConstant) {
UntypedConstant uc = (UntypedConstant) op2;
be.setOp2(uc.defineType(op1.getType()));
}
} else {
throw new RuntimeException("error: expected local/untyped untyped/local or untyped/untyped. Got " + stmt);
}
}
} else if (c instanceof UnopExpr) {
} else {
throw new RuntimeException("error: expected binop or unop. Got " + stmt);
}
}
@Override
public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseNopStmt(NopStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseRetStmt(RetStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
if (stmt.getOp() instanceof UntypedConstant) {
UntypedConstant uc = (UntypedConstant) stmt.getOp();
Type type = b.getMethod().getReturnType();
stmt.setOp(uc.defineType(type));
}
}
@Override
public void caseReturnVoidStmt(ReturnVoidStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseTableSwitchStmt(TableSwitchStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void caseThrowStmt(ThrowStmt stmt) {
// TODO Auto-generated method stub
}
@Override
public void defaultCase(Object obj) {
// TODO Auto-generated method stub
}
};
u.apply(sw);
}
// fix untyped constants remaining
// Debug.printDbg("assignTypes: after: \n", b);
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class DavaBody method copy_Body.
/*
* Copy and patch a GrimpBody so that it can be used to output Java.
*/
private void copy_Body(Body body) {
if (!(body instanceof GrimpBody))
throw new RuntimeException("You can only create a DavaBody from a GrimpBody!");
GrimpBody grimpBody = (GrimpBody) body;
/*
* Import body contents from Grimp.
*/
{
HashMap<Switchable, Switchable> bindings = new HashMap<Switchable, Switchable>();
HashMap<Unit, Unit> reverse_binding = new HashMap<Unit, Unit>();
// Clone units in body's statement list
for (Unit original : grimpBody.getUnits()) {
Unit copy = (Unit) original.clone();
// Add cloned unit to our unitChain.
getUnits().addLast(copy);
// Build old <-> new map to be able to patch up references to other units
// within the cloned units. (these are still refering to the original
// unit objects).
bindings.put(original, copy);
reverse_binding.put(copy, original);
}
// patch up the switch statments
for (Unit u : getUnits()) {
Stmt s = (Stmt) u;
if (s instanceof TableSwitchStmt) {
TableSwitchStmt ts = (TableSwitchStmt) s;
TableSwitchStmt original_switch = (TableSwitchStmt) reverse_binding.get(u);
ts.setDefaultTarget((Unit) bindings.get(original_switch.getDefaultTarget()));
LinkedList<Unit> new_target_list = new LinkedList<Unit>();
int target_count = ts.getHighIndex() - ts.getLowIndex() + 1;
for (int i = 0; i < target_count; i++) new_target_list.add((Unit) bindings.get(original_switch.getTarget(i)));
ts.setTargets(new_target_list);
}
if (s instanceof LookupSwitchStmt) {
LookupSwitchStmt ls = (LookupSwitchStmt) s;
LookupSwitchStmt original_switch = (LookupSwitchStmt) reverse_binding.get(u);
ls.setDefaultTarget((Unit) bindings.get(original_switch.getDefaultTarget()));
Unit[] new_target_list = new Unit[original_switch.getTargetCount()];
for (int i = 0; i < original_switch.getTargetCount(); i++) new_target_list[i] = (Unit) (bindings.get(original_switch.getTarget(i)));
ls.setTargets(new_target_list);
ls.setLookupValues(original_switch.getLookupValues());
}
}
// Clone locals.
for (Local original : grimpBody.getLocals()) {
Local copy = Dava.v().newLocal(original.getName(), original.getType());
getLocals().add(copy);
// Build old <-> new mapping.
bindings.put(original, copy);
}
// Patch up references within units using our (old <-> new) map.
for (UnitBox box : getAllUnitBoxes()) {
Unit newObject, oldObject = box.getUnit();
// it's clone.
if ((newObject = (Unit) bindings.get(oldObject)) != null)
box.setUnit(newObject);
}
// backpatch all local variables.
for (ValueBox vb : getUseAndDefBoxes()) {
if (vb.getValue() instanceof Local)
vb.setValue((Value) bindings.get(vb.getValue()));
}
// clone the traps
for (Trap originalTrap : grimpBody.getTraps()) {
Trap cloneTrap = (Trap) originalTrap.clone();
Unit handlerUnit = (Unit) bindings.get(originalTrap.getHandlerUnit());
cloneTrap.setHandlerUnit(handlerUnit);
cloneTrap.setBeginUnit((Unit) bindings.get(originalTrap.getBeginUnit()));
cloneTrap.setEndUnit((Unit) bindings.get(originalTrap.getEndUnit()));
getTraps().add(cloneTrap);
}
}
/*
* Add one level of indirection to "if", "switch", and exceptional control flow.
* This allows for easy handling of breaks, continues and exceptional loops.
*/
{
PatchingChain<Unit> units = getUnits();
Iterator<Unit> it = units.snapshotIterator();
while (it.hasNext()) {
Unit u = it.next();
Stmt s = (Stmt) u;
if (s instanceof IfStmt) {
IfStmt ifs = (IfStmt) s;
JGotoStmt jgs = new JGotoStmt((Unit) units.getSuccOf(u));
units.insertAfter(jgs, u);
JGotoStmt jumper = new JGotoStmt((Unit) ifs.getTarget());
units.insertAfter(jumper, jgs);
ifs.setTarget((Unit) jumper);
} else if (s instanceof TableSwitchStmt) {
TableSwitchStmt tss = (TableSwitchStmt) s;
int targetCount = tss.getHighIndex() - tss.getLowIndex() + 1;
for (int i = 0; i < targetCount; i++) {
JGotoStmt jgs = new JGotoStmt((Unit) tss.getTarget(i));
units.insertAfter(jgs, tss);
tss.setTarget(i, (Unit) jgs);
}
JGotoStmt jgs = new JGotoStmt((Unit) tss.getDefaultTarget());
units.insertAfter(jgs, tss);
tss.setDefaultTarget((Unit) jgs);
} else if (s instanceof LookupSwitchStmt) {
LookupSwitchStmt lss = (LookupSwitchStmt) s;
for (int i = 0; i < lss.getTargetCount(); i++) {
JGotoStmt jgs = new JGotoStmt((Unit) lss.getTarget(i));
units.insertAfter(jgs, lss);
lss.setTarget(i, (Unit) jgs);
}
JGotoStmt jgs = new JGotoStmt((Unit) lss.getDefaultTarget());
units.insertAfter(jgs, lss);
lss.setDefaultTarget((Unit) jgs);
}
}
for (Trap t : getTraps()) {
JGotoStmt jgs = new JGotoStmt((Unit) t.getHandlerUnit());
units.addLast(jgs);
t.setHandlerUnit((Unit) jgs);
}
}
/*
* Fix up the grimp representations of statements so they can be compiled as java.
*/
{
for (Local l : getLocals()) {
Type t = l.getType();
if (t instanceof RefType) {
RefType rt = (RefType) t;
String className = rt.getSootClass().toString();
String packageName = rt.getSootClass().getJavaPackageName();
String classPackageName = packageName;
if (className.lastIndexOf('.') > 0) {
// 0 doesnt make sense
classPackageName = className.substring(0, className.lastIndexOf('.'));
}
if (!packageName.equals(classPackageName))
throw new DecompilationException("Unable to retrieve package name for identifier. Please report to developer.");
addToImportList(className);
// addPackage(rt.getSootClass().getJavaPackageName());
}
}
for (Unit u : getUnits()) {
Stmt s = (Stmt) u;
if (s instanceof IfStmt)
javafy(((IfStmt) s).getConditionBox());
else if (s instanceof ThrowStmt)
javafy(((ThrowStmt) s).getOpBox());
else if (s instanceof TableSwitchStmt)
javafy(((TableSwitchStmt) s).getKeyBox());
else if (s instanceof LookupSwitchStmt)
javafy(((LookupSwitchStmt) s).getKeyBox());
else if (s instanceof MonitorStmt)
javafy(((MonitorStmt) s).getOpBox());
else if (s instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) s;
javafy(ds.getRightOpBox());
javafy(ds.getLeftOpBox());
if (ds.getRightOp() instanceof IntConstant)
ds.getRightOpBox().setValue(DIntConstant.v(((IntConstant) ds.getRightOp()).value, ds.getLeftOp().getType()));
} else if (s instanceof ReturnStmt) {
ReturnStmt rs = (ReturnStmt) s;
if (rs.getOp() instanceof IntConstant)
rs.getOpBox().setValue(DIntConstant.v(((IntConstant) rs.getOp()).value, body.getMethod().getReturnType()));
else
javafy(rs.getOpBox());
} else if (s instanceof InvokeStmt)
javafy(((InvokeStmt) s).getInvokeExprBox());
}
}
/*
* Convert references to "this" and parameters.
*/
{
for (Unit u : getUnits()) {
Stmt s = (Stmt) u;
if (s instanceof IdentityStmt) {
IdentityStmt ids = (IdentityStmt) s;
Value ids_rightOp = ids.getRightOp();
Value ids_leftOp = ids.getLeftOp();
if ((ids_leftOp instanceof Local) && (ids_rightOp instanceof ThisRef)) {
Local thisLocal = (Local) ids_leftOp;
thisLocals.add(thisLocal);
thisLocal.setName("this");
}
}
if (s instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) s;
Value rightOp = ds.getRightOp();
if (rightOp instanceof ParameterRef)
pMap.put(((ParameterRef) rightOp).getIndex(), ds.getLeftOp());
if (rightOp instanceof CaughtExceptionRef)
caughtrefs.add((CaughtExceptionRef) rightOp);
}
}
}
/*
* Fix up the calls to other constructors. Note, this is seriously underbuilt.
*/
{
for (Unit u : getUnits()) {
Stmt s = (Stmt) u;
if (s instanceof InvokeStmt) {
InvokeStmt ivs = (InvokeStmt) s;
Value ie = ivs.getInvokeExpr();
if (ie instanceof InstanceInvokeExpr) {
InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
Value base = iie.getBase();
if ((base instanceof Local) && (((Local) base).getName().equals("this"))) {
SootMethodRef m = iie.getMethodRef();
String name = m.name();
if ((name.equals(SootMethod.constructorName)) || (name.equals(SootMethod.staticInitializerName))) {
if (constructorUnit != null)
throw new RuntimeException("More than one candidate for constructor found.");
constructorExpr = iie;
constructorUnit = (Unit) s;
}
}
}
}
}
}
}
Aggregations