use of soot.UnitBox in project soot by Sable.
the class Walker method outAGotoStatement.
public void outAGotoStatement(AGotoStatement node) {
String targetLabel = (String) mProductions.removeLast();
UnitBox box = Jimple.v().newStmtBox(null);
Unit branch = Jimple.v().newGotoStmt(box);
addBoxToPatch(targetLabel, box);
mProductions.addLast(branch);
}
use of soot.UnitBox 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;
}
}
}
}
}
}
}
use of soot.UnitBox in project soot by Sable.
the class UnitGraph method buildUnexceptionalEdges.
/**
* Utility method for <tt>UnitGraph</tt> constructors. It computes the edges
* corresponding to unexceptional control flow.
*
* @param unitToSuccs
* A {@link Map} from {@link Unit}s to {@link List}s of
* {@link Unit}s. This is an ``out parameter''; callers must pass
* an empty {@link Map}. <tt>buildUnexceptionalEdges</tt> will
* add a mapping for every <tt>Unit</tt> in the body to a list of
* its unexceptional successors.
*
* @param unitToPreds
* A {@link Map} from {@link Unit}s to {@link List}s of
* {@link Unit}s. This is an ``out parameter''; callers must pass
* an empty {@link Map}. <tt>buildUnexceptionalEdges</tt> will
* add a mapping for every <tt>Unit</tt> in the body to a list of
* its unexceptional predecessors.
*/
protected void buildUnexceptionalEdges(Map<Unit, List<Unit>> unitToSuccs, Map<Unit, List<Unit>> unitToPreds) {
Iterator<Unit> unitIt = unitChain.iterator();
Unit currentUnit, nextUnit;
nextUnit = unitIt.hasNext() ? (Unit) unitIt.next() : null;
while (nextUnit != null) {
currentUnit = nextUnit;
nextUnit = unitIt.hasNext() ? (Unit) unitIt.next() : null;
ArrayList<Unit> successors = new ArrayList<Unit>();
if (currentUnit.fallsThrough()) {
// Add the next unit as the successor
if (nextUnit != null) {
successors.add(nextUnit);
List<Unit> preds = unitToPreds.get(nextUnit);
if (preds == null) {
preds = new ArrayList<Unit>();
unitToPreds.put(nextUnit, preds);
}
preds.add(currentUnit);
}
}
if (currentUnit.branches()) {
for (UnitBox targetBox : currentUnit.getUnitBoxes()) {
Unit target = targetBox.getUnit();
// target it falls through to, so we screen for duplicates:
if (!successors.contains(target)) {
successors.add(target);
List<Unit> preds = unitToPreds.get(target);
if (preds == null) {
preds = new ArrayList<Unit>();
unitToPreds.put(target, preds);
}
preds.add(currentUnit);
}
}
}
// Store away successors
if (!successors.isEmpty()) {
successors.trimToSize();
unitToSuccs.put(currentUnit, successors);
}
}
}
use of soot.UnitBox in project soot by Sable.
the class HashChain method insertOnEdge.
/**
* Inserts instrumentation in a manner such that the resulting control flow
* graph (CFG) of the program will contain <code>toInsert</code> on an edge
* that is defined by <code>point_source</code> and
* <code>point_target</code>.
*
* @param toInsert
* instrumentation to be added in the Chain
* @param point_src
* the source point of an edge in CFG
* @param point_tgt
* the target point of an edge
*/
public void insertOnEdge(Collection<? extends E> toInsert, E point_src, E point_tgt) {
if (toInsert == null)
throw new RuntimeException("Bad idea! You tried to insert " + "a null object into a Chain!");
// is null
if (point_src == null && point_tgt != null) {
((Unit) point_tgt).redirectJumpsToThisTo((Unit) toInsert.iterator().next());
insertBefore(toInsert, point_tgt);
return;
}
// is null
if (point_src != null && point_tgt == null) {
insertAfter(toInsert, point_src);
return;
}
// Throw an exception if both source and target is null
if (point_src == null && point_tgt == null) {
throw new RuntimeException("insertOnEdge failed! Both source and target points are null.");
}
// 2- Insert 'toInsert' after 'source' in Chain
if (getSuccOf(point_src) == point_tgt) {
List<UnitBox> boxes = ((Unit) point_src).getUnitBoxes();
for (UnitBox box : boxes) {
if (box.getUnit() == point_tgt) {
box.setUnit((Unit) toInsert.iterator().next());
}
}
insertAfter(toInsert, point_src);
return;
}
// If the target is not right after the source in chain then,
// 1- Redirect all jumps (if any) from 'source' to 'target', to
// 'toInsert[0]'
// (source->target) ==> (source->toInsert[0])
// 1.1- if there are no jumps from source to target, then such an edge
// does not exist. Throw an exception.
// 2- Insert 'toInsert' before 'target' in Chain
// 3- If required, add a 'goto target' statement so that no other edge
// executes 'toInsert'
boolean validEdgeFound = false;
E originalPred = getPredOf(point_tgt);
List<UnitBox> boxes = ((Unit) point_src).getUnitBoxes();
for (UnitBox box : boxes) {
if (box.getUnit() == point_tgt) {
if (point_src instanceof GotoStmt) {
box.setUnit((Unit) toInsert.iterator().next());
insertAfter(toInsert, point_src);
E goto_unit = (E) new JGotoStmt((Unit) point_tgt);
if (toInsert instanceof List) {
List l = ((List) toInsert);
insertAfter(goto_unit, (E) l.get(l.size() - 1));
} else
insertAfter(goto_unit, (E) toInsert.toArray()[toInsert.size() - 1]);
return;
}
box.setUnit((Unit) toInsert.iterator().next());
validEdgeFound = true;
}
}
if (validEdgeFound) {
insertBefore(toInsert, point_tgt);
if (originalPred != point_src) {
if (originalPred instanceof GotoStmt)
return;
E goto_unit = (E) new JGotoStmt((Unit) point_tgt);
insertBefore(goto_unit, (E) toInsert.iterator().next());
}
return;
}
// The following code handles such scenarios.
if (getSuccOf(point_src) instanceof GotoStmt) {
if (((Unit) getSuccOf(point_src)).getUnitBoxes().get(0).getUnit() == point_tgt) {
((Unit) getSuccOf(point_src)).redirectJumpsToThisTo((Unit) toInsert.iterator().next());
insertBefore(toInsert, getSuccOf(point_src));
return;
}
}
// Return an exception.
throw new RuntimeException("insertOnEdge failed! No such edge found. The edge on which you want to insert an instrumentation is invalid.");
}
use of soot.UnitBox in project soot by Sable.
the class DexReturnInliner method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
Set<Unit> duplicateIfTargets = getFallThroughReturns(body);
Iterator<Unit> it = body.getUnits().snapshotIterator();
boolean mayBeMore = false;
Unit last = null;
do {
mayBeMore = false;
while (it.hasNext()) {
Unit u = it.next();
if (u instanceof GotoStmt) {
GotoStmt gtStmt = (GotoStmt) u;
if (isInstanceofReturn(gtStmt.getTarget())) {
Stmt stmt = (Stmt) gtStmt.getTarget().clone();
for (Trap t : body.getTraps()) for (UnitBox ubox : t.getUnitBoxes()) if (ubox.getUnit() == u)
ubox.setUnit(stmt);
while (!u.getBoxesPointingToThis().isEmpty()) u.getBoxesPointingToThis().get(0).setUnit(stmt);
// the cloned return stmt gets the tags of u
stmt.addAllTagsOf(u);
body.getUnits().swapWith(u, stmt);
mayBeMore = true;
}
} else if (u instanceof IfStmt) {
IfStmt ifstmt = (IfStmt) u;
Unit t = ifstmt.getTarget();
if (isInstanceofReturn(t)) {
// once, otherwise we will end up with unused copies
if (duplicateIfTargets == null)
duplicateIfTargets = new HashSet<Unit>();
if (!duplicateIfTargets.add(t)) {
Unit newTarget = (Unit) t.clone();
body.getUnits().addLast(newTarget);
ifstmt.setTarget(newTarget);
}
}
} else if (isInstanceofReturn(u)) {
// the original return stmt gets the tags of its predecessor
if (last != null) {
u.removeAllTags();
u.addAllTagsOf(last);
}
}
last = u;
}
} while (mayBeMore);
}
Aggregations