use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class FieldRenamerPass method accept.
@Override
public PassResult accept(PassContext pcxt) {
AnalysisContext cxt = pcxt.getAnalysis();
Map<FieldNode, String> remapped = new HashMap<>();
// int totalFields = 0;
// int i = RenamingUtil.computeMinimum(totalFields);
ApplicationClassSource source = cxt.getApplication();
int i = RenamingUtil.numeric("aaaaa");
for (ClassNode cn : source.iterate()) {
// totalFields += cn.fields.size();
for (FieldNode fn : cn.getFields()) {
remapped.put(fn, RenamingUtil.createName(i++));
}
}
InvocationResolver resolver = cxt.getInvocationResolver();
for (ClassNode cn : source.iterate()) {
for (MethodNode m : cn.getMethods()) {
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
if (stmt.getOpcode() == Opcode.FIELD_STORE) {
FieldStoreStmt fs = (FieldStoreStmt) stmt;
FieldNode f = resolver.findField(fs.getOwner(), fs.getName(), fs.getDesc(), fs.getInstanceExpression() == null);
if (f != null) {
if (remapped.containsKey(f)) {
fs.setName(remapped.get(f));
} else if (mustMark(source, f.getOwner())) {
System.err.println(" no remap for " + f + ", owner: " + f.getOwner());
}
} else {
if (mustMark(source, fs.getOwner())) {
System.err.println(" can't resolve field(set): " + fs.getOwner() + "." + fs.getName() + " " + fs.getDesc() + ", " + (fs.getInstanceExpression() == null));
}
}
}
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.FIELD_LOAD) {
FieldLoadExpr fl = (FieldLoadExpr) e;
FieldNode f = resolver.findField(fl.getOwner(), fl.getName(), fl.getDesc(), fl.getInstanceExpression() == null);
if (f != null) {
if (remapped.containsKey(f)) {
fl.setName(remapped.get(f));
} else if (mustMark(source, f.getOwner())) {
System.err.println(" no remap for " + f + ", owner: " + f.getOwner());
}
} else {
if (mustMark(source, fl.getOwner())) {
System.err.println(" can't resolve field(get): " + fl.getOwner() + "." + fl.getName() + " " + fl.getDesc() + ", " + (fl.getInstanceExpression() == null));
}
}
}
}
}
}
}
}
for (Entry<FieldNode, String> e : remapped.entrySet()) {
e.getKey().node.name = e.getValue();
}
System.out.printf(" Renamed %d fields.%n", remapped.size());
return PassResult.with(pcxt, this).finished().make();
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class CFGExporterUtils method makeDotGraph.
public static DotGraph makeDotGraph(ControlFlowGraph cfg, IPropertyDictionary properties) {
boolean showStmts = PropertyHelper.isSet(properties, OPT_STMTS);
boolean labelEdges = PropertyHelper.isSet(properties, OPT_EDGES);
boolean simplifyEdges = PropertyHelper.isSet(properties, OPT_SIMPLE_EDGES);
boolean hideHandlerEdges = PropertyHelper.isSet(properties, OPT_HIDE_HANDLER_EDGES);
DotGraph sourceGraph = Factory.graph().getGraphAttr().with(Rank.SOURCE);
DotGraph sinkGraph = Factory.graph().getGraphAttr().with(Rank.SINK);
DotGraph g = GraphUtils.makeDotSkeleton(cfg, (block, node) -> {
StringBuilder sb = new StringBuilder();
sb.append("<table>");
{
sb.append("<tr><td><font point-size=\"12\">").append(block.getDisplayName()).append("</font></td></tr>");
}
{
sb.append("<tr><td>");
if (showStmts) {
StringBuilder stmtsStr = new StringBuilder();
outputBlock(block, stmtsStr);
sb.append(stmtsStr.toString());
}
sb.append("</td></tr>");
}
sb.append("</table>");
Attrs colour;
DotGraph rankGraph;
if (cfg.getEntries().contains(block)) {
colour = Colour.RED.fill();
rankGraph = sourceGraph;
} else if (cfg.getEdges(block).isEmpty()) {
colour = Colour.GREEN.fill();
rankGraph = sinkGraph;
} else {
colour = Attrs.attrs();
rankGraph = null;
}
if (rankGraph != null) {
Context.use(rankGraph, (ctx) -> {
return rankGraph.addSource(Factory.node(node.getName()));
});
}
node.with(Shape.BOX, Style.FILLED, colour, ComplexLabel.html(sb.toString()).justify(Justification.LEFT));
return true;
}, (e, dotE) -> {
if (hideHandlerEdges && e instanceof TryCatchEdge) {
// dotE.with(Style.INVIS);
return false;
}
if (labelEdges) {
dotE.with(ComplexLabel.of(simplifyEdges ? e.getClass().getSimpleName().replace("Edge", "") : e.toGraphString()));
}
return true;
}).setDirected(true);
g.addSource(sourceGraph);
g.addSource(sinkGraph);
return g;
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class Boot method main.
public static void main(String[] args) throws Exception {
sections = new LinkedList<>();
logging = true;
// Load input jar
// File f = locateRevFile(135);
File f = new File(args[0]);
section("Preparing to run on " + f.getAbsolutePath());
SingleJarDownloader<ClassNode> dl = new SingleJarDownloader<>(new JarInfo(f));
dl.download();
String appName = f.getName().substring(0, f.getName().length() - 4);
ApplicationClassSource app = new ApplicationClassSource(appName, dl.getJarContents().getClassContents());
//
// ApplicationClassSource app = new ApplicationClassSource("test", ClassHelper.parseClasses(CGExample.class));
// app.addLibraries(new InstalledRuntimeClassSource(app));
File rtjar = new File(System.getProperty("java.home"), "lib/rt.jar");
// File androidjar = new File("res/android.jar");
app.addLibraries(rt(app, rtjar));
section("Initialising context.");
IRCache irFactory = new IRCache(ControlFlowGraphBuilder::build);
AnalysisContext cxt = new BasicAnalysisContext.BasicContextBuilder().setApplication(app).setInvocationResolver(new DefaultInvocationResolver(app)).setCache(irFactory).setApplicationContext(new SimpleApplicationContext(app)).setDataFlowAnalysis(new LiveDataFlowAnalysisImpl(irFactory)).build();
section("Expanding callgraph and generating cfgs.");
for (ClassNode cn : cxt.getApplication().iterate()) {
// continue;
for (MethodNode m : cn.getMethods()) {
// if (!m.getName().equals("setRccState"))
// continue;
cxt.getIRCache().getFor(m);
}
}
section0("...generated " + cxt.getIRCache().size() + " cfgs in %fs.%n", "Preparing to transform.");
// do passes
PassGroup masterGroup = new PassGroup("MasterController");
for (IPass p : getTransformationPasses()) {
masterGroup.add(p);
}
run(cxt, masterGroup);
section0("...done transforming in %fs.%n", "Preparing to transform.");
for (Entry<MethodNode, ControlFlowGraph> e : cxt.getIRCache().entrySet()) {
MethodNode mn = e.getKey();
ControlFlowGraph cfg = e.getValue();
try {
cfg.verify();
} catch (Exception ex) {
ex.printStackTrace();
}
}
section("Retranslating SSA IR to standard flavour.");
for (Entry<MethodNode, ControlFlowGraph> e : cxt.getIRCache().entrySet()) {
MethodNode mn = e.getKey();
// if (!mn.getName().equals("openFiles"))
// continue;
ControlFlowGraph cfg = e.getValue();
// CFGUtils.easyDumpCFG(cfg, "pre-destruct");
try {
cfg.verify();
} catch (Exception ex) {
ex.printStackTrace();
}
BoissinotDestructor.leaveSSA(cfg);
// CFGUtils.easyDumpCFG(cfg, "pre-reaalloc");
LocalsReallocator.realloc(cfg);
// System.out.println(cfg);
try {
cfg.verify();
} catch (Exception ex) {
ex.printStackTrace();
}
// System.out.println("Rewriting " + mn.getName());
(new ControlFlowGraphDumper(cfg, mn)).dump();
// System.out.println(InsnListUtils.insnListToString(mn.instructions));
}
section("Rewriting jar.");
dumpJar(app, dl, masterGroup, "out/rewritten.jar");
section("Finished.");
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class ConstantExpressionReorderPass method accept.
@Override
public PassResult accept(PassContext pcxt) {
AnalysisContext cxt = pcxt.getAnalysis();
int delta = 0;
for (MethodNode m : cxt.getIRCache().getActiveMethods()) {
ControlFlowGraph ir = cxt.getIRCache().getFor(m);
delta += transform(ir);
}
System.out.println(" swapped " + delta + " constant expression orders.");
return PassResult.with(pcxt, this).finished(delta).make();
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class ExpressionEvaluator method evalPossibleValues0.
private TaintableSet<ConstantExpr> evalPossibleValues0(NullPermeableHashMap<ControlFlowGraph, Set<Local>> visited, LocalValueResolver resolver, Expr e) {
if (e.getOpcode() == CONST_LOAD) {
TaintableSet<ConstantExpr> set = new TaintableSet<>();
set.add((ConstantExpr) e);
return set;
} else /*else if(e.getOpcode() == PHI) {
PhiExpr phi = (PhiExpr) e;
TaintableSet<ConstantExpr> set = new HashSet<>();
for(Expr pA : phi.getArguments().values()) {
TaintableSet<ConstantExpr> s = evalPossibleValues(resolver, pA);
set.union(s);
}
return set;
}*/
if (e.getOpcode() == ARITHMETIC) {
ArithmeticExpr ae = (ArithmeticExpr) e;
Expr l = ae.getLeft();
Expr r = ae.getRight();
TaintableSet<ConstantExpr> le = evalPossibleValues0(visited, resolver, l);
TaintableSet<ConstantExpr> re = evalPossibleValues0(visited, resolver, r);
TaintableSet<ConstantExpr> results = new TaintableSet<>(le.isTainted() | re.isTainted());
for (Iterator<Pair<ConstantExpr, ConstantExpr>> it = le.product(re); it.hasNext(); ) {
Pair<ConstantExpr, ConstantExpr> lcrc = it.next();
ConstantExpr lc = lcrc.getKey();
ConstantExpr rc = lcrc.getValue();
EvaluationFunctor<Number> b = factory.arithmetic(lc.getType(), rc.getType(), ae.getType(), ae.getOperator());
results.add(new ConstantExpr(b.eval(lc.getConstant(), rc.getConstant())));
}
return results;
} else if (e.getOpcode() == NEGATE) {
NegationExpr neg = (NegationExpr) e;
TaintableSet<ConstantExpr> inputs = evalPossibleValues0(visited, resolver, neg.getExpression());
TaintableSet<ConstantExpr> outputs = new TaintableSet<>(inputs.isTainted());
for (ConstantExpr c : inputs) {
EvaluationFunctor<Number> b = factory.negate(c.getType());
outputs.add(new ConstantExpr(b.eval(c.getConstant())));
}
return outputs;
} else if (e.getOpcode() == LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
Local l = v.getLocal();
ControlFlowGraph g = e.getBlock().getGraph();
visited.getNonNull(g).add(l);
TaintableSet<Expr> defExprs = resolver.getValues(g, l);
TaintableSet<ConstantExpr> vals = new TaintableSet<>(defExprs.isTainted());
for (Expr defE : defExprs) {
if (defE.getOpcode() == LOCAL_LOAD) {
VarExpr v2 = (VarExpr) defE;
Local l2 = v2.getLocal();
if (visited.getNonNull(g).contains(l2)) {
continue;
}
visited.getNonNull(g).add(l2);
}
TaintableSet<ConstantExpr> defConstVals = evalPossibleValues0(visited, resolver, defE);
vals.union(defConstVals);
}
return vals;
} else if (e.getOpcode() == CAST) {
CastExpr cast = (CastExpr) e;
TaintableSet<ConstantExpr> inputs = evalPossibleValues0(visited, resolver, cast.getExpression());
TaintableSet<ConstantExpr> outputs = new TaintableSet<>(inputs.isTainted());
for (ConstantExpr ce : inputs) {
// TODO: czech out::
// can get expressions like (double)({lvar7_1 * 4})
// where {lvar7_1 * 4} has type INT but the real
// eval consts are all bytes or shorts etc
/*if(!ce.getType().equals(cast.getExpression().getType())) {
System.err.printf("want to cast %s%n", cast);
System.err.printf(" in: %s, death: %s%n", set, ce);
throw new IllegalStateException(ce.getType() + " : " + cast.getExpression().getType());
}*/
Type from = ce.getType();
Type to = cast.getType();
boolean p1 = TypeUtils.isPrimitive(from);
boolean p2 = TypeUtils.isPrimitive(to);
if (p1 != p2) {
throw new IllegalStateException(from + " to " + to);
}
if (!p1 && !p2) {
throw new IllegalStateException(from + " to " + to);
// return new TaintableSet<>();
}
EvaluationFunctor<Number> b = factory.cast(from, to);
outputs.add(new ConstantExpr(b.eval(ce.getConstant())));
}
return outputs;
} else if (e.getOpcode() == COMPARE) {
// throw new UnsupportedOperationException("todo lmao");
// ComparisonExpr comp = (ComparisonExpr) e;
// Expr l = comp.getLeft();
// Expr r = comp.getRight();
//
// Expr le = eval(pool, l);
// Expr re = eval(pool, r);
//
// if(le != null && re != null) {
// ConstantExpr lc = (ConstantExpr) le;
// ConstantExpr rc = (ConstantExpr) re;
//
// Bridge b = getComparisonBridge(lc.getType(), rc.getType(), comp.getComparisonType());
//
// System.out.println(b.method);
// System.out.println(comp + " -> " + b.eval(lc.getConstant(), rc.getConstant()));
// ConstantExpr cr = new ConstantExpr((int)b.eval(lc.getConstant(), rc.getConstant()));
// return cr;
// }
}
/* uncomputable value, i.e. non const. */
return new TaintableSet<>(true);
}
Aggregations