Example #1
0
  /**
   * Does a regular basic block dump.
   *
   * @param meth {@code non-null;} method data to dump
   */
  private void regularDump(ConcreteMethod meth) {
    BytecodeArray code = meth.getCode();
    ByteArray bytes = code.getBytes();
    ByteBlockList list = BasicBlocker.identifyBlocks(meth);
    int sz = list.size();
    CodeObserver codeObserver = new CodeObserver(bytes, BlockDumper.this);

    // Reset the dump cursor to the start of the bytecode.
    setAt(bytes, 0);

    suppressDump = false;

    int byteAt = 0;
    for (int i = 0; i < sz; i++) {
      ByteBlock bb = list.get(i);
      int start = bb.getStart();
      int end = bb.getEnd();

      if (byteAt < start) {
        parsed(bytes, byteAt, start - byteAt, "dead code " + Hex.u2(byteAt) + ".." + Hex.u2(start));
      }

      parsed(
          bytes,
          start,
          0,
          "block " + Hex.u2(bb.getLabel()) + ": " + Hex.u2(start) + ".." + Hex.u2(end));
      changeIndent(1);

      int len;
      for (int j = start; j < end; j += len) {
        len = code.parseInstruction(j, codeObserver);
        codeObserver.setPreviousOffset(j);
      }

      IntList successors = bb.getSuccessors();
      int ssz = successors.size();
      if (ssz == 0) {
        parsed(bytes, end, 0, "returns");
      } else {
        for (int j = 0; j < ssz; j++) {
          int succ = successors.get(j);
          parsed(bytes, end, 0, "next " + Hex.u2(succ));
        }
      }

      ByteCatchList catches = bb.getCatches();
      int csz = catches.size();
      for (int j = 0; j < csz; j++) {
        ByteCatchList.Item one = catches.get(j);
        CstType exceptionClass = one.getExceptionClass();
        parsed(
            bytes,
            end,
            0,
            "catch "
                + ((exceptionClass == CstType.OBJECT) ? "<any>" : exceptionClass.toHuman())
                + " -> "
                + Hex.u2(one.getHandlerPc()));
      }

      changeIndent(-1);
      byteAt = end;
    }

    int end = bytes.size();
    if (byteAt < end) {
      parsed(bytes, byteAt, end - byteAt, "dead code " + Hex.u2(byteAt) + ".." + Hex.u2(end));
    }

    suppressDump = true;
  }
Example #2
0
  /**
   * Does a registerizing dump.
   *
   * @param meth {@code non-null;} method data to dump
   */
  private void ropDump(ConcreteMethod meth) {
    TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
    BytecodeArray code = meth.getCode();
    ByteArray bytes = code.getBytes();
    RopMethod rmeth = Ropper.convert(meth, advice);
    StringBuffer sb = new StringBuffer(2000);

    if (optimize) {
      boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
      int paramWidth = computeParamWidth(meth, isStatic);
      rmeth = new Optimizer().optimize(rmeth, paramWidth, isStatic, true, advice);
    }

    BasicBlockList blocks = rmeth.getBlocks();
    int[] order = blocks.getLabelsInOrder();

    sb.append("first " + Hex.u2(rmeth.getFirstLabel()) + "\n");

    for (int label : order) {
      BasicBlock bb = blocks.get(blocks.indexOfLabel(label));
      sb.append("block ");
      sb.append(Hex.u2(label));
      sb.append("\n");

      IntList preds = rmeth.labelToPredecessors(label);
      int psz = preds.size();
      for (int i = 0; i < psz; i++) {
        sb.append("  pred ");
        sb.append(Hex.u2(preds.get(i)));
        sb.append("\n");
      }

      InsnList il = bb.getInsns();
      int ilsz = il.size();
      for (int i = 0; i < ilsz; i++) {
        Insn one = il.get(i);
        sb.append("  ");
        sb.append(il.get(i).toHuman());
        sb.append("\n");
      }

      IntList successors = bb.getSuccessors();
      int ssz = successors.size();
      if (ssz == 0) {
        sb.append("  returns\n");
      } else {
        int primary = bb.getPrimarySuccessor();
        for (int i = 0; i < ssz; i++) {
          int succ = successors.get(i);
          sb.append("  next ");
          sb.append(Hex.u2(succ));

          if ((ssz != 1) && (succ == primary)) {
            sb.append(" *");
          }

          sb.append("\n");
        }
      }
    }

    suppressDump = false;
    setAt(bytes, 0);
    parsed(bytes, 0, bytes.size(), sb.toString());
    suppressDump = true;
  }
Example #3
0
  /**
   * Processes the methods of the given class.
   *
   * @param cf {@code non-null;} class being translated
   * @param cfOptions {@code non-null;} options for class translation
   * @param dexOptions {@code non-null;} options for dex output
   * @param out {@code non-null;} output class
   */
  private static void processMethods(
      DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, ClassDefItem out) {
    CstType thisClass = cf.getThisClass();
    MethodList methods = cf.getMethods();
    int sz = methods.size();

    for (int i = 0; i < sz; i++) {
      Method one = methods.get(i);
      try {
        CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
        int accessFlags = one.getAccessFlags();
        boolean isStatic = AccessFlags.isStatic(accessFlags);
        boolean isPrivate = AccessFlags.isPrivate(accessFlags);
        boolean isNative = AccessFlags.isNative(accessFlags);
        boolean isAbstract = AccessFlags.isAbstract(accessFlags);
        boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
        DalvCode code;

        if (isNative || isAbstract) {
          // There's no code for native or abstract methods.
          code = null;
        } else {
          ConcreteMethod concrete =
              new ConcreteMethod(
                  one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);

          TranslationAdvice advice;

          advice = DexTranslationAdvice.THE_ONE;

          RopMethod rmeth = Ropper.convert(concrete, advice);
          RopMethod nonOptRmeth = null;
          int paramSize;

          paramSize = meth.getParameterWordCount(isStatic);

          String canonicalName =
              thisClass.getClassType().getDescriptor() + "." + one.getName().getString();

          if (cfOptions.optimize && OptimizerOptions.shouldOptimize(canonicalName)) {
            if (DEBUG) {
              System.err.println("Optimizing " + canonicalName);
            }

            nonOptRmeth = rmeth;
            rmeth = Optimizer.optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);

            if (DEBUG) {
              OptimizerOptions.compareOptimizerStep(
                  nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
            }

            if (cfOptions.statistics) {
              CodeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
            }
          }

          LocalVariableInfo locals = null;

          if (cfOptions.localInfo) {
            locals = LocalVariableExtractor.extract(rmeth);
          }

          code =
              RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);

          if (cfOptions.statistics && nonOptRmeth != null) {
            updateDexStatistics(
                cfOptions,
                dexOptions,
                rmeth,
                nonOptRmeth,
                locals,
                paramSize,
                concrete.getCode().size());
          }
        }

        // Preserve the synchronized flag as its "declared" variant...
        if (AccessFlags.isSynchronized(accessFlags)) {
          accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;

          /*
           * ...but only native methods are actually allowed to be
           * synchronized.
           */
          if (!isNative) {
            accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
          }
        }

        if (isConstructor) {
          accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
        }

        TypeList exceptions = AttributeTranslator.getExceptions(one);
        EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);

        if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
          out.addDirectMethod(mi);
        } else {
          out.addVirtualMethod(mi);
        }

        Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
        if (annotations.size() != 0) {
          out.addMethodAnnotations(meth, annotations);
        }

        AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
        if (list.size() != 0) {
          out.addParameterAnnotations(meth, list);
        }
      } catch (RuntimeException ex) {
        String msg =
            "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
        throw ExceptionWithContext.withContext(ex, msg);
      }
    }
  }