Проблема в том, что я хотел бы вставить специальное выражение вызова в мой код, не присваивая его значению, например, в jimple ему назначается $ r2.
Ошибка в том, что я использую unit.insertBefore (). Это приводит к тому, что я не могу вставить его без использования присваивания для выражения вызова.
Есть ли способ обойти это?
Проблема находится в строке 92 файла Test2.java, представленного ниже.
Любая помощь будет принята с благодарностью. Спасибо.
ФАЙЛ: Test2.java
package dfa;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import soot.options.Options;
import soot.*;
import soot.jimple.AssignStmt;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.InvokeStmt;
import soot.jimple.Jimple;
import soot.jimple.SpecialInvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.VirtualInvokeExpr;
import soot.jimple.toolkits.callgraph.Units;
import soot.toolkits.graph.BriefUnitGraph;
import soot.toolkits.graph.UnitGraph;
import soot.jimple.AssignStmt;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.Jimple;
import soot.jimple.Stmt;
import soot.jimple.StringConstant;
import soot.toolkits.graph.*;
import soot.util.Chain;
public class Testing2 {
public static void main(String[] args) {
soot.G.reset();
Options.v().set_process_dir(Collections.singletonList("/home/sean/Projects/Soot/HelloWorld.jar"));
Options.v().set_src_prec(Options.src_prec_java);
Options.v().set_whole_program(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_output_format(Options.output_format_jimple);
Options.v().setPhaseOption("cg.spark", "verbose:false");
Scene.v().loadNecessaryClasses();
SootClass entryClass = Scene.v().getSootClassUnsafe("HelloWorld");
SootMethod sMethod = entryClass.getMethodByNameUnsafe("main");
Options.v().set_main_class(sMethod.getSignature());
Scene.v().setEntryPoints(Collections.singletonList(sMethod));
PackManager.v().runPacks();
Body body = sMethod.getActiveBody();
UnitGraph graph = new BriefUnitGraph(body);
// Perform LV Analysis on the Graph
LiveVariableAnalysis analysis = new LiveVariableAnalysis(graph);
// Print live variables at the entry and exit of each node
Iterator<Unit> unitIt = graph.iterator();
analysis.getFlowBefore(unitIt.next());
Stmt stm =null;
Chain units = graph.getBody().getUnits();
Set<Value> activeList = new HashSet<>(); //USED FOR ACTIVE DATA
Value base = null;
//WANT TO ITERATE THROUGH EACH UNIT WHICH HAS STATEMENTS ASSOCIATED WITH EACH UNIT
while (unitIt.hasNext()) {
Unit s = unitIt.next();
stm = (Stmt)s;
System.out.println("Statement: " + stm);
if (stm.containsInvokeExpr()) {
System.out.println("CONTAINS INVOKE EXPR");
activeList.add(stm.getInvokeExpr().getArg(0));
System.out.println(stm.getInvokeExpr().getArgs());
InvokeExpr ie = stm.getInvokeExpr();
InstanceInvokeExpr iie = (InstanceInvokeExpr)ie;
base = iie.getBase();
}
}
for(Value s : activeList)
{
System.out.println("ACTIVE LIST IS: \t"+s);
LinkedList<Value> args2 = new LinkedList<Value>();
args2.add(s);
Local tmp = Jimple.v().newLocal("$r"+Integer.toString(graph.getBody().getLocalCount()), RefType.v("java.io.PrintStream"));
graph.getBody().getLocals().add(tmp);
SootMethodRef setRef = Scene.v().getMethod("<java.io.PrintStream: void println(java.lang.String)>").makeRef();
VirtualInvokeExpr vr = Jimple.v().newVirtualInvokeExpr((Local) base, setRef, args2);
AssignStmt a = Jimple.v().newAssignStmt(tmp, vr);
vr = Jimple.v().newVirtualInvokeExpr((Local)a.getLeftOp(), setRef, args2);
a = Jimple.v().newAssignStmt(tmp, vr);
units.insertBefore(a,stm);
SpecialInvokeExpr vr2 = Jimple.v().newSpecialInvokeExpr((Local) base, setRef, args2);
AssignStmt a2 = Jimple.v().newAssignStmt(tmp, vr2);
vr2 = Jimple.v().newSpecialInvokeExpr((Local)a2.getLeftOp(), setRef, args2);
System.out.println("TESTING: " + vr2);
a2 = Jimple.v().newAssignStmt(tmp, vr2);
// units.insertBefore(a2, stm);
}
//WANT TO VIEW THE CODE FOR THE UNIT
System.out.println();
System.out.println("UNIT 1:");
Iterator<Unit> unitIt1 = graph.iterator();
while (unitIt1.hasNext()) {
Unit s = unitIt1.next();
stm = (Stmt)s;
System.out.println("\t"+stm);
if (stm.containsInvokeExpr()) {
InvokeExpr ie = stm.getInvokeExpr();
InstanceInvokeExpr iie = (InstanceInvokeExpr)ie;
base = iie.getBase();
}
}
// PRINT OUT WHOLE BODY NOW
System.out.println("Body: ");
System.out.println(body);
}
}
ФАЙЛ: LiveVariableAnalysis.java
package dfa;
import soot.Local;
import soot.Unit;
import soot.ValueBox;
import soot.toolkits.graph.DirectedGraph;
import soot.toolkits.scalar.BackwardFlowAnalysis;
import soot.toolkits.scalar.FlowSet;
import soot.toolkits.scalar.ArraySparseSet;
class LiveVariableAnalysis
extends BackwardFlowAnalysis<Unit, FlowSet<Local>>
{
private FlowSet<Local> emptySet;
public LiveVariableAnalysis(DirectedGraph g) {
// First obligation
super(g);
emptySet = new ArraySparseSet<Local>();
// Second obligation
doAnalysis();
}
// This method performs the joining of successor nodes
// Since live variables is a may analysis we join by union
@Override
protected void merge(FlowSet<Local> inSet1,
FlowSet<Local> inSet2,
FlowSet<Local> outSet)
{
inSet1.union(inSet2, outSet);
}
@Override
protected void copy(FlowSet<Local> srcSet,
FlowSet<Local> destSet)
{
srcSet.copy(destSet);
}
// Used to initialize the in and out sets for each node. In
// our case we build up the sets as we go, so we initialize
// with the empty set.
@Override
protected FlowSet<Local> newInitialFlow() {
return emptySet.clone();
}
// Returns FlowSet representing the initial set of the entry
// node. In our case the entry node is the last node and it
// should contain the empty set.
@Override
protected FlowSet<Local> entryInitialFlow() {
return emptySet.clone();
}
// Sets the outSet with the values that flow through the
// node from the inSet based on reads/writes at the node
// Set the outSet (entry) based on the inSet (exit)
@Override
protected void flowThrough(FlowSet<Local> inSet,
Unit node, FlowSet<Local> outSet) {
// outSet is the set at enrty of the node
// inSet is the set at exit of the node
// out <- (in - write(node)) union read(node)
// out <- (in - write(node))
FlowSet writes = (FlowSet)emptySet.clone();
for (ValueBox def: node.getUseAndDefBoxes()) {
if (def.getValue() instanceof Local) {
writes.add(def.getValue());
}
}
inSet.difference(writes, outSet);
// out <- out union read(node)
for (ValueBox use: node.getUseBoxes()) {
if (use.getValue() instanceof Local) {
outSet.add((Local) use.getValue());
}
}
}
}