diff --git a/baksmali/src/main/java/org/jf/baksmali/main.java b/baksmali/src/main/java/org/jf/baksmali/main.java index 49a49e48..82600295 100644 --- a/baksmali/src/main/java/org/jf/baksmali/main.java +++ b/baksmali/src/main/java/org/jf/baksmali/main.java @@ -182,7 +182,7 @@ public class main { } //Read in and parse the dex file - DexFile dexFile = new DexFile(dexFileFile, !fixRegisters); + DexFile dexFile = new DexFile(dexFileFile, !fixRegisters, false); Deodexerant deodexerant = null; diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java index c9635468..7cb49266 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java @@ -58,7 +58,7 @@ public class ClassPath { DexFile dexFile; try { - dexFile = new DexFile(file); + dexFile = new DexFile(file, false, true); } catch (Exception ex) { throw ExceptionWithContext.withContext(ex, "Error while reading ClassPath entry \"" + bootClassPathEntry + "\"."); diff --git a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java index 1409db84..49d4c1f4 100644 --- a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java @@ -148,57 +148,80 @@ public class CodeItem extends Item { if (this.debugInfo != null) { this.debugInfo.setParent(this); } + int instructionCount = in.readInt(); - final ArrayList instructionList = new ArrayList(); + if (dexFile.skipInstructions()) { + in.skipBytes(instructionCount * 2); - byte[] encodedInstructions = in.readBytes(instructionCount * 2); - InstructionIterator.IterateInstructions(dexFile, encodedInstructions, - new InstructionIterator.ProcessInstructionDelegate() { - public void ProcessInstruction(int codeAddress, Instruction instruction) { - instructionList.add(instruction); + if (triesCount > 0) { + in.alignTo(4); + in.skipBytes(8 * triesCount); + + int handlerCount = in.readUnsignedLeb128(); + for (int i=0; i 0) { - in.alignTo(4); - - //we need to read in the catch handlers first, so save the offset to the try items for future reference - int triesOffset = in.getCursor(); - in.setCursor(triesOffset + 8 * triesCount); - - //read in the encoded catch handlers - int encodedHandlerStart = in.getCursor(); - int handlerCount = in.readUnsignedLeb128(); - SparseArray handlerMap = new SparseArray(handlerCount); - encodedCatchHandlers = new EncodedCatchHandler[handlerCount]; - for (int i=0; i instructionList = new ArrayList(); - //now go back and read the tries - in.setCursor(triesOffset); - tries = new TryItem[triesCount]; - for (int i=0; i 0) { + in.alignTo(4); + + //we need to read in the catch handlers first, so save the offset to the try items for future reference + int triesOffset = in.getCursor(); + in.setCursor(triesOffset + 8 * triesCount); + + //read in the encoded catch handlers + int encodedHandlerStart = in.getCursor(); + int handlerCount = in.readUnsignedLeb128(); + SparseArray handlerMap = new SparseArray(handlerCount); + encodedCatchHandlers = new EncodedCatchHandler[handlerCount]; + for (int i=0; i { /** * @return the "Catch All" handler address for this EncodedCatchHandler, or -1 if there - * is no "Catch All" handler + * is no "Catch All" handler */ public int getCatchAllHandlerAddress() { return catchAllHandlerAddress; diff --git a/dexlib/src/main/java/org/jf/dexlib/DexFile.java b/dexlib/src/main/java/org/jf/dexlib/DexFile.java index c2de17df..b12ff4e8 100644 --- a/dexlib/src/main/java/org/jf/dexlib/DexFile.java +++ b/dexlib/src/main/java/org/jf/dexlib/DexFile.java @@ -30,7 +30,7 @@ package org.jf.dexlib; import org.jf.dexlib.Util.*; import org.jf.dexlib.*; -import org.jf.dexlib.Item; +import org.jf.dexlib.Item; import org.jf.dexlib.StringDataItem; import java.io.*; @@ -139,6 +139,13 @@ public class DexFile */ private final boolean preserveSignedRegisters; + /** + * When true, any instructions in a code item are skipped over instead of being read in. This is useful when + * you only need the information about the classes and their methods, for example, when loading the BOOTCLASSPATH + * jars in order to analyze a dex file + */ + private final boolean skipInstructions; + /** * When true, this prevents any sorting of the items during placement of the dex file. This * should *only* be set to true when this dex file was read in from an existing (valid) dex file, @@ -184,11 +191,13 @@ public class DexFile /** * A private constructor containing common code to initialize the section maps and lists * @param preserveSignedRegisters If true, keep track of any registers in the debug information + * @param skipInstructions If true, skip the instructions in any code item. * that are signed, so they will be written in the same format. See * getPreserveSignedRegisters() */ - private DexFile(boolean preserveSignedRegisters) { + private DexFile(boolean preserveSignedRegisters, boolean skipInstructions) { this.preserveSignedRegisters = preserveSignedRegisters; + this.skipInstructions = skipInstructions; sectionsByType = new Section[] { StringIdsSection, @@ -242,7 +251,7 @@ public class DexFile */ public DexFile(String file) throws IOException { - this(new File(file), true); + this(new File(file), true, false); } /** @@ -252,12 +261,13 @@ public class DexFile * @param file The dex file to read in * @param preserveSignedRegisters If true, keep track of any registers in the debug information * that are signed, so they will be written in the same format. See + * @param skipInstructions If true, skip the instructions in any code item. * getPreserveSignedRegisters() * @throws IOException if an IOException occurs */ - public DexFile(String file, boolean preserveSignedRegisters) + public DexFile(String file, boolean preserveSignedRegisters, boolean skipInstructions) throws IOException { - this(new File(file), preserveSignedRegisters); + this(new File(file), preserveSignedRegisters, skipInstructions); } /** @@ -267,7 +277,7 @@ public class DexFile */ public DexFile(File file) throws IOException { - this(file, true); + this(file, true, false); } /** @@ -277,12 +287,13 @@ public class DexFile * @param file The dex file to read in * @param preserveSignedRegisters If true, keep track of any registers in the debug information * that are signed, so they will be written in the same format. + * @param skipInstructions If true, skip the instructions in any code item. * @see #getPreserveSignedRegisters * @throws IOException if an IOException occurs */ - public DexFile(File file, boolean preserveSignedRegisters) + public DexFile(File file, boolean preserveSignedRegisters, boolean skipInstructions) throws IOException { - this(preserveSignedRegisters); + this(preserveSignedRegisters, skipInstructions); long fileLength; byte[] magic = FileUtils.readFile(file, 0, 8); @@ -415,7 +426,7 @@ public class DexFile * the Section.intern() method of ClassDefsSection */ public DexFile() { - this(true); + this(true, false); } /** @@ -457,6 +468,16 @@ public class DexFile return preserveSignedRegisters; } + /** + * Get a boolean value indicating whether to skip any instructions in a code item while reading in the dex file. + * This is useful when you only need the information about the classes and their methods, for example, when + * loading the BOOTCLASSPATH jars in order to analyze a dex file + * @return a boolean value indicating whether to skip any instructions in a code item + */ + public boolean skipInstructions() { + return skipInstructions; + } + /** * Get a boolean value indicating whether all items should be placed into a * (possibly arbitrary) "canonical" ordering. If false, then only the items