mirror of
https://github.com/revanced/smali.git
synced 2025-06-12 12:17:37 +02:00
Don't load the instructions in a code item when loading the BOOTCLASSPATH dex files
git-svn-id: https://smali.googlecode.com/svn/trunk@623 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
@ -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 + "\".");
|
||||
|
@ -148,57 +148,80 @@ public class CodeItem extends Item<CodeItem> {
|
||||
if (this.debugInfo != null) {
|
||||
this.debugInfo.setParent(this);
|
||||
}
|
||||
|
||||
int instructionCount = in.readInt();
|
||||
|
||||
final ArrayList<Instruction> instructionList = new ArrayList<Instruction>();
|
||||
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<handlerCount; i++) {
|
||||
int size = in.readSignedLeb128();
|
||||
int absSize = Math.abs(size);
|
||||
for (int j=0; j<absSize; j++) {
|
||||
in.readUnsignedLeb128();
|
||||
in.readUnsignedLeb128();
|
||||
}
|
||||
if (size <= 0) {
|
||||
in.readUnsignedLeb128();
|
||||
}
|
||||
});
|
||||
|
||||
this.instructions = new Instruction[instructionList.size()];
|
||||
instructionList.toArray(instructions);
|
||||
|
||||
if (triesCount > 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<EncodedCatchHandler> handlerMap = new SparseArray<EncodedCatchHandler>(handlerCount);
|
||||
encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
|
||||
for (int i=0; i<handlerCount; i++) {
|
||||
try {
|
||||
int position = in.getCursor() - encodedHandlerStart;
|
||||
encodedCatchHandlers[i] = new EncodedCatchHandler(dexFile, in);
|
||||
handlerMap.append(position, encodedCatchHandlers[i]);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading EncodedCatchHandler at index " + i);
|
||||
}
|
||||
}
|
||||
int codeItemEnd = in.getCursor();
|
||||
} else {
|
||||
final ArrayList<Instruction> instructionList = new ArrayList<Instruction>();
|
||||
|
||||
//now go back and read the tries
|
||||
in.setCursor(triesOffset);
|
||||
tries = new TryItem[triesCount];
|
||||
for (int i=0; i<triesCount; i++) {
|
||||
try {
|
||||
tries[i] = new TryItem(in, handlerMap);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading TryItem at index " + i);
|
||||
byte[] encodedInstructions = in.readBytes(instructionCount * 2);
|
||||
InstructionIterator.IterateInstructions(dexFile, encodedInstructions,
|
||||
new InstructionIterator.ProcessInstructionDelegate() {
|
||||
public void ProcessInstruction(int codeAddress, Instruction instruction) {
|
||||
instructionList.add(instruction);
|
||||
}
|
||||
});
|
||||
|
||||
this.instructions = new Instruction[instructionList.size()];
|
||||
instructionList.toArray(instructions);
|
||||
|
||||
if (triesCount > 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<EncodedCatchHandler> handlerMap = new SparseArray<EncodedCatchHandler>(handlerCount);
|
||||
encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
|
||||
for (int i=0; i<handlerCount; i++) {
|
||||
try {
|
||||
int position = in.getCursor() - encodedHandlerStart;
|
||||
encodedCatchHandlers[i] = new EncodedCatchHandler(dexFile, in);
|
||||
handlerMap.append(position, encodedCatchHandlers[i]);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading EncodedCatchHandler at index " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
int codeItemEnd = in.getCursor();
|
||||
|
||||
//and now back to the end of the code item
|
||||
in.setCursor(codeItemEnd);
|
||||
//now go back and read the tries
|
||||
in.setCursor(triesOffset);
|
||||
tries = new TryItem[triesCount];
|
||||
for (int i=0; i<triesCount; i++) {
|
||||
try {
|
||||
tries[i] = new TryItem(in, handlerMap);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while reading TryItem at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
//and now back to the end of the code item
|
||||
in.setCursor(codeItemEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -867,7 +890,7 @@ public class CodeItem extends Item<CodeItem> {
|
||||
|
||||
/**
|
||||
* @return the "Catch All" handler address for this <code>EncodedCatchHandler</code>, or -1 if there
|
||||
* is no "Catch All" handler
|
||||
* is no "Catch All" handler
|
||||
*/
|
||||
public int getCatchAllHandlerAddress() {
|
||||
return catchAllHandlerAddress;
|
||||
|
@ -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
|
||||
* <code>getPreserveSignedRegisters()</code>
|
||||
*/
|
||||
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.
|
||||
* <code>getPreserveSignedRegisters()</code>
|
||||
* @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 <code>Section.intern()</code> method of <code>ClassDefsSection</code>
|
||||
*/
|
||||
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
|
||||
|
Reference in New Issue
Block a user