Search in sources :

Example 1 with MethodNode

use of org.mapleir.asm.MethodNode in project maple-ir by LLVM-but-worse.

the class SimpleApplicationContext method isLibraryInheritedMethod.

private boolean isLibraryInheritedMethod(MethodNode m) {
    if (Modifier.isStatic(m.node.access) || m.getName().equals("<init>")) {
        return false;
    }
    ClassTree tree = app.getClassTree();
    // TODO: could probably optimise with dfs instead of getAll
    Collection<ClassNode> parents = tree.getAllParents(m.owner);
    for (ClassNode cn : parents) {
        if (app.isLibraryClass(cn.getName())) {
            for (MethodNode cnM : cn.getMethods()) {
                if (!Modifier.isStatic(cnM.node.access) && cnM.getName().equals(m.getName()) && cnM.getDesc().equals(m.getDesc())) {
                    return true;
                }
            }
        }
    }
    return false;
}
Also used : ClassNode(org.mapleir.asm.ClassNode) MethodNode(org.mapleir.asm.MethodNode) ClassTree(org.mapleir.app.service.ClassTree)

Example 2 with MethodNode

use of org.mapleir.asm.MethodNode in project maple-ir by LLVM-but-worse.

the class ConstantExpressionEvaluatorPass method accept.

@Override
public PassResult accept(PassContext pcxt) {
    AnalysisContext cxt = pcxt.getAnalysis();
    branchesEvaluated = 0;
    exprsEvaluated = 0;
    IPConstAnalysisVisitor vis = new IPConstAnalysisVisitor(cxt);
    IPAnalysis.create(cxt, vis);
    for (; ; ) {
        int prevExprsEval = exprsEvaluated;
        int prevBranchesEval = branchesEvaluated;
        for (ClassNode cn : cxt.getApplication().iterate()) {
            for (MethodNode m : cn.getMethods()) {
                processMethod(m, vis, cxt.getIRCache().getFor(m));
            }
        }
        if (prevExprsEval == exprsEvaluated && prevBranchesEval == branchesEvaluated) {
            break;
        }
    }
    System.out.printf("  evaluated %d constant expressions.%n", exprsEvaluated);
    System.out.printf("  eliminated %d constant branches.%n", branchesEvaluated);
    return PassResult.with(pcxt, this).finished(exprsEvaluated).make();
}
Also used : ClassNode(org.mapleir.asm.ClassNode) MethodNode(org.mapleir.asm.MethodNode) AnalysisContext(org.mapleir.context.AnalysisContext)

Example 3 with MethodNode

use of org.mapleir.asm.MethodNode in project maple-ir by LLVM-but-worse.

the class MethodRenamerPass method accept.

@Override
public PassResult accept(PassContext pcxt) {
    AnalysisContext cxt = pcxt.getAnalysis();
    ApplicationClassSource source = cxt.getApplication();
    InvocationResolver resolver = cxt.getInvocationResolver();
    Map<MethodNode, String> remapped = new HashMap<>();
    int totalMethods = 0;
    for (ClassNode cn : source.iterate()) {
        totalMethods += cn.getMethods().size();
    }
    int i = RenamingUtil.computeMinimum(totalMethods);
    for (ClassNode cn : source.iterate()) {
        for (MethodNode m : cn.getMethods()) {
            if (!heuristic.shouldRename(m.getName(), m.node.access)) {
                // System.out.println("Heuristic bypass meth " + m.name);
                continue;
            }
            if (remapped.containsKey(m)) {
                continue;
            }
            if (Modifier.isStatic(m.node.access)) {
                if (!m.getName().equals("<clinit>") && !SimpleApplicationContext.isMainMethod(m)) {
                    String newName = RenamingUtil.createName(i++);
                    remapped.put(m, newName);
                }
            } else {
                if (!m.getName().equals("<init>")) {
                    // Set<ClassNode> classes = source.getStructures().dfsTree(m.owner, true, true, true);
                    // Set<MethodNode> methods = getVirtualMethods(cxt, classes, m.name, m.desc);
                    Set<MethodNode> methods = resolver.getHierarchyMethodChain(m.owner, m.getName(), m.node.desc, true);
                    if (canRename(cxt, methods)) {
                        String newName = RenamingUtil.createName(i++);
                        for (MethodNode o : methods) {
                            // Set<MethodNode> s2 = InvocationResolver.getHierarchyMethodChain(cxt, o.owner, o.name, m.desc, true);
                            /*if(!methods.equals(s2)) {
									System.err.printf("m: %s%n", m);
									System.err.printf("o: %s%n", o);
									System.err.println("this ms::");
									for(MethodNode s : methods) {
										System.err.printf("   %s%n", s);
									}
									System.err.println("o ms::");
									for(MethodNode s : s2) {
										System.err.printf("   %s%n", s);
									}
									throw new IllegalStateException();
								}*/
                            /*if(remapped.containsKey(o)) {
									System.err.printf("m: %s%n", m);
									System.err.printf("o: %s%n", o);
									System.err.println("this ms::");
									for(MethodNode s : methods) {
										System.err.printf("   %s%n", s);
									}
									System.err.println("o ms::");
									for(MethodNode s : InvocationResolver.getHierarchyMethodChain(cxt, o.owner, o.name, m.desc, true)) {
										System.err.printf("   %s%n", s);
									}
									System.err.println(" o debugset::");
									for(MethodNode s : debugMap.get(o)) {
										System.err.printf("   %s%n", s);
									}
									System.err.printf("on: %s%n", remapped.get(o));
									System.err.printf("nn: %s%n", newName);
									throw new IllegalStateException();
								}*/
                            remapped.put(o, newName);
                        }
                    /*for(MethodNode hm : methods) {
								debugMap.put(hm, methods);
							}*/
                    } else {
                        System.out.println("  can't rename: " + methods);
                    }
                }
            }
        }
    }
    rename(cxt, remapped, true);
    System.out.printf("  Remapped %d/%d methods.%n", remapped.size(), totalMethods);
    return PassResult.with(pcxt, this).finished().make();
}
Also used : ClassNode(org.mapleir.asm.ClassNode) ApplicationClassSource(org.mapleir.app.service.ApplicationClassSource) MethodNode(org.mapleir.asm.MethodNode) HashMap(java.util.HashMap) InvocationResolver(org.mapleir.app.service.InvocationResolver) AnalysisContext(org.mapleir.context.AnalysisContext)

Example 4 with MethodNode

use of org.mapleir.asm.MethodNode in project maple-ir by LLVM-but-worse.

the class MethodRenamerPass method rename.

public static void rename(AnalysisContext cxt, Map<MethodNode, String> remapped, boolean warn) {
    ApplicationClassSource source = cxt.getApplication();
    InvocationResolver resolver = cxt.getInvocationResolver();
    for (ClassNode cn : source.iterate()) {
        {
            if (cn.node.outerMethod != null) {
                // ClassNode owner = tree.getClass(cn.node.outerClass);
                System.out.println("Outer: " + cn.node.outerClass + "." + cn.node.outerMethod + " " + cn.node.outerMethodDesc);
                cn.node.outerClass = null;
                cn.node.outerMethod = null;
                cn.node.outerMethodDesc = null;
            // System.out.println(owner.name);
            // do {
            // for(MethodNode m : owner.methods) {
            // System.out.println(m);
            // if(m.name.equals(cn.outerMethod) && m.desc.equals(cn.outerMethodDesc)) {
            // System.out.println("m: " + m);
            // }
            // }
            // owner = tree.getClass(owner.superName);
            // System.out.println(cn.superName);
            // System.out.println(owner);
            // } while(owner != null);
            }
        }
        Set<Expr> visited = new HashSet<>();
        for (MethodNode m : cn.getMethods()) {
            ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
            for (BasicBlock b : cfg.vertices()) {
                for (Stmt stmt : b) {
                    for (Expr e : stmt.enumerateOnlyChildren()) {
                        if (e.getOpcode() == Opcode.INVOKE) {
                            InvocationExpr invoke = (InvocationExpr) e;
                            if (invoke.isDynamic())
                                throw new UnsupportedOperationException();
                            if (visited.contains(invoke)) {
                                throw new RuntimeException(invoke.toString());
                            }
                            visited.add(invoke);
                            if (invoke.getOwner().startsWith("[")) {
                                System.err.println("  ignore array object invoke: " + invoke + ", owner: " + invoke.getOwner());
                                continue;
                            }
                            if (invoke.isStatic()) {
                                MethodNode site = resolver.resolveStaticCall(invoke.getOwner(), invoke.getName(), invoke.getDesc());
                                if (site != null) {
                                    if (remapped.containsKey(site)) {
                                        invoke.setName(remapped.get(site));
                                    } else {
                                        if (warn && mustMark(source, invoke.getOwner())) {
                                            System.err.println("  invalid site(s): " + invoke);
                                        }
                                    }
                                } else {
                                    if (mustMark(source, invoke.getOwner())) {
                                        System.err.printf("  can't resolve(s) %s ; %s.%s %s%n", invoke, invoke.getOwner(), invoke.getName(), invoke.getDesc());
                                        if (invoke.getOwner().equals("hey")) {
                                            for (MethodNode mm : cxt.getApplication().findClassNode(invoke.getOwner()).getMethods()) {
                                                System.out.println(mm);
                                            }
                                            throw new UnsupportedOperationException();
                                        }
                                    }
                                }
                            } else {
                                // Set<MethodNode> sites = resolver.resolveVirtualCalls(invoke.getOwner(), invoke.getName(), invoke.getDesc());
                                // Set<ClassNode> classes = source.getStructures().dfsTree(cn, true, true, true);
                                // Set<MethodNode> sites = getVirtualMethods(cxt, classes, invoke.getName(), invoke.getDesc());
                                Set<MethodNode> sites = resolver.getHierarchyMethodChain(source.findClassNode(invoke.getOwner()), invoke.getName(), invoke.getDesc(), true);
                                if (sites.size() > 0) {
                                    /* all of the sites must be linked by the same name,
										 * so we can use any to find the new name. */
                                    boolean anyContains = false;
                                    boolean allContains = true;
                                    for (MethodNode s : sites) {
                                        anyContains |= remapped.containsKey(s);
                                        allContains &= remapped.containsKey(s);
                                    }
                                    if (anyContains && !allContains) {
                                        System.err.println("mismatch: ");
                                        // System.err.println(classes);
                                        System.err.println(sites);
                                        throw new RuntimeException();
                                    }
                                    MethodNode site = sites.iterator().next();
                                    if (remapped.containsKey(site)) {
                                        invoke.setName(remapped.get(site));
                                    } else {
                                        if (warn && !site.getName().equals("<init>") && canRename(cxt, sites)) {
                                            System.err.println("  invalid site(v): " + invoke + ", " + sites);
                                        }
                                    }
                                } else {
                                    if (mustMark(source, invoke.getOwner())) {
                                        System.err.println("  can't resolve(v) " + invoke + ", owner: " + invoke.getOwner() + " desc " + invoke.getDesc());
                                    // System.err.println("  classes: " + classes);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    /* Rename the methods after as we need to resolve
		 * them using the old names during the invocation 
		 * analysis above. */
    for (Entry<MethodNode, String> e : remapped.entrySet()) {
        // System.out.printf("%s -> %s%n", e.getKey(), e.getValue());
        e.getKey().node.name = e.getValue();
    }
}
Also used : ClassNode(org.mapleir.asm.ClassNode) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Stmt(org.mapleir.ir.code.Stmt) ApplicationClassSource(org.mapleir.app.service.ApplicationClassSource) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) Expr(org.mapleir.ir.code.Expr) MethodNode(org.mapleir.asm.MethodNode) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) InvocationResolver(org.mapleir.app.service.InvocationResolver) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) HashSet(java.util.HashSet)

Example 5 with MethodNode

use of org.mapleir.asm.MethodNode in project maple-ir by LLVM-but-worse.

the class ReflectiveFunctorFactory method branch.

@Override
public EvaluationFunctor<Boolean> branch(Type lt, Type rt, ConditionalJumpStmt.ComparisonType type) {
    Type opType = TypeUtils.resolveBinOpType(lt, rt);
    String name = lt.getClassName() + type.name() + rt.getClassName() + "OPTYPE" + opType.getClassName() + "RETbool";
    String desc = "(" + lt.getDescriptor() + rt.getDescriptor() + ")Z";
    if (cache.containsKey(name)) {
        return _get(name);
    }
    MethodNode m = makeBase(name, desc);
    {
        InsnList insns = new InsnList();
        insns.add(new VarInsnNode(TypeUtils.getVariableLoadOpcode(lt), 0));
        cast(insns, lt, opType);
        insns.add(new VarInsnNode(TypeUtils.getVariableLoadOpcode(rt), lt.getSize()));
        cast(insns, rt, opType);
        LabelNode trueSuccessor = new LabelNode();
        if (opType == Type.INT_TYPE) {
            insns.add(new JumpInsnNode(Opcodes.IF_ICMPEQ + type.ordinal(), trueSuccessor));
        } else if (opType == Type.LONG_TYPE) {
            insns.add(new InsnNode(Opcodes.LCMP));
            insns.add(new JumpInsnNode(Opcodes.IFEQ + type.ordinal(), trueSuccessor));
        } else if (opType == Type.FLOAT_TYPE) {
            insns.add(new InsnNode((type == ConditionalJumpStmt.ComparisonType.LT || type == ConditionalJumpStmt.ComparisonType.LE) ? Opcodes.FCMPL : Opcodes.FCMPG));
            insns.add(new JumpInsnNode(Opcodes.IFEQ + type.ordinal(), trueSuccessor));
        } else if (opType == Type.DOUBLE_TYPE) {
            insns.add(new InsnNode((type == ConditionalJumpStmt.ComparisonType.LT || type == ConditionalJumpStmt.ComparisonType.LE) ? Opcodes.DCMPL : Opcodes.DCMPG));
            insns.add(new JumpInsnNode(Opcodes.IFEQ + type.ordinal(), trueSuccessor));
        } else {
            throw new IllegalArgumentException(opType.toString());
        }
        branchReturn(insns, trueSuccessor);
        m.node.instructions = insns;
    }
    return buildBridge(m);
}
Also used : LabelNode(org.objectweb.asm.tree.LabelNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) InsnNode(org.objectweb.asm.tree.InsnNode) Type(org.objectweb.asm.Type) MethodNode(org.mapleir.asm.MethodNode) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) InsnList(org.objectweb.asm.tree.InsnList) VarInsnNode(org.objectweb.asm.tree.VarInsnNode)

Aggregations

MethodNode (org.mapleir.asm.MethodNode)36 ClassNode (org.mapleir.asm.ClassNode)21 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)17 AnalysisContext (org.mapleir.context.AnalysisContext)13 ApplicationClassSource (org.mapleir.app.service.ApplicationClassSource)8 Expr (org.mapleir.ir.code.Expr)8 Stmt (org.mapleir.ir.code.Stmt)7 BasicBlock (org.mapleir.ir.cfg.BasicBlock)6 Type (org.objectweb.asm.Type)6 InvocationResolver (org.mapleir.app.service.InvocationResolver)5 IRCache (org.mapleir.context.IRCache)5 ControlFlowGraphBuilder (org.mapleir.ir.cfg.builder.ControlFlowGraphBuilder)5 InsnList (org.objectweb.asm.tree.InsnList)5 InsnNode (org.objectweb.asm.tree.InsnNode)5 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)5 VarInsnNode (org.objectweb.asm.tree.VarInsnNode)5 HashSet (java.util.HashSet)4 SimpleApplicationContext (org.mapleir.app.client.SimpleApplicationContext)4 BasicAnalysisContext (org.mapleir.context.BasicAnalysisContext)4 IPass (org.mapleir.deob.IPass)4