diff options
Diffstat (limited to 'dx/src/com/android/dx/command/dump/BlockDumper.java')
-rw-r--r-- | dx/src/com/android/dx/command/dump/BlockDumper.java | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/dx/src/com/android/dx/command/dump/BlockDumper.java b/dx/src/com/android/dx/command/dump/BlockDumper.java deleted file mode 100644 index 0be2fb402..000000000 --- a/dx/src/com/android/dx/command/dump/BlockDumper.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.command.dump; - -import com.android.dx.cf.attrib.AttCode; -import com.android.dx.cf.code.BasicBlocker; -import com.android.dx.cf.code.ByteBlock; -import com.android.dx.cf.code.ByteBlockList; -import com.android.dx.cf.code.ByteCatchList; -import com.android.dx.cf.code.BytecodeArray; -import com.android.dx.cf.code.ConcreteMethod; -import com.android.dx.cf.code.Ropper; -import com.android.dx.cf.direct.CodeObserver; -import com.android.dx.cf.direct.DirectClassFile; -import com.android.dx.cf.direct.StdAttributeFactory; -import com.android.dx.cf.iface.Member; -import com.android.dx.cf.iface.Method; -import com.android.dx.rop.code.BasicBlock; -import com.android.dx.rop.code.BasicBlockList; -import com.android.dx.rop.code.Insn; -import com.android.dx.rop.code.InsnList; -import com.android.dx.rop.code.RopMethod; -import com.android.dx.rop.code.DexTranslationAdvice; -import com.android.dx.rop.code.TranslationAdvice; -import com.android.dx.rop.code.AccessFlags; -import com.android.dx.rop.cst.CstType; -import com.android.dx.ssa.Optimizer; -import com.android.dx.util.ByteArray; -import com.android.dx.util.Hex; -import com.android.dx.util.IntList; - -import java.io.PrintStream; - -/** - * Utility to dump basic block info from methods in a human-friendly form. - */ -public class BlockDumper - extends BaseDumper { - /** whether or not to registerize (make rop blocks) */ - private boolean rop; - - /** - * null-ok; the class file object being constructed; becomes non-null - * during {@link #dump} - */ - protected DirectClassFile classFile; - - /** null-ok; most recently parsed code attribute */ - private AttCode codeAtt; - - /** whether or not to suppress dumping */ - protected boolean suppressDump; - - /** whether this is the first method being dumped */ - private boolean first; - - /** whether or not to run the ssa optimziations */ - private boolean optimize; - - /** - * Dumps the given array, interpreting it as a class file and dumping - * methods with indications of block-level stuff. - * - * @param bytes non-null; bytes of the (alleged) class file - * @param out non-null; where to dump to - * passed in as <= 0 - * @param filePath the file path for the class, excluding any base - * directory specification - * @param rop whether or not to registerize (make rop blocks) - * @param args commandline parsedArgs - */ - public static void dump(byte[] bytes, PrintStream out, - String filePath, boolean rop, Args args) { - BlockDumper bd = - new BlockDumper(bytes, out, filePath, - rop, args); - bd.dump(); - } - - /** - * Constructs an instance. This class is not publicly instantiable. - * Use {@link #dump}. - */ - BlockDumper(byte[] bytes, PrintStream out, - String filePath, - boolean rop, Args args) { - super(bytes, out, filePath, args); - - this.rop = rop; - this.classFile = null; - this.codeAtt = null; - this.suppressDump = true; - this.first = true; - this.optimize = args.optimize; - } - - /** - * Does the dumping. - */ - public void dump() { - byte[] bytes = getBytes(); - ByteArray ba = new ByteArray(bytes); - - /* - * First, parse the file completely, so we can safely refer to - * attributes, etc. - */ - classFile = new DirectClassFile(ba, getFilePath(), getStrictParse()); - classFile.setAttributeFactory(StdAttributeFactory.THE_ONE); - classFile.getMagic(); // Force parsing to happen. - - // Next, reparse it and observe the process. - DirectClassFile liveCf = - new DirectClassFile(ba, getFilePath(), getStrictParse()); - liveCf.setAttributeFactory(StdAttributeFactory.THE_ONE); - liveCf.setObserver(this); - liveCf.getMagic(); // Force parsing to happen. - } - - /** {@inheritDoc} */ - @Override - public void changeIndent(int indentDelta) { - if (!suppressDump) { - super.changeIndent(indentDelta); - } - } - - /** {@inheritDoc} */ - @Override - public void parsed(ByteArray bytes, int offset, int len, String human) { - if (!suppressDump) { - super.parsed(bytes, offset, len, human); - } - } - - /** - * @param name method name - * @return true if this method should be dumped - */ - protected boolean shouldDumpMethod(String name) { - return args.method == null || args.method.equals(name); - } - - /** {@inheritDoc} */ - @Override - public void startParsingMember(ByteArray bytes, int offset, String name, - String descriptor) { - if (descriptor.indexOf('(') < 0) { - // It's a field, not a method - return; - } - - if (!shouldDumpMethod(name)) { - return; - } - - // Reset the dump cursor to the start of the method. - setAt(bytes, offset); - - suppressDump = false; - - if (first) { - first = false; - } else { - parsed(bytes, offset, 0, "\n"); - } - - parsed(bytes, offset, 0, "method " + name + " " + descriptor); - suppressDump = true; - } - - /** {@inheritDoc} */ - @Override - public void endParsingMember(ByteArray bytes, int offset, String name, - String descriptor, Member member) { - if (!(member instanceof Method)) { - return; - } - - if (!shouldDumpMethod(name)) { - return; - } - - ConcreteMethod meth = new ConcreteMethod((Method) member, classFile, - true, true); - - if (rop) { - ropDump(meth); - } else { - regularDump(meth); - } - } - - /** - * Does a regular basic block dump. - * - * @param meth 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; - } - - /** - * Does a registerizing dump. - * - * @param meth non-null; method data to dump - */ - private void ropDump(ConcreteMethod meth) { - BytecodeArray code = meth.getCode(); - ByteArray bytes = code.getBytes(); - - TranslationAdvice advice = DexTranslationAdvice.THE_ONE; - - 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 = Optimizer.optimize(rmeth, paramWidth, isStatic, true, - advice); - } - - BasicBlockList blocks = rmeth.getBlocks(); - - sb.append("first " + Hex.u2(rmeth.getFirstLabel()) + "\n"); - - int sz = blocks.size(); - for (int i = 0; i < sz; i++) { - BasicBlock bb = blocks.get(i); - int label = bb.getLabel(); - sb.append("block "); - sb.append(Hex.u2(label)); - sb.append("\n"); - - IntList preds = rmeth.labelToPredecessors(label); - int psz = preds.size(); - for (int j = 0; j < psz; j++) { - sb.append(" pred "); - sb.append(Hex.u2(preds.get(j))); - sb.append("\n"); - } - - InsnList il = bb.getInsns(); - int ilsz = il.size(); - for (int j = 0; j < ilsz; j++) { - Insn one = il.get(j); - sb.append(" "); - sb.append(il.get(j).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 j = 0; j < ssz; j++) { - int succ = successors.get(j); - 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; - } -} |