예제 #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;
  }
  /** Parses a {@code Code} attribute. */
  private Attribute code(DirectClassFile cf, int offset, int length, ParseObserver observer) {
    if (length < 12) {
      return throwSeverelyTruncated();
    }

    ByteArray bytes = cf.getBytes();
    ConstantPool pool = cf.getConstantPool();
    int maxStack = bytes.getUnsignedShort(offset); // u2 max_stack
    int maxLocals = bytes.getUnsignedShort(offset + 2); // u2 max_locals
    int codeLength = bytes.getInt(offset + 4); // u4 code_length
    int origOffset = offset;

    if (observer != null) {
      observer.parsed(bytes, offset, 2, "max_stack: " + Hex.u2(maxStack));
      observer.parsed(bytes, offset + 2, 2, "max_locals: " + Hex.u2(maxLocals));
      observer.parsed(bytes, offset + 4, 4, "code_length: " + Hex.u4(codeLength));
    }

    offset += 8;
    length -= 8;

    if (length < (codeLength + 4)) {
      return throwTruncated();
    }

    int codeOffset = offset;
    offset += codeLength;
    length -= codeLength;
    BytecodeArray code = new BytecodeArray(bytes.slice(codeOffset, codeOffset + codeLength), pool);
    if (observer != null) {
      code.forEach(new CodeObserver(code.getBytes(), observer));
    }

    // u2 exception_table_length
    int exceptionTableLength = bytes.getUnsignedShort(offset);
    ByteCatchList catches =
        (exceptionTableLength == 0) ? ByteCatchList.EMPTY : new ByteCatchList(exceptionTableLength);

    if (observer != null) {
      observer.parsed(bytes, offset, 2, "exception_table_length: " + Hex.u2(exceptionTableLength));
    }

    offset += 2;
    length -= 2;

    if (length < (exceptionTableLength * 8 + 2)) {
      return throwTruncated();
    }

    for (int i = 0; i < exceptionTableLength; i++) {
      if (observer != null) {
        observer.changeIndent(1);
      }

      int startPc = bytes.getUnsignedShort(offset);
      int endPc = bytes.getUnsignedShort(offset + 2);
      int handlerPc = bytes.getUnsignedShort(offset + 4);
      int catchTypeIdx = bytes.getUnsignedShort(offset + 6);
      CstType catchType = (CstType) pool.get0Ok(catchTypeIdx);
      catches.set(i, startPc, endPc, handlerPc, catchType);
      if (observer != null) {
        observer.parsed(
            bytes,
            offset,
            8,
            Hex.u2(startPc)
                + ".."
                + Hex.u2(endPc)
                + " -> "
                + Hex.u2(handlerPc)
                + " "
                + ((catchType == null) ? "<any>" : catchType.toHuman()));
      }
      offset += 8;
      length -= 8;

      if (observer != null) {
        observer.changeIndent(-1);
      }
    }

    catches.setImmutable();

    AttributeListParser parser = new AttributeListParser(cf, CTX_CODE, offset, this);
    parser.setObserver(observer);

    StdAttributeList attributes = parser.getList();
    attributes.setImmutable();

    int attributeByteCount = parser.getEndOffset() - offset;
    if (attributeByteCount != length) {
      return throwBadLength(attributeByteCount + (offset - origOffset));
    }

    return new AttCode(maxStack, maxLocals, code, catches, attributes);
  }