use of soot.ValueBox in project soot by Sable.
the class XMLPrinter method printStatementsInBody.
/**
* Prints the given <code>JimpleBody</code> to the specified <code>PrintWriter</code>.
*/
private void printStatementsInBody(Body body, java.io.PrintWriter out) {
LabeledUnitPrinter up = new NormalUnitPrinter(body);
Map<Unit, String> stmtToName = up.labels();
Chain<Unit> units = body.getUnits();
// UnitGraph unitGraph = new soot.toolkits.graph.BriefUnitGraph( body );
ExceptionalUnitGraph exceptionalUnitGraph = new soot.toolkits.graph.ExceptionalUnitGraph(body);
// include any analysis which will be used in the xml output
LiveLocals sll = new SimpleLiveLocals(exceptionalUnitGraph);
// iterate through each statement
String cleanMethodName = cleanMethod(body.getMethod().getName());
Iterator<Unit> unitIt = units.iterator();
Unit currentStmt = null;
String currentLabel = "default";
long statementCount = 0;
long labelCount = 0;
long labelID = 0;
// lists
Vector<String> useList = new Vector<String>();
Vector<Vector<Long>> useDataList = new Vector<Vector<Long>>();
Vector<String> defList = new Vector<String>();
Vector<Vector<Long>> defDataList = new Vector<Vector<Long>>();
Vector<Vector<String>> paramData = new Vector<Vector<String>>();
Vector<XMLLabel> xmlLabelsList = new Vector<XMLLabel>();
long maxStmtCount = 0;
/*
// for invokes, add a list of potential targets
if (!Scene.v().hasActiveInvokeGraph()) {
InvokeGraphBuilder.v().transform("jil.igb");
}
// build an invoke graph based on class hiearchy analysis
InvokeGraph igCHA = Scene.v().getActiveInvokeGraph();
// build an invoke graph based on variable type analysis
InvokeGraph igVTA = Scene.v().getActiveInvokeGraph();
try {
VariableTypeAnalysis vta = null;
int VTApasses = 1;
//Options.getInt( PackManager.v().getPhaseOptions( "jil.igb" ), "VTA-passes" );
for (int i = 0; i < VTApasses; i++) {
vta = new VariableTypeAnalysis(igVTA);
vta.trimActiveInvokeGraph();
igVTA.refreshReachableMethods();
}
} catch (RuntimeException re) {
// this will fail if the --analyze-context flag is not specified
// logger.debug(""+ "JIL VTA FAILED: " + re );
igVTA = null;
}
*/
// add method node
XMLNode methodNode = xmlNode.addChild("method", new String[] { "name", "returntype", "class" }, new String[] { cleanMethodName, body.getMethod().getReturnType().toString(), body.getMethod().getDeclaringClass().getName().toString() });
String declarationStr = body.getMethod().getDeclaration().toString().trim();
methodNode.addChild("declaration", toCDATA(declarationStr), new String[] { "length" }, new String[] { declarationStr.length() + "" });
// create references to parameters, locals, labels, stmts nodes
XMLNode parametersNode = methodNode.addChild("parameters", new String[] { "method" }, new String[] { cleanMethodName });
XMLNode localsNode = methodNode.addChild("locals");
XMLNode labelsNode = methodNode.addChild("labels");
XMLNode stmtsNode = methodNode.addChild("statements");
// create default label
XMLLabel xmlLabel = new XMLLabel(labelCount, cleanMethodName, currentLabel);
labelsNode.addChild("label", new String[] { "id", "name", "method" }, new String[] { (labelCount++) + "", currentLabel, cleanMethodName });
// for each statement...
while (unitIt.hasNext()) {
currentStmt = (Unit) unitIt.next();
// new label
if (stmtToName.containsKey(currentStmt)) {
currentLabel = stmtToName.get(currentStmt).toString();
// fill in the stmt count for the previous label
// index = xmlLabels.indexOf( "%s" );
// if( index != -1 )
// xmlLabels = xmlLabels.substring( 0, index ) + ( labelID ) + xmlLabels.substring( index + 2 );
// index = xmlLabels.indexOf( "%d" );
// if( index != -1 )
// xmlLabels = xmlLabels.substring( 0, index ) + new Float( ( new Float( labelID ).floatValue() / new Float( units.size() ).intValue() ) * 100.0 ).intValue() + xmlLabels.substring( index + 2 );
xmlLabel.stmtCount = labelID;
xmlLabel.stmtPercentage = new Float((new Float(labelID).floatValue() / new Float(units.size()).intValue()) * 100.0).longValue();
if (xmlLabel.stmtPercentage > maxStmtCount)
maxStmtCount = xmlLabel.stmtPercentage;
xmlLabelsList.addElement(xmlLabel);
// xmlLabel.clear();
xmlLabel = new XMLLabel(labelCount, cleanMethodName, currentLabel);
labelsNode.addChild("label", new String[] { "id", "name", "method" }, new String[] { labelCount + "", currentLabel, cleanMethodName });
labelCount++;
labelID = 0;
}
// examine each statement
XMLNode stmtNode = stmtsNode.addChild("statement", new String[] { "id", "label", "method", "labelid" }, new String[] { statementCount + "", currentLabel, cleanMethodName, labelID + "" });
XMLNode sootstmtNode = stmtNode.addChild("soot_statement", new String[] { "branches", "fallsthrough" }, new String[] { boolToString(currentStmt.branches()), boolToString(currentStmt.fallsThrough()) });
// uses for each statement
int j = 0;
Iterator<ValueBox> boxIt = currentStmt.getUseBoxes().iterator();
while (boxIt.hasNext()) {
ValueBox box = (ValueBox) boxIt.next();
if (box.getValue() instanceof Local) {
String local = cleanLocal(((Local) box.getValue()).toString());
sootstmtNode.addChild("uses", new String[] { "id", "local", "method" }, new String[] { j + "", local, cleanMethodName });
j++;
Vector<Long> tempVector = null;
int useIndex = useList.indexOf(local);
if (useIndex == -1) {
useDataList.addElement(tempVector);
useList.addElement(local);
useIndex = useList.indexOf(local);
}
if (useDataList.size() > useIndex) {
tempVector = useDataList.elementAt(useIndex);
if (tempVector == null) {
tempVector = new Vector<Long>();
}
tempVector.addElement(new Long(statementCount));
useDataList.setElementAt(tempVector, useIndex);
}
}
}
// defines for each statement
j = 0;
boxIt = currentStmt.getDefBoxes().iterator();
while (boxIt.hasNext()) {
ValueBox box = (ValueBox) boxIt.next();
if (box.getValue() instanceof Local) {
String local = cleanLocal(((Local) box.getValue()).toString());
sootstmtNode.addChild("defines", new String[] { "id", "local", "method" }, new String[] { j + "", local, cleanMethodName });
j++;
Vector<Long> tempVector = null;
int defIndex = defList.indexOf(local);
if (defIndex == -1) {
defDataList.addElement(tempVector);
defList.addElement(local);
defIndex = defList.indexOf(local);
}
if (defDataList.size() > defIndex) {
tempVector = defDataList.elementAt(defIndex);
if (tempVector == null) {
tempVector = new Vector<Long>();
}
tempVector.addElement(new Long(statementCount));
defDataList.setElementAt(tempVector, defIndex);
}
}
}
/*
// for invokes, add a list of potential targets
if (stmtCurrentStmt.containsInvokeExpr()) {
// default analysis is CHA
if (igCHA != null) {
try {
List targets = igCHA.getTargetsOf(stmtCurrentStmt);
XMLNode CHAinvoketargetsNode =
sootstmtNode.addChild(
"invoketargets",
new String[] { "analysis", "count" },
new String[] { "CHA", targets.size() + "" });
for (int i = 0; i < targets.size(); i++) {
SootMethod meth = (SootMethod) targets.get(i);
CHAinvoketargetsNode.addChild(
"target",
new String[] { "id", "class", "method" },
new String[] {
i + "",
meth.getDeclaringClass().getFullName(),
cleanMethod(meth.getName())});
}
} catch (RuntimeException re) {
//logger.debug(""+ "XML: " + re + " (" + stmtCurrentStmt + ")" );
}
}
// now try VTA, which will only work if the -a or --analyze-context switch is specified
if (igVTA != null) {
InvokeExpr ie =
(InvokeExpr) stmtCurrentStmt.getInvokeExpr();
if (!(ie instanceof StaticInvokeExpr)
&& !(ie instanceof SpecialInvokeExpr)) {
try {
List targets = igVTA.getTargetsOf(stmtCurrentStmt);
XMLNode VTAinvoketargetsNode =
sootstmtNode.addChild(
"invoketargets",
new String[] { "analysis", "count" },
new String[] {
"VTA",
targets.size() + "" });
for (int i = 0; i < targets.size(); i++) {
SootMethod meth = (SootMethod) targets.get(i);
VTAinvoketargetsNode.addChild(
"target",
new String[] { "id", "class", "method" },
new String[] {
i + "",
meth.getDeclaringClass().getFullName(),
cleanMethod(meth.getName())});
}
} catch (RuntimeException re) {
//logger.debug(""+ "XML: " + re + " (" + stmtCurrentStmt + ")" );
}
}
}
}
*/
// simple live locals
List<Local> liveLocalsIn = sll.getLiveLocalsBefore(currentStmt);
List<Local> liveLocalsOut = sll.getLiveLocalsAfter(currentStmt);
XMLNode livevarsNode = sootstmtNode.addChild("livevariables", new String[] { "incount", "outcount" }, new String[] { liveLocalsIn.size() + "", liveLocalsOut.size() + "" });
for (int i = 0; i < liveLocalsIn.size(); i++) {
livevarsNode.addChild("in", new String[] { "id", "local", "method" }, new String[] { i + "", cleanLocal(liveLocalsIn.get(i).toString()), cleanMethodName });
}
for (int i = 0; i < liveLocalsOut.size(); i++) {
livevarsNode.addChild("out", new String[] { "id", "local", "method" }, new String[] { i + "", cleanLocal(liveLocalsOut.get(i).toString()), cleanMethodName });
}
// parameters
for (int i = 0; i < body.getMethod().getParameterTypes().size(); i++) {
Vector<String> tempVec = new Vector<String>();
paramData.addElement(tempVec);
}
// parse any info from the statement code
currentStmt.toString(up);
String jimpleStr = up.toString().trim();
if (currentStmt instanceof soot.jimple.IdentityStmt && jimpleStr.indexOf("@parameter") != -1) {
// this line is a use of a parameter
String tempStr = jimpleStr.substring(jimpleStr.indexOf("@parameter") + 10);
if (tempStr.indexOf(":") != -1)
tempStr = tempStr.substring(0, tempStr.indexOf(":")).trim();
if (tempStr.indexOf(" ") != -1)
tempStr = tempStr.substring(0, tempStr.indexOf(" ")).trim();
int paramIndex = new Integer(tempStr).intValue();
Vector<String> tempVec = paramData.elementAt(paramIndex);
if (tempVec != null)
tempVec.addElement(Long.toString(statementCount));
paramData.setElementAt(tempVec, paramIndex);
}
// add plain jimple representation of each statement
sootstmtNode.addChild("jimple", toCDATA(jimpleStr), new String[] { "length" }, new String[] { (jimpleStr.length() + 1) + "" });
// increment statement counters
labelID++;
statementCount++;
}
// add count to statments
stmtsNode.addAttribute("count", statementCount + "");
// method parameters
parametersNode.addAttribute("count", body.getMethod().getParameterCount() + "");
for (int i = 0; i < body.getMethod().getParameterTypes().size(); i++) {
XMLNode paramNode = parametersNode.addChild("parameter", new String[] { "id", "type", "method", "name" }, new String[] { i + "", body.getMethod().getParameterTypes().get(i).toString(), cleanMethodName, "_parameter" + i });
XMLNode sootparamNode = paramNode.addChild("soot_parameter");
Vector<String> tempVec = paramData.elementAt(i);
for (int k = 0; k < tempVec.size(); k++) {
sootparamNode.addChild("use", new String[] { "id", "line", "method" }, new String[] { k + "", String.valueOf(tempVec.elementAt(k)) + "", cleanMethodName });
}
sootparamNode.addAttribute("uses", tempVec.size() + "");
}
/*
index = xmlLabels.indexOf( "%s" );
if( index != -1 )
xmlLabels = xmlLabels.substring( 0, index ) + ( labelID ) + xmlLabels.substring( index + 2 );
index = xmlLabels.indexOf( "%d" );
if( index != -1 )
xmlLabels = xmlLabels.substring( 0, index ) + new Float( ( new Float( labelID ).floatValue() / new Float( units.size() ).floatValue() ) * 100.0 ).intValue() + xmlLabels.substring( index + 2 );
*/
xmlLabel.stmtCount = labelID;
xmlLabel.stmtPercentage = new Float((new Float(labelID).floatValue() / new Float(units.size()).floatValue()) * 100.0).longValue();
if (xmlLabel.stmtPercentage > maxStmtCount)
maxStmtCount = xmlLabel.stmtPercentage;
xmlLabelsList.addElement(xmlLabel);
// print out locals
Collection<Local> locals = body.getLocals();
Iterator<Local> localsIterator = locals.iterator();
Vector<String> localTypes = new Vector<String>();
Vector<Vector<XMLNode>> typedLocals = new Vector<Vector<XMLNode>>();
Vector<Integer> typeCounts = new Vector<Integer>();
int j = 0;
int currentType = 0;
while (localsIterator.hasNext()) {
int useCount = 0;
int defineCount = 0;
Local localData = (Local) localsIterator.next();
String local = cleanLocal((String) localData.toString());
String localType = localData.getType().toString();
// collect the local types
if (!localTypes.contains(localType)) {
localTypes.addElement(localType);
typedLocals.addElement(new Vector<XMLNode>());
typeCounts.addElement(new Integer(0));
}
// create a reference to the local node
XMLNode localNode = new XMLNode("local", "", new String[] { "id", "method", "name", "type" }, new String[] { j + "", cleanMethodName, local, localType });
XMLNode sootlocalNode = localNode.addChild("soot_local");
currentType = 0;
for (int k = 0; k < localTypes.size(); k++) {
if (localType.equalsIgnoreCase(localTypes.elementAt(k))) {
currentType = k;
Integer tempInt = new Integer(typeCounts.elementAt(k).intValue() + 1);
typeCounts.setElementAt(tempInt, k);
break;
}
}
// add all uses to this local
for (int k = 0; k < useList.size(); k++) {
String query = useList.elementAt(k);
if (query.equalsIgnoreCase(local)) {
Vector<Long> tempVector = useDataList.elementAt(useList.indexOf(local));
for (int i = 0; i < tempVector.size(); i++) {
sootlocalNode.addChild("use", new String[] { "id", "line", "method" }, new String[] { i + "", ((Long) tempVector.elementAt(i)).toString(), cleanMethodName });
}
useCount = tempVector.size();
break;
}
}
// add all definitions to this local
for (int k = 0; k < defList.size(); k++) {
String query = (defList.elementAt(k));
if (query.equalsIgnoreCase(local)) {
Vector<Long> tempVector = defDataList.elementAt(defList.indexOf(local));
for (int i = 0; i < tempVector.size(); i++) {
sootlocalNode.addChild("definition", new String[] { "id", "line", "method" }, new String[] { i + "", ((Long) tempVector.elementAt(i)).toString(), cleanMethodName });
}
defineCount = tempVector.size();
break;
}
}
// add number of uses and defines to this local
sootlocalNode.addAttribute("uses", useCount + "");
sootlocalNode.addAttribute("defines", defineCount + "");
// create a list of locals sorted by type
Vector<XMLNode> list = typedLocals.elementAt(currentType);
list.addElement(localNode);
typedLocals.setElementAt(list, currentType);
// add local to locals node
localsNode.addChild((XMLNode) localNode.clone());
j++;
}
// add count to the locals node
localsNode.addAttribute("count", locals.size() + "");
// add types node to locals node, and each type with each local per type
XMLNode typesNode = localsNode.addChild("types", new String[] { "count" }, new String[] { localTypes.size() + "" });
for (int i = 0; i < localTypes.size(); i++) {
String type = localTypes.elementAt(i);
XMLNode typeNode = typesNode.addChild("type", new String[] { "id", "type", "count" }, new String[] { i + "", type, typeCounts.elementAt(i) + "" });
Vector<XMLNode> list = typedLocals.elementAt(i);
for (j = 0; j < list.size(); j++) {
typeNode.addChild(list.elementAt(j));
}
}
// add count attribute to labels node, and stmtcount, and stmtpercentage attributes to each label node
labelsNode.addAttribute("count", labelCount + "");
XMLNode current = labelsNode.child;
for (int i = 0; i < xmlLabelsList.size(); i++) {
XMLLabel tempLabel = xmlLabelsList.elementAt(i);
tempLabel.stmtPercentage = new Float((new Float(tempLabel.stmtPercentage).floatValue() / new Float(maxStmtCount).floatValue()) * 100.0).longValue();
if (current != null) {
current.addAttribute("stmtcount", tempLabel.stmtCount + "");
current.addAttribute("stmtpercentage", tempLabel.stmtPercentage + "");
current = current.next;
}
}
// Print out exceptions
statementCount = 0;
XMLNode exceptionsNode = methodNode.addChild("exceptions");
Iterator<Trap> trapIt = body.getTraps().iterator();
if (trapIt.hasNext()) {
while (trapIt.hasNext()) {
Trap trap = trapIt.next();
// catch java.io.IOException from label0 to label1 with label2;
XMLNode catchNode = exceptionsNode.addChild("exception", new String[] { "id", "method", "type" }, new String[] { (statementCount++) + "", cleanMethodName, Scene.v().quotedNameOf(trap.getException().getName()) });
catchNode.addChild("begin", new String[] { "label" }, new String[] { stmtToName.get(trap.getBeginUnit()).toString() });
catchNode.addChild("end", new String[] { "label" }, new String[] { stmtToName.get(trap.getEndUnit()).toString() });
catchNode.addChild("handler", new String[] { "label" }, new String[] { stmtToName.get(trap.getHandlerUnit()).toString() });
}
}
exceptionsNode.addAttribute("count", exceptionsNode.getNumberOfChildren() + "");
return;
}
use of soot.ValueBox in project soot by Sable.
the class LocalSplitter method internalTransform.
@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
if (Options.v().verbose())
logger.debug("[" + body.getMethod().getName() + "] Splitting locals...");
if (Options.v().time())
Timers.v().splitTimer.start();
if (Options.v().time())
Timers.v().splitPhase1Timer.start();
if (throwAnalysis == null)
throwAnalysis = Scene.v().getDefaultThrowAnalysis();
if (omitExceptingUnitEdges == false)
omitExceptingUnitEdges = Options.v().omit_excepting_unit_edges();
// Pack the locals for efficiency
final LocalBitSetPacker localPacker = new LocalBitSetPacker(body);
localPacker.pack();
// Go through the definitions, building the webs
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body, throwAnalysis, omitExceptingUnitEdges);
// run in panic mode on first split (maybe change this depending on the input
// source)
final LocalDefs defs = LocalDefs.Factory.newLocalDefs(graph, true);
final LocalUses uses = LocalUses.Factory.newLocalUses(graph, defs);
if (Options.v().time())
Timers.v().splitPhase1Timer.end();
if (Options.v().time())
Timers.v().splitPhase2Timer.start();
Set<Unit> visited = new HashSet<Unit>();
// Collect the set of locals that we need to split^
BitSet localsToSplit = new BitSet(localPacker.getLocalCount());
{
BitSet localsVisited = new BitSet(localPacker.getLocalCount());
for (Unit s : body.getUnits()) {
if (s.getDefBoxes().isEmpty())
continue;
if (!(s.getDefBoxes().get(0).getValue() instanceof Local))
continue;
// If we see a local the second time, we know that we must split it
Local l = (Local) s.getDefBoxes().get(0).getValue();
if (localsVisited.get(l.getNumber()))
localsToSplit.set(l.getNumber());
localsVisited.set(l.getNumber());
}
}
int w = 0;
for (Unit s : body.getUnits()) {
if (s.getDefBoxes().isEmpty())
continue;
if (s.getDefBoxes().size() > 1)
throw new RuntimeException("stmt with more than 1 defbox!");
if (!(s.getDefBoxes().get(0).getValue() instanceof Local))
continue;
// we don't want to visit a node twice
if (visited.remove(s))
continue;
// always reassign locals to avoid "use before definition" bugs!
// unfortunately this creates a lot of new locals, so it's important
// to remove them afterwards
Local oldLocal = (Local) s.getDefBoxes().get(0).getValue();
if (!localsToSplit.get(oldLocal.getNumber()))
continue;
Local newLocal = (Local) oldLocal.clone();
// renaming should not be done here
newLocal.setName(newLocal.getName() + '#' + ++w);
body.getLocals().add(newLocal);
Deque<Unit> queue = new ArrayDeque<Unit>();
queue.addFirst(s);
do {
final Unit head = queue.removeFirst();
if (visited.add(head)) {
for (UnitValueBoxPair use : uses.getUsesOf(head)) {
ValueBox vb = use.valueBox;
Value v = vb.getValue();
if (v == newLocal)
continue;
// should always be true - but who knows ...
if (v instanceof Local) {
Local l = (Local) v;
queue.addAll(defs.getDefsOfAt(l, use.unit));
vb.setValue(newLocal);
}
}
for (ValueBox vb : head.getDefBoxes()) {
Value v = vb.getValue();
if (v instanceof Local) {
vb.setValue(newLocal);
}
}
}
} while (!queue.isEmpty());
// keep the set small
visited.remove(s);
}
// Restore the original local numbering
localPacker.unpack();
if (Options.v().time())
Timers.v().splitPhase2Timer.end();
if (Options.v().time())
Timers.v().splitTimer.end();
}
use of soot.ValueBox in project soot by Sable.
the class SimpleLocalDefs method init.
private void init(DirectedGraph<Unit> graph, Local[] locals, FlowAnalysisMode mode) {
@SuppressWarnings("unchecked") List<Unit>[] unitList = new List[locals.length];
Arrays.fill(unitList, emptyList());
boolean omitSSA = mode == FlowAnalysisMode.OmitSSA;
boolean doFlowAnalsis = omitSSA;
int units = 0;
// collect all def points
for (Unit unit : graph) {
for (ValueBox box : unit.getDefBoxes()) {
Value v = box.getValue();
if (v instanceof Local) {
Local l = (Local) v;
int lno = l.getNumber();
switch(unitList[lno].size()) {
case 0:
unitList[lno] = singletonList(unit);
if (omitSSA)
units++;
break;
case 1:
if (!omitSSA)
units++;
unitList[lno] = new ArrayList<Unit>(unitList[lno]);
doFlowAnalsis = true;
// fallthrough
default:
unitList[lno].add(unit);
units++;
break;
}
}
}
}
if (doFlowAnalsis && mode != FlowAnalysisMode.FlowInsensitive) {
def = new FlowAssignment(graph, locals, unitList, units, omitSSA);
} else {
def = new StaticSingleAssignment(locals, unitList);
}
}
use of soot.ValueBox in project soot by Sable.
the class SmartLocalDefs method localDef.
private Local localDef(Unit u) {
List<ValueBox> defBoxes = u.getDefBoxes();
int size = defBoxes.size();
if (size == 0)
return null;
if (size != 1)
throw new RuntimeException();
ValueBox vb = defBoxes.get(0);
Value v = vb.getValue();
if (!(v instanceof Local))
return null;
return (Local) v;
}
use of soot.ValueBox in project soot by Sable.
the class SimpleVeryBusyAnalysis method kill.
/**
* Performs kills by generating a killSet and then performing<br/>
* outSet <- inSet - killSet<br/>
* The kill set is generated by iterating over the def-boxes
* of the unit. For each local defined in the unit we iterate
* over the binopExps in the inSet, and check whether they use
* that local. If so, it is added to the kill set.
* @param inSet the set flowing into the unit
* @param u the unit being flown through
* @param outSet the set flowing out of the unit
*/
private void kill(FlowSet inSet, Unit u, FlowSet outSet) {
FlowSet kills = emptySet.clone();
for (ValueBox defBox : u.getDefBoxes()) {
if (defBox.getValue() instanceof Local) {
Iterator<BinopExpr> inIt = inSet.iterator();
while (inIt.hasNext()) {
BinopExpr e = inIt.next();
Iterator<ValueBox> eIt = e.getUseBoxes().iterator();
while (eIt.hasNext()) {
ValueBox useBox = eIt.next();
if (useBox.getValue() instanceof Local && useBox.getValue().equivTo(defBox.getValue()))
kills.add(e);
}
}
}
}
inSet.difference(kills, outSet);
}
Aggregations