package org.jf.dexlib.Interface;
import java.io.FileNotFoundException;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.List;
import org.jf.dexlib.ClassDataItem.EncodedMethod;
import org.jf.dexlib.CodeItem;
import org.jf.dexlib.MethodIdItem;
import org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
import org.jf.dexlib.Code.Analysis.InlineMethodResolver;
import org.jf.dexlib.Code.Analysis.MethodAnalyzer;
import org.jf.dexlib.Code.Analysis.graphs.CDG;
import org.jf.dexlib.Code.Analysis.graphs.CFG;
import org.jf.dexlib.Code.Analysis.graphs.DominanceFrontiers;
import org.jf.dexlib.Code.Analysis.graphs.Dominators;
import org.jf.dexlib.Code.Analysis.graphs.Dominators.DomTree;
import org.jf.dexlib.Code.Analysis.graphs.GraphDumper;
import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.EdgeReversedGraph;
/**
*
* @author Juergen Graf <juergen.graf@gmail.com>
*
*/
public class DexMethod {
private final List<AnalyzedInstruction> instructions;
private final EncodedMethod encMethod;
private SoftReference<CFG> cfg;
private SoftReference<CFG> cfgWithExc;
public static DexMethod build(final EncodedMethod encMethod) {
return build(encMethod, false, null);
}
public static DexMethod build(final EncodedMethod encMethod, final boolean deodex, final InlineMethodResolver inlineResolver) {
final MethodAnalyzer analyzer = new MethodAnalyzer(encMethod, deodex, inlineResolver);
analyzer.analyze();
final List<AnalyzedInstruction> instrList = analyzer.getInstructions();
return new DexMethod(instrList, encMethod);
}
public DexMethod(final List<AnalyzedInstruction> instructions, final EncodedMethod encMethod) {
this.instructions = Collections.unmodifiableList(instructions);
this.encMethod = encMethod;
}
public MethodIdItem getId() {
return encMethod.method;
}
public CodeItem getCode() {
return encMethod.codeItem;
}
public List<AnalyzedInstruction> getInstructions() {
return instructions;
}
public CFG getControlFlowGraph(final boolean includeExceptions) {
if (includeExceptions) {
if (cfgWithExc == null || cfgWithExc.get() == null) {
final CFG tmp = CFG.build(instructions, getId().getMethodString(), true);
cfgWithExc = new SoftReference<CFG>(tmp);
}
return cfgWithExc.get();
} else {
if (cfg == null || cfg.get() == null) {
final CFG tmp = CFG.build(instructions, getId().getMethodString(), false);
cfg = new SoftReference<CFG>(tmp);
}
return cfg.get();
}
}
public CDG getControlDependenceGraph(final boolean includeExceptions) {
return CDG.build(getControlFlowGraph(includeExceptions));
}
public Dominators<CFG.Node, CFG.Edge> getDominators(final boolean includeExceptions) {
final CFG cfg = getControlFlowGraph(includeExceptions);
final DirectedGraph<CFG.Node, CFG.Edge> reversedCfg = new EdgeReversedGraph<CFG.Node, CFG.Edge>(cfg);
return Dominators.compute(reversedCfg, cfg.getExit());
}
public DomTree<CFG.Node> getDominationTree(final boolean includeExceptions) {
return getDominators(includeExceptions).getDominationTree();
}
public DominanceFrontiers<CFG.Node, CFG.Edge> getDominanceFrontiers(final boolean includeExceptions) {
final CFG cfg = getControlFlowGraph(includeExceptions);
final DirectedGraph<CFG.Node, CFG.Edge> reversedCfg = new EdgeReversedGraph<CFG.Node, CFG.Edge>(cfg);
return DominanceFrontiers.compute(reversedCfg, cfg.getExit());
}
public void dumpGraphs(final GraphDumper gDump) throws FileNotFoundException {
gDump.dump(this, encMethod.method.getVirtualMethodString());
}
public String toString() {
return "DexMethod(" + encMethod.method.getMethodString() + "): " + instructions.size() + " instructions";
}
}