public JDynamicInvokeExpr( SootMethodRef bootstrapMethodRef, List<Value> bootstrapArgs, SootMethodRef methodRef, List<Value> methodArgs) { if (!methodRef.getSignature().startsWith("<" + SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME + ": ")) throw new IllegalArgumentException( "Receiver type of JDynamicInvokeExpr must be " + SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME + "!"); if (!bootstrapMethodRef.returnType().equals(RefType.v("java.lang.invoke.CallSite"))) { throw new IllegalArgumentException( "Return type of bootstrap method must be java.lang.invoke.CallSite!"); } this.bsmRef = bootstrapMethodRef; this.methodRef = methodRef; this.bsmArgBoxes = new ValueBox[bootstrapArgs.size()]; this.argBoxes = new ValueBox[methodArgs.size()]; for (int i = 0; i < bootstrapArgs.size(); i++) { // RoboVM note: Changed to handle InvokeExpr values in bootstrap args Value v = bootstrapArgs.get(i); if (v instanceof InvokeExpr) { this.bsmArgBoxes[i] = Jimple.v().newInvokeExprBox(v); } else { this.bsmArgBoxes[i] = Jimple.v().newImmediateBox(v); } } for (int i = 0; i < methodArgs.size(); i++) { this.argBoxes[i] = Jimple.v().newImmediateBox((Value) methodArgs.get(i)); } }
private SootMethodRef remapRef(SootMethodRef ref) { Type return_type = fixType(ref.returnType()); List params = fixParameterList(ref.parameterTypes()); int modifiers = Modifier.PUBLIC; if (ref.isStatic()) { modifiers += Modifier.STATIC; } SootMethod method = new SootMethod(ref.name(), params, return_type, modifiers); SootClass decl_class = ref.declaringClass(); if (shouldMap(decl_class)) { decl_class = getMapping(decl_class); } method.setDeclaringClass(decl_class); return method.makeRef(); }
@SuppressWarnings("unchecked") public static FunctionType getFunctionType(SootMethodRef methodRef) { Type returnType = getType(methodRef.returnType()); Type[] paramTypes = new Type[(methodRef.isStatic() ? 1 : 2) + methodRef.parameterTypes().size()]; int i = 0; paramTypes[i++] = ENV_PTR; if (!methodRef.isStatic()) { paramTypes[i++] = OBJECT_PTR; } for (soot.Type t : (List<soot.Type>) methodRef.parameterTypes()) { paramTypes[i++] = getType(t); } return new FunctionType(returnType, paramTypes); }
public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(Jimple.DYNAMICINVOKE); buffer.append(" \""); buffer.append(methodRef.name()); // quoted method name (can be any UTF8 string) buffer.append("\" <"); buffer.append( SootMethod.getSubSignature( "" /* no method name here*/, methodRef.parameterTypes(), methodRef.returnType())); buffer.append(">("); for (int i = 0; i < argBoxes.length; i++) { if (i != 0) buffer.append(", "); buffer.append(argBoxes[i].getValue().toString()); } buffer.append(") "); buffer.append(bsmRef.getSignature()); buffer.append("("); for (int i = 0; i < bsmArgBoxes.length; i++) { if (i != 0) buffer.append(", "); buffer.append(bsmArgBoxes[i].getValue().toString()); } buffer.append(")"); return buffer.toString(); }
/** * Finds in class hierarchy and returns all app and lib concrete methods possibly referenced by * method ref. Method is assumed to be virtual (not special or static). Returns true if there are * library methods among targets found. */ public static boolean getConcreteCallTargets( InvokeExpr instInvExpr, /*OUT*/ Set<SootMethod> appTargets, /*OUT*/ Set<SootMethod> libTargets) { // get class of method ref; we start searching from this class SootMethodRef mref = instInvExpr.getMethodRef(); SootClass cls = mref.declaringClass(); // starting class final NumberedString subsignature = mref.getSubSignature(); // signature to search for // CASE 1: object is of declared class type or inherited from some superclass // find first superclass, starting from current cls, that declares method; there HAS to // be such a class // note that if cls is interface, superclass if java.lang.Object // note that we don't check if there is indeed an interface declaring the method; we assume this // is the case if no superclass declares it while (!cls.declaresMethod(subsignature) && cls.hasSuperclass()) cls = cls.getSuperclass(); // never an interface // now, method might not be in superclass, or might be abstract; in that case, it's not a target SootMethod m; if (cls.declaresMethod(subsignature)) { m = cls.getMethod(subsignature); if (!m.isAbstract()) { if (cls.hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } // (only for virtual/interface calls) // CASE 2: object's actual type is a subclass; any subclass declaring the method is a possible // target // we have to check all superclasses of implementers, because starting cls might be // interface if (instInvExpr instanceof VirtualInvokeExpr || instInvExpr instanceof InterfaceInvokeExpr) { cls = mref.declaringClass(); // start again from declaring class List<SootClass> allSubclasses = getAllSubtypes(cls); for (SootClass subCls : allSubclasses) { m = getMethodInClassOrSuperclass(subCls, subsignature); if (m != null && !m.isAbstract()) { if (m.getDeclaringClass().hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } } return !libTargets.isEmpty(); }
public void outAStaticInvokeExpr(AStaticInvokeExpr node) { List args; if (node.getArgList() != null) args = (List) mProductions.removeLast(); else args = new ArrayList(); SootMethodRef method = (SootMethodRef) mProductions.removeLast(); method = Scene.v() .makeMethodRef( method.declaringClass(), method.name(), method.parameterTypes(), method.returnType(), true); mProductions.addLast(Jimple.v().newStaticInvokeExpr(method, args)); }
/** Dumps out the call chain in json format * */ public void dump_json(PrintStream fp, String indent) { fp.printf("%s{ %s,\n", indent, json_field("type", type)); fp.printf("%s %s,\n", indent, json_field("link", link)); String sig = method.getSignature(); fp.printf("%s %s,\n", indent, json_field("signature", sig)); if (stmt != null) { SootMethodRef invoke = stmt.getInvokeExpr().getMethodRef(); String invokeSig; try { SootMethod concrete = SootUtils.resolve(stmt.getInvokeExpr().getMethodRef()); invokeSig = concrete.getSignature(); } catch (CannotFindMethodException e1) { logger.debug("Cannot find concrete method for {} in SourceCallChainInfo.dump_json()", stmt); invokeSig = invoke.getSignature(); } if (!invokeSig.equals(sig)) { fp.printf("%s %s,\n", indent, json_field("source-signature", invokeSig)); } } SourceLocationTag slt = (stmt == null) ? SootUtils.getMethodLocation(method) : getSourceLocation(stmt); if (slt != null) { fp.printf("%s %s", indent, json_field("src-loc")); fp.printf( "{ %s, %s},\n", json_field("class", slt.getClz()), json_field("line", slt.getLine())); } fp.printf("%s %s,\n", indent, json_field("syscalls", syscalls)); fp.printf("%s %s,\n", indent, json_field("calls", calls)); if ((contents != null) && (contents.length > 0)) { fp.printf("%s %s,\n", indent, json_field("score", score)); fp.printf("%s %s [\n", indent, json_field("contents")); String delim = ""; for (SourceCallChainInfo cci : contents) { fp.print(delim); delim = ",\n"; cci.dump_json(fp, indent + " "); } fp.printf("\n%s]}", indent); } else { fp.printf("%s %s\n", indent, json_field("score", score)); fp.printf("%s}", indent); } }
/** For instance invokes */ public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) { final NumberedString mSubsignature = methodRef.getSubSignature(); if (tgtType instanceof RefType) { // find first class upwards in hierarchy, starting from cls, that implements method (i.e., // *concrete* method) SootClass cls = ((RefType) tgtType).getSootClass(); while (!cls.declaresMethod(mSubsignature)) cls = cls .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a // superclass must exist if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method // finally, store resolved app method SootMethod m = cls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); methods.add(m); // just one element, directly resolved return methods; } if (tgtType instanceof AnySubType) { // return set of all app subtypes that implement referenced method SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass(); List subClasses = baseCls.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls) : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); for (Object oSubCls : subClasses) { SootClass subCls = (SootClass) oSubCls; if (subCls.hasTag(ClassTag.TAG_NAME)) { try { SootMethod m = subCls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); if (!m.isAbstract()) methods.add(m); } catch (RuntimeException e) { } } } return methods; } assert tgtType instanceof ArrayType; // only other case observed so far return new ArrayList(); // no array class/method is in app }
public boolean equivTo(Object o) { if (o instanceof JDynamicInvokeExpr) { JDynamicInvokeExpr ie = (JDynamicInvokeExpr) o; if (!(getMethod().equals(ie.getMethod()) && bsmArgBoxes.length == ie.bsmArgBoxes.length)) return false; int i = 0; for (ValueBox element : bsmArgBoxes) { if (!(element.getValue().equivTo(ie.getBootstrapArg(i)))) return false; i++; } if (!(getMethod().equals(ie.getMethod()) && argBoxes.length == ie.argBoxes.length)) return false; i = 0; for (ValueBox element : argBoxes) { if (!(element.getValue().equivTo(ie.getArg(i)))) return false; i++; } if (!methodRef.equals(ie.methodRef)) return false; if (!bsmRef.equals(ie.bsmRef)) return false; return true; } return false; }
public void methodRef(SootMethodRef m) { handleIndent(); output.append(m.name()); }
public BSpecialInvokeInst(SootMethodRef methodRef) { if (methodRef.isStatic()) throw new RuntimeException("wrong static-ness"); this.methodRef = methodRef; }
public Type getType() { return methodRef.returnType(); }
public SootMethod getMethod() { return methodRef.resolve(); }
private Value mutate(Value value) { if (value instanceof FieldRef) { FieldRef ref = (FieldRef) value; SootField field = ref.getField(); Type type = field.getType(); if (type instanceof RefType) { RefType ref_type = (RefType) type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { addField(field, ref); } } else if (type instanceof ArrayType) { ArrayType array_type = (ArrayType) type; Type base_type = array_type.baseType; if (base_type instanceof RefType) { RefType ref_type = (RefType) base_type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { addField(field, ref); } } } SootClass soot_class = field.getDeclaringClass(); if (shouldMap(soot_class)) { addField(field, ref); } return value; } else if (value instanceof InvokeExpr) { InvokeExpr expr = (InvokeExpr) value; SootMethodRef ref = expr.getMethodRef(); SootClass soot_class = ref.declaringClass(); final NumberedString subSignature = ref.getSubSignature(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); if (new_class.declaresMethod(subSignature)) { SootMethod new_method = RootbeerScene.v().getMethod(new_class, subSignature.getString()); addAddedMethod(new_method); fixArguments(new_method); RootbeerScene.v().getDfsInfo().addReachableMethodSig(new_method.getSignature()); expr.setMethodRef(new_method.makeRef()); } } else { if (soot_class.declaresMethod(ref.getSubSignature())) { SootMethod method = soot_class.getMethod(ref.getSubSignature()); fixArguments(method); } } ref = remapRef(ref); try { if (shouldMap(soot_class)) { soot_class = getMapping(soot_class); } SootMethod method = soot_class.getMethod(ref.getSubSignature()); RootbeerScene.v().getDfsInfo().addReachableMethodSig(method.getSignature()); expr.setMethodRef(method.makeRef()); } catch (Exception ex) { // ex.printStackTrace(); } return value; } else if (value instanceof NewExpr) { NewExpr expr = (NewExpr) value; RefType base_type = expr.getBaseType(); SootClass soot_class = base_type.getSootClass(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); expr.setBaseType(new_class.getType()); } return value; } else if (value instanceof NewArrayExpr) { NewArrayExpr expr = (NewArrayExpr) value; Type base_type = expr.getBaseType(); base_type = fixType(base_type); expr.setBaseType(base_type); return value; } else if (value instanceof NewMultiArrayExpr) { NewMultiArrayExpr expr = (NewMultiArrayExpr) value; ArrayType array_type = expr.getBaseType(); Type base_type = array_type.baseType; if (base_type instanceof RefType) { RefType ref_type = (RefType) base_type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); ArrayType new_type = ArrayType.v(new_class.getType(), array_type.numDimensions); expr.setBaseType(new_type); } } return value; } else if (value instanceof CastExpr) { CastExpr expr = (CastExpr) value; Type cast_type = expr.getCastType(); cast_type = fixType(cast_type); expr.setCastType(cast_type); return value; } else if (value instanceof ParameterRef) { ParameterRef ref = (ParameterRef) value; Type new_type = fixType(ref.getType()); return new ParameterRef(new_type, ref.getIndex()); } else if (value instanceof ThisRef) { ThisRef ref = (ThisRef) value; Type new_type = fixType(ref.getType()); return new ThisRef((RefType) new_type); } else if (value instanceof Local) { Local local = (Local) value; Type type = local.getType(); local.setType(fixType(type)); return value; } else { return value; } }
public SootMethod getBootstrapMethod() { return bsmRef.resolve(); }
@SuppressWarnings("unchecked") public static String getDescriptor(SootMethodRef methodRef) { return getDescriptor(methodRef.parameterTypes(), methodRef.returnType()); }