예제 #1
1
  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));
    }
  }
예제 #2
0
  public void outANonstaticInvokeExpr(ANonstaticInvokeExpr node) {
    List args;

    if (node.getArgList() != null) args = (List) mProductions.removeLast();
    else args = new ArrayList();

    SootMethodRef method = (SootMethodRef) mProductions.removeLast();

    String local = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(local);
    if (l == null) throw new RuntimeException("did not find local: " + local);

    Node invokeType = (Node) node.getNonstaticInvoke();
    Expr invokeExpr;

    if (invokeType instanceof ASpecialNonstaticInvoke) {
      invokeExpr = Jimple.v().newSpecialInvokeExpr(l, method, args);
    } else if (invokeType instanceof AVirtualNonstaticInvoke) {
      invokeExpr = Jimple.v().newVirtualInvokeExpr(l, method, args);
    } else {
      if (debug)
        if (!(invokeType instanceof AInterfaceNonstaticInvoke))
          throw new RuntimeException("expected interface invoke.");
      invokeExpr = Jimple.v().newInterfaceInvokeExpr(l, method, args);
    }

    mProductions.addLast(invokeExpr);
  }
예제 #3
0
  public void outAIdentityNoTypeStatement(AIdentityNoTypeStatement node) {
    mProductions.removeLast(); // get rid of @caughtexception string presently on top of the stack
    Value local =
        (Value) mLocals.get(mProductions.removeLast()); // the local ref from it's identifier

    Unit u = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
    mProductions.addLast(u);
  }
예제 #4
0
  public static SootMethod mockSootMethod(
      String clsName, String methodSubSignature, boolean isStatic) {
    SootClass sc = mockSootClass(clsName);

    SootMethod sm = null;

    try {
      sm = sc.getMethod(methodSubSignature);
    } catch (Exception ex) {
      sm = null;
    }

    if (null == sm) {
      int m = Modifier.PUBLIC;
      if (isStatic) {
        m = m | Modifier.STATIC;
      }

      List<Type> paramTypes = new ArrayList<Type>();
      paramTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));

      String[] strs = methodSubSignature.split(" ");
      String methodName = strs[1].trim().substring(0, strs[1].trim().indexOf("("));

      if (null == methodName || methodName.isEmpty()) {
        return null;
      }

      sm = new SootMethod(methodName, paramTypes, RefType.v("java.lang.Object"), m);
      sc.addMethod(sm);

      // Add body of sm
      JimpleBody b = Jimple.v().newBody(sm);
      sm.setActiveBody(b);
      // LocalGenerator lg = new LocalGenerator(b);
      {
        b.insertIdentityStmts();

        // Local rtLoc = lg.generateLocal(RefType.v("java.lang.Object"));

        // Local param0 = lg.generateLocal(ArrayType.v(RefType.v("java.lang.Object"), 1));
        // Unit param0U = Jimple.v().newIdentityStmt(rtLoc,
        // Jimple.v().newParameterRef(ArrayType.v(RefType.v("java.lang.Object"), 1), 0));

        // Unit rtLocAssignU = Jimple.v().newAssignStmt(rtLoc, param0);

        Unit returnU = Jimple.v().newReturnStmt(b.getParameterLocal(0));

        // b.getUnits().add(param0U);
        b.getUnits().add(returnU);
      }

      System.out.println("validation:" + b);
      b.validate();
    }

    return sm;
  }
예제 #5
0
  public Object clone() {
    List argList = new ArrayList(getArgCount());

    for (int i = 0; i < getArgCount(); i++) {
      argList.add(i, Jimple.cloneIfNecessary(getArg(i)));
    }

    return new JInterfaceInvokeExpr(Jimple.cloneIfNecessary(getBase()), methodRef, argList);
  }
예제 #6
0
  public void outAGotoStatement(AGotoStatement node) {
    String targetLabel = (String) mProductions.removeLast();

    UnitBox box = Jimple.v().newStmtBox(null);
    Unit branch = Jimple.v().newGotoStmt(box);

    addBoxToPatch(targetLabel, box);

    mProductions.addLast(branch);
  }
예제 #7
0
  public void outAIfStatement(AIfStatement node) {
    String targetLabel = (String) mProductions.removeLast();
    Value condition = (Value) mProductions.removeLast();

    UnitBox box = Jimple.v().newStmtBox(null);
    Unit u = Jimple.v().newIfStmt(condition, box);

    addBoxToPatch(targetLabel, box);

    mProductions.addLast(u);
  }
예제 #8
0
  public void outAReturnStatement(AReturnStatement node) {
    Value v;
    Stmt s = null;
    if (node.getImmediate() != null) {
      v = (Value) mProductions.removeLast();
      s = Jimple.v().newReturnStmt(v);
    } else {
      s = Jimple.v().newReturnVoidStmt();
    }

    mProductions.addLast(s);
  }
예제 #9
0
 public void jimplify(DexBody body) {
   TwoRegisterInstruction i = (TwoRegisterInstruction) instruction;
   int dest = i.getRegisterA();
   int object = i.getRegisterB();
   FieldIdItem f = (FieldIdItem) ((InstructionWithReference) instruction).getReferencedItem();
   InstanceFieldRef r =
       Jimple.v().newInstanceFieldRef(body.getRegisterLocal(object), getSootFieldRef(f));
   assign = Jimple.v().newAssignStmt(body.getRegisterLocal(dest), r);
   setUnit(assign);
   tagWithLineNumber(assign);
   body.add(assign);
 }
예제 #10
0
  public void jimplify(DexBody body) {
    if (!(instruction instanceof Instruction31t))
      throw new IllegalArgumentException(
          "Expected Instruction31t but got: " + instruction.getClass());

    Instruction31t fillArrayInstr = (Instruction31t) instruction;
    int destRegister = fillArrayInstr.getRegisterA();
    int offset = fillArrayInstr.getCodeOffset();
    int targetAddress = codeAddress + offset;

    Instruction referenceTable = body.instructionAtAddress(targetAddress).instruction;

    if (!(referenceTable instanceof ArrayPayload)) {
      throw new RuntimeException(
          "Address " + targetAddress + "refers to an invalid PseudoInstruction.");
    }

    ArrayPayload arrayTable = (ArrayPayload) referenceTable;

    //        NopStmt nopStmtBeginning = Jimple.v().newNopStmt();
    //        body.add(nopStmtBeginning);

    Local arrayReference = body.getRegisterLocal(destRegister);
    List<Number> elements = arrayTable.getArrayElements();
    int numElements = elements.size();

    Stmt firstAssign = null;
    for (int i = 0; i < numElements; i++) {
      ArrayRef arrayRef = Jimple.v().newArrayRef(arrayReference, IntConstant.v(i));
      NumericConstant element = getArrayElement(elements.get(i), body, destRegister);
      if (element
          == null) // array was not defined -> element type can not be found (obfuscated bytecode?)
      break;
      AssignStmt assign = Jimple.v().newAssignStmt(arrayRef, element);
      addTags(assign);
      body.add(assign);
      if (i == 0) {
        firstAssign = assign;
      }
    }
    if (firstAssign == null) { // if numElements == 0. Is it possible?
      firstAssign = Jimple.v().newNopStmt();
      body.add(firstAssign);
    }

    //        NopStmt nopStmtEnd = Jimple.v().newNopStmt();
    //        body.add(nopStmtEnd);

    //        defineBlock(nopStmtBeginning, nopStmtEnd);
    setUnit(firstAssign);
  }
예제 #11
0
  public void outAInvokeStatement(AInvokeStatement node) {
    Value op = (Value) mProductions.removeLast();

    Unit u = Jimple.v().newInvokeStmt(op);

    mProductions.addLast(u);
  }
예제 #12
0
  public void outALookupswitchStatement(ALookupswitchStatement node) {
    List lookupValues = new ArrayList();
    List targets = new ArrayList();
    UnitBox defaultTarget = null;

    if (node.getCaseStmt() != null) {
      int size = node.getCaseStmt().size();

      for (int i = 0; i < size; i++) {
        Object valueTargetPair = mProductions.removeLast();
        if (valueTargetPair instanceof UnitBox) {
          if (defaultTarget != null)
            throw new RuntimeException("error: can't ;have more than 1 default stmt");

          defaultTarget = (UnitBox) valueTargetPair;
        } else {
          Object[] pair = (Object[]) valueTargetPair;

          lookupValues.add(0, pair[0]);
          targets.add(0, pair[1]);
        }
      }
    } else {
      throw new RuntimeException("error: switch stmt has no case stmts");
    }

    Value key = (Value) mProductions.removeLast();
    Unit switchStmt = Jimple.v().newLookupSwitchStmt(key, lookupValues, targets, defaultTarget);

    mProductions.addLast(switchStmt);
  }
예제 #13
0
  public void outAAssignStatement(AAssignStatement node) {
    Value rvalue = (Value) mProductions.removeLast();
    Value variable = (Value) mProductions.removeLast();

    Unit u = Jimple.v().newAssignStmt(variable, rvalue);
    mProductions.addLast(u);
  }
예제 #14
0
  AbstractStaticInvokeExpr(SootMethodRef methodRef, List args) {
    super.methodRef = methodRef;
    super.argBoxes = new ArrayList();

    for (int i = 0; i < args.size(); i++)
      this.argBoxes.add(Jimple.v().newImmediateBox((Value) args.get(i)));
  }
예제 #15
0
 public void jimplify(DexBody body) {
   Instruction11x throwInstruction = (Instruction11x) instruction;
   throwStmt = Jimple.v().newThrowStmt(body.getRegisterLocal(throwInstruction.getRegisterA()));
   setUnit(throwStmt);
   tagWithLineNumber(throwStmt);
   body.add(throwStmt);
 }
예제 #16
0
  private List<Unit> instrumentIntentAddings(
      BiDiInterproceduralCFG<Unit, SootMethod> cfg,
      Unit unit,
      InvokeExpr sinkExpr,
      Set<ResultSourceInfo> sourceInfo) {
    if (isMethodInterComponentSink(sinkExpr.getMethod())) {
      SootMethod method = cfg.getMethodOf(unit);
      Body body = null;
      if (method.hasActiveBody()) body = method.retrieveActiveBody();
      else throw new RuntimeException("No body found!");

      Set<String> sourceCategories = getDataIdList(sourceInfo);

      final String hashSetType = "java.util.HashSet";
      List<Unit> generated = new ArrayList<Unit>();

      // HashSet initialization
      Local hashSetLocal = generateFreshLocal(body, RefType.v(hashSetType));
      NewExpr newExpr = Jimple.v().newNewExpr(RefType.v(hashSetType));
      AssignStmt assignStmt = Jimple.v().newAssignStmt(hashSetLocal, newExpr);
      generated.add(assignStmt);

      // constructor call
      SpecialInvokeExpr constructorCall =
          Jimple.v()
              .newSpecialInvokeExpr(
                  hashSetLocal,
                  Scene.v().getMethod("<java.util.HashSet: void <init>()>").makeRef());
      InvokeStmt constructorCallStmt = Jimple.v().newInvokeStmt(constructorCall);
      generated.add(constructorCallStmt);

      // add categories to HashSet
      for (String cat : sourceCategories) {
        InterfaceInvokeExpr addCall =
            Jimple.v()
                .newInterfaceInvokeExpr(
                    hashSetLocal,
                    Scene.v().getMethod("<java.util.Set: boolean add(java.lang.Object)>").makeRef(),
                    StringConstant.v(cat));
        InvokeStmt addCallStmt = Jimple.v().newInvokeStmt(addCall);
        generated.add(addCallStmt);
      }

      // get Intent
      Value intent = sinkExpr.getArg(0);
      List<Object> args = new ArrayList<Object>();
      args.add(RefType.v("android.content.Intent"));
      args.add(intent);
      args.add(RefType.v(hashSetType));
      args.add(hashSetLocal);
      StaticInvokeExpr sie =
          Instrumentation.createJimpleStaticInvokeExpr(
              Settings.INSTRUMENTATION_HELPER_JAVA, "addTaintInformationToIntent", args);
      InvokeStmt invStmt = Jimple.v().newInvokeStmt(sie);
      generated.add(invStmt);

      return generated;
    }
    return Collections.emptyList();
  }
예제 #17
0
  /**
   * Generate a default assignment with 'local' as left-hand-side value.
   *
   * @param local
   * @return
   */
  private Unit createCorrectDummyAssignment(Local local) {
    Unit dummyAssignemnt = null;
    if (local.getType() instanceof PrimType) {
      if (local.getType() instanceof IntType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyInteger", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof BooleanType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyBoolean", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof ByteType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyByte", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof CharType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(
                Settings.SANITIZER, "dummyCharacter", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof DoubleType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyDouble", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof FloatType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyFloat", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof LongType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyLong", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof ShortType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyShort", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else throw new RuntimeException("Oops, the primitive type is not correct");
    } else {
      if (local.getType().equals(RefType.v("java.lang.String")))
        dummyAssignemnt = Jimple.v().newAssignStmt(local, StringConstant.v(""));
      else dummyAssignemnt = Jimple.v().newAssignStmt(local, NullConstant.v());
    }

    return dummyAssignemnt;
  }
예제 #18
0
  public void outAArrayRef(AArrayRef node) {
    Value immediate = (Value) mProductions.removeLast();
    String identifier = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(identifier);
    if (l == null) throw new RuntimeException("did not find local: " + identifier);

    mProductions.addLast(Jimple.v().newArrayRef(l, immediate));
  }
예제 #19
0
  public void outALocalFieldRef(ALocalFieldRef node) {
    SootFieldRef field = (SootFieldRef) mProductions.removeLast();

    String local = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(local);
    if (l == null) throw new RuntimeException("did not find local: " + local);

    mProductions.addLast(Jimple.v().newInstanceFieldRef(l, field));
  }
예제 #20
0
  public void outACatchClause(ACatchClause node) {
    String exceptionName;
    UnitBox withUnit, fromUnit, toUnit;

    withUnit = Jimple.v().newStmtBox(null);
    addBoxToPatch((String) mProductions.removeLast(), withUnit);

    toUnit = Jimple.v().newStmtBox(null);
    addBoxToPatch((String) mProductions.removeLast(), toUnit);

    fromUnit = Jimple.v().newStmtBox(null);
    addBoxToPatch((String) mProductions.removeLast(), fromUnit);

    exceptionName = (String) mProductions.removeLast();

    Trap trap =
        Jimple.v().newTrap(mResolver.makeClassRef(exceptionName), fromUnit, toUnit, withUnit);
    mProductions.addLast(trap);
  }
예제 #21
0
  public void jimplify(DexBody body) {
    if (!(instruction instanceof Instruction21c))
      throw new IllegalArgumentException(
          "Expected Instruction21c but got: " + instruction.getClass());

    Instruction21c checkCastInstr = (Instruction21c) instruction;

    Local castValue = body.getRegisterLocal(checkCastInstr.getRegisterA());
    Type checkCastType = DexType.toSoot((TypeIdItem) checkCastInstr.getReferencedItem());

    CastExpr castExpr = Jimple.v().newCastExpr(castValue, checkCastType);

    // generate "x = (Type) x"
    // splitter will take care of the rest
    assign = Jimple.v().newAssignStmt(castValue, castExpr);

    setUnit(assign);
    tagWithLineNumber(assign);
    body.add(assign);
  }
예제 #22
0
  public void outAIdentityStatement(AIdentityStatement node) {
    Type identityRefType = (Type) mProductions.removeLast();
    String atClause = (String) mProductions.removeLast();
    Value local =
        (Value) mLocals.get(mProductions.removeLast()); // the local ref from it's identifier

    Value ref = null;
    if (atClause.startsWith("@this")) {
      ref = Jimple.v().newThisRef((RefType) identityRefType);
    } else if (atClause.startsWith("@parameter")) {
      int index = Integer.parseInt(atClause.substring(10, atClause.length() - 1));

      ref = Jimple.v().newParameterRef(identityRefType, index);
    } else
      throw new RuntimeException(
          "shouldn't @caughtexception be handled by outAIdentityNoTypeStatement: got" + atClause);

    Unit u = Jimple.v().newIdentityStmt(local, ref);
    mProductions.addLast(u);
  }
예제 #23
0
  /**
   * @param parameter
   * @param body
   * @return
   */
  private Pair<Value, List<Unit>> generateParameterArray(List<Value> parameter, Body body) {
    List<Unit> generated = new ArrayList<Unit>();

    NewArrayExpr arrayExpr =
        Jimple.v().newNewArrayExpr(RefType.v("java.lang.Object"), IntConstant.v(parameter.size()));

    Value newArrayLocal = generateFreshLocal(body, getParameterArrayType());
    Unit newAssignStmt = Jimple.v().newAssignStmt(newArrayLocal, arrayExpr);
    generated.add(newAssignStmt);

    for (int i = 0; i < parameter.size(); i++) {
      Value index = IntConstant.v(i);
      ArrayRef leftSide = Jimple.v().newArrayRef(newArrayLocal, index);
      Value rightSide = generateCorrectObject(body, parameter.get(i), generated);

      Unit parameterInArray = Jimple.v().newAssignStmt(leftSide, rightSide);
      generated.add(parameterInArray);
    }

    return new Pair<Value, List<Unit>>(newArrayLocal, generated);
  }
예제 #24
0
  public void outADeclaration(ADeclaration node) {
    List localNameList = (List) mProductions.removeLast();
    Type type = (Type) mProductions.removeLast();
    Iterator it = localNameList.iterator();
    List localList = new ArrayList();

    while (it.hasNext()) {
      Local l = Jimple.v().newLocal((String) it.next(), type);
      mLocals.put(l.getName(), l);
      localList.add(l);
    }
    mProductions.addLast(localList);
  }
예제 #25
0
  /**
   * Create a method conveniently. The method is added to the class "TestClass". Parameters can be
   * given as an (positional) array of local variables (the "identity statements", required by Soot
   * to map parameters to local variables, are inserted automatically)
   */
  public SootMethod makeMethod(
      int modifier, String name, List<Local> params, soot.Type retType, List<Unit> bodyStmts) {
    SootMethod m =
        new SootMethod(
            name, params.stream().map(Local::getType).collect(toList()), retType, modifier);
    this.testClass.addMethod(m);
    Body body = Jimple.v().newBody(m);
    m.setActiveBody(body);

    // set the statements for the body.. first the identity statements, then the bodyStmts
    if (!m.isStatic()) {
      body.getLocals().add(localThis);
      body.getUnits()
          .add(Jimple.v().newIdentityStmt(localThis, Jimple.v().newThisRef(testClass.getType())));
    }
    IntStream.range(0, params.size())
        .forEach(
            pos -> {
              Local l = params.get(pos);
              ParameterRef pr = Jimple.v().newParameterRef(l.getType(), pos);
              body.getUnits().add(Jimple.v().newIdentityStmt(l, pr));
            });
    body.getUnits().addAll(bodyStmts);

    // set the locals for the body
    Set<Local> locals =
        Stream.concat(
                params.stream(),
                body.getUseAndDefBoxes()
                    .stream()
                    .filter(b -> b.getValue() instanceof Local)
                    .map(b -> (Local) b.getValue()))
            .collect(toSet());
    locals.removeAll(body.getLocals());
    body.getLocals().addAll(locals);

    return m;
  }
예제 #26
0
public class G {
  public static final Jimple jimple = Jimple.v();

  static final SootClass innerClass;
  static final String innerClassStr = "edu.gatech.util.innerClass";

  static final SootMethodRef testMethodRef;

  static {
    innerClass = Scene.v().getSootClass(innerClassStr);

    testMethodRef = innerClass.getMethod("void test()").makeRef();
  }
}
예제 #27
0
  public void toString(UnitPrinter up) {
    up.literal(Jimple.v().STATICINVOKE);
    up.literal(" ");
    up.methodRef(methodRef);
    up.literal("(");

    for (int i = 0; i < argBoxes.size(); i++) {
      if (i != 0) up.literal(", ");

      getArgBox(i).toString(up);
    }

    up.literal(")");
  }
예제 #28
0
  public String toString() {
    StringBuffer buffer = new StringBuffer();

    buffer.append(Jimple.v().STATICINVOKE + " " + methodRef.getSignature() + "(");

    for (int i = 0; i < argBoxes.size(); i++) {
      if (i != 0) buffer.append(", ");

      buffer.append(getArg(i).toString());
    }

    buffer.append(")");

    return buffer.toString();
  }
  public static SootMethod createSootMethod(
      SootClass sootClass, String name, List<Type> paramTypes, Type returnType, boolean isStatic) {
    int modifier = Modifier.PUBLIC;

    if (isStatic) {
      modifier = modifier | Modifier.STATIC;
    }

    SootMethod sootMethod = new SootMethod(name, paramTypes, returnType, modifier);
    sootClass.addMethod(sootMethod);

    Body body = Jimple.v().newBody(sootMethod);
    sootMethod.setActiveBody(body);

    return sootMethod;
  }
예제 #30
0
  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));
  }