Misc cleanup

git-svn-id: https://smali.googlecode.com/svn/trunk@638 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com
2010-02-22 07:01:23 +00:00
parent 0c65e0f4f5
commit e9b722eab0
8 changed files with 20 additions and 114 deletions

View File

@ -64,7 +64,13 @@ public class baksmali {
baksmali.bootClassPath = bootClassPath; baksmali.bootClassPath = bootClassPath;
if (registerInfo != 0 || deodex) { if (registerInfo != 0 || deodex) {
ClassPath.InitializeClassPath(bootClassPathDir, bootClassPath==null?null:bootClassPath.split(":"), dexFile); try {
ClassPath.InitializeClassPath(bootClassPathDir, bootClassPath==null?null:bootClassPath.split(":"), dexFile);
} catch (Exception ex) {
System.err.println("\n\nError occured while loading boot class path files. Aborting.");
ex.printStackTrace(System.err);
System.exit(1);
}
} }
File outputDirectoryFile = new File(outputDirectory); File outputDirectoryFile = new File(outputDirectory);
@ -150,7 +156,7 @@ public class baksmali {
writer = new FileWriter(smaliFile); writer = new FileWriter(smaliFile);
writer.write(output); writer.write(output);
} catch (Throwable ex) { } catch (Exception ex) {
System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class");
ex.printStackTrace(); ex.printStackTrace();
} }

View File

@ -225,10 +225,10 @@ public class main {
if (dexFile.isOdex()) { if (dexFile.isOdex()) {
if (doDump) { if (doDump) {
System.err.println("-d cannot be used with on odex file. Ignoring -d"); System.err.println("-D cannot be used with on odex file. Ignoring -D");
} }
if (write) { if (write) {
System.err.println("-w cannot be used with an odex file. Ignoring -w"); System.err.println("-W cannot be used with an odex file. Ignoring -W");
} }
if (!deodex) { if (!deodex) {
System.err.println("Warning: You are disassembling an odex file without deodexing it. You"); System.err.println("Warning: You are disassembling an odex file without deodexing it. You");
@ -305,7 +305,7 @@ public class main {
.create("v"); .create("v");
Option helpOption = OptionBuilder.withLongOpt("help") Option helpOption = OptionBuilder.withLongOpt("help")
.withDescription("prints the help message then exits") .withDescription("prints the help message then exits. Specify twice for debug options")
.create("?"); .create("?");
Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly")
@ -380,8 +380,8 @@ public class main {
Option classPathOption = OptionBuilder.withLongOpt("bootclasspath") Option classPathOption = OptionBuilder.withLongOpt("bootclasspath")
.withDescription("the bootclasspath jars to use, for analysis. Defaults to " + .withDescription("the bootclasspath jars to use, for analysis. Defaults to " +
"core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If you specify a value that " + "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If the value begins with a " +
"begins with a :, it will be appended to the default bootclasspath") ":, it will be appended to the default bootclasspath instead of replacing it")
.hasOptionalArg() .hasOptionalArg()
.withArgName("BOOTCLASSPATH") .withArgName("BOOTCLASSPATH")
.create("c"); .create("c");

View File

@ -186,7 +186,7 @@ public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> {
/** /**
* Iterates over the predecessors of this instruction, and merges all the post-instruction register types for the * Iterates over the predecessors of this instruction, and merges all the post-instruction register types for the
* given register. Any dead, unreachable, or odexed predecessor is ignored * given register. Any dead, unreachable, or odexed predecessor is ignored
* @param registerNumber * @param registerNumber the register number
* @return The register type resulting from merging the post-instruction register types from all predecessors * @return The register type resulting from merging the post-instruction register types from all predecessors
*/ */
protected RegisterType mergePreRegisterTypeFromPredecessors(int registerNumber) { protected RegisterType mergePreRegisterTypeFromPredecessors(int registerNumber) {

View File

@ -17,24 +17,6 @@ public class ClassPath {
private final HashMap<String, ClassDef> classDefs; private final HashMap<String, ClassDef> classDefs;
protected ClassDef javaLangObjectClassDef; //Ljava/lang/Object; protected ClassDef javaLangObjectClassDef; //Ljava/lang/Object;
private final static String[][] inlineMethods =
new String[][] {
{ "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod()V"},
{ "Ljava/lang/String;", "charAt(I)C"},
{ "Ljava/lang/String;", "compareTo(Ljava/lang/String;)I"},
{ "Ljava/lang/String;", "equals(Ljava/lang/Object;)Z"},
{ "Ljava/lang/String;", "length()I"},
{ "Ljava/lang/Math;", "abs(I)I"},
{ "Ljava/lang/Math;", "abs(J)J"},
{ "Ljava/lang/Math;", "abs(F)F"},
{ "Ljava/lang/Math;", "abs(D)D"},
{ "Ljava/lang/Math;", "min(I)I"},
{ "Ljava/lang/Math;", "max(II)I"},
{ "Ljava/lang/Math;", "sqrt(D)D"},
{ "Ljava/lang/Math;", "cos(D)D"},
{ "Ljava/lang/Math;", "sin(D)D"}
};
public static void InitializeClassPath(String bootClassPathDir, String[] bootClassPath, DexFile dexFile) { public static void InitializeClassPath(String bootClassPathDir, String[] bootClassPath, DexFile dexFile) {
if (theClassPath != null) { if (theClassPath != null) {
throw new ExceptionWithContext("Cannot initialize ClassPath multiple times"); throw new ExceptionWithContext("Cannot initialize ClassPath multiple times");
@ -250,15 +232,6 @@ public class ClassPath {
return getArrayClassDefByElementClassAndDimension(theClassPath.javaLangObjectClassDef, dimensions); return getArrayClassDefByElementClassAndDimension(theClassPath.javaLangObjectClassDef, dimensions);
} }
public static String[] getInlineMethod(int inlineIndex) {
if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) {
return null;
}
return inlineMethods[inlineIndex];
}
public static class ArrayClassDef extends ClassDef { public static class ArrayClassDef extends ClassDef {
private final ClassDef elementClass; private final ClassDef elementClass;
private final int arrayDimensions; private final int arrayDimensions;
@ -290,7 +263,7 @@ public class ClassPath {
* *
* For example, for a multi-dimensional array of strings ([[Ljava/lang/String;), this method would return * For example, for a multi-dimensional array of strings ([[Ljava/lang/String;), this method would return
* Ljava/lang/String; * Ljava/lang/String;
* @return * @return the "base" element class of the array
*/ */
public ClassDef getBaseElementClass() { public ClassDef getBaseElementClass() {
return elementClass; return elementClass;
@ -301,7 +274,7 @@ public class ClassPath {
* *
* For example, for a multi-dimensional array of stings with 2 dimensions ([[Ljava/lang/String;), this method * For example, for a multi-dimensional array of stings with 2 dimensions ([[Ljava/lang/String;), this method
* would return [Ljava/lang/String; * would return [Ljava/lang/String;
* @return * @return the immediate element class of the array
*/ */
public ClassDef getImmediateElementClass() { public ClassDef getImmediateElementClass() {
if (arrayDimensions == 1) { if (arrayDimensions == 1) {
@ -1066,24 +1039,4 @@ public class ClassPath {
throw ExceptionWithContext.withContext(ex, String.format("Error while checking class #%d", count)); throw ExceptionWithContext.withContext(ex, String.format("Error while checking class #%d", count));
} }
} }
public static String join(String[] vals)
{
StringBuilder sb = new StringBuilder();
for (String val: vals) {
sb.append(val);
sb.append('\n');
}
return sb.toString();
}
public static String join(List<String> vals)
{
StringBuilder sb = new StringBuilder();
for (String val: vals) {
sb.append(val);
sb.append('\n');
}
return sb.toString();
}
} }

View File

@ -1,7 +1,6 @@
package org.jf.dexlib.Code.Analysis; package org.jf.dexlib.Code.Analysis;
import org.jf.dexlib.*; import org.jf.dexlib.*;
import org.jf.dexlib.Util.ExceptionWithContext;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -43,23 +42,6 @@ public class DeodexUtil {
return inlineMethods[inlineMethodIndex]; return inlineMethods[inlineMethodIndex];
} }
private TypeIdItem resolveTypeOrSupertype(ClassPath.ClassDef classDef) {
ClassPath.ClassDef originalClassDef = classDef;
do {
TypeIdItem typeItem = TypeIdItem.lookupTypeIdItem(dexFile, classDef.getClassType());
if (typeItem != null) {
return typeItem;
}
classDef = classDef.getSuperclass();
} while (classDef != null);
throw new ExceptionWithContext(String.format("Cannot find type %s in the dex file",
originalClassDef.getClassType()));
}
public FieldIdItem lookupField(ClassPath.ClassDef classDef, int fieldOffset) { public FieldIdItem lookupField(ClassPath.ClassDef classDef, int fieldOffset) {
String field = classDef.getInstanceField(fieldOffset); String field = classDef.getInstanceField(fieldOffset);
if (field == null) { if (field == null) {
@ -249,7 +231,7 @@ public class DeodexUtil {
* Newer versions of dalvik add additional inline methods, but (so far) have changed any existing ones. * Newer versions of dalvik add additional inline methods, but (so far) have changed any existing ones.
* *
* If anything doesn't look right, we just throw an exception * If anything doesn't look right, we just throw an exception
* @param inlineMethods * @param inlineMethods the inline methods from deodexerant
*/ */
protected void checkInlineMethods(String[] inlineMethods) { protected void checkInlineMethods(String[] inlineMethods) {
if (inlineMethods.length > this.inlineMethods.length) { if (inlineMethods.length > this.inlineMethods.length) {

View File

@ -32,7 +32,6 @@ import java.net.Socket;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
/** /**

View File

@ -1233,31 +1233,7 @@ public class MethodAnalyzer {
setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType);
} }
//TODO: GROT
/*private void checkConstructorReturn(AnalyzedInstruction analyzedInstruction) {
assert this.isInstanceConstructor();
//if we're in an instance constructor (an <init> method), then the superclass <init> must have been called.
//When execution enters the method, the "this" register is set as an uninitialized reference to the containing
//class. Once the superclass' <init> is called, the "this" register is upgraded to a full-blown reference type,
//so we need to ensure that the "this" register isn't an uninitialized reference
int thisRegister = getThisRegister();
RegisterType thisRegisterType = analyzedInstruction.postRegisterMap[thisRegister];
if (thisRegisterType.category == RegisterType.Category.UninitRef) {
throw new ValidationException("Returning from constructor without calling the superclass' <init>");
}
//TODO: GROT
//assert thisRegisterType.category == RegisterType.Category.Reference;
//assert thisRegisterType.type == ClassPath.getClassDef(encodedMethod.method.getContainingClass());
}*/
private void handleReturnVoid(AnalyzedInstruction analyzedInstruction) { private void handleReturnVoid(AnalyzedInstruction analyzedInstruction) {
/*if (this.isInstanceConstructor()) {
checkConstructorReturn(analyzedInstruction);
}*/
TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType();
if (returnType.getTypeDescriptor().charAt(0) != 'V') { if (returnType.getTypeDescriptor().charAt(0) != 'V') {
//TODO: could add which return-* variation should be used instead //TODO: could add which return-* variation should be used instead
@ -1320,7 +1296,6 @@ public class MethodAnalyzer {
private void handleConstHigh16(AnalyzedInstruction analyzedInstruction) { private void handleConstHigh16(AnalyzedInstruction analyzedInstruction) {
LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction; LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction;
//TODO: test this
long literalValue = instruction.getLiteral() << 16; long literalValue = instruction.getLiteral() << 16;
RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(literalValue); RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(literalValue);
@ -2395,7 +2370,6 @@ public class MethodAnalyzer {
InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
//TODO: check access //TODO: check access
//TODO: allow uninitialized reference if this in an <init> method
Item item = instruction.getReferencedItem(); Item item = instruction.getReferencedItem();
assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM; assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM;
@ -2578,7 +2552,7 @@ public class MethodAnalyzer {
if (preInstructionRegisterType.category == RegisterType.Category.UninitRef || if (preInstructionRegisterType.category == RegisterType.Category.UninitRef ||
preInstructionRegisterType.category == RegisterType.Category.UninitThis) { preInstructionRegisterType.category == RegisterType.Category.UninitThis) {
RegisterType registerType = null; RegisterType registerType;
if (preInstructionRegisterType == objectRegisterType) { if (preInstructionRegisterType == objectRegisterType) {
registerType = analyzedInstruction.postRegisterMap[objectRegister]; registerType = analyzedInstruction.postRegisterMap[objectRegister];
} else { } else {
@ -2836,8 +2810,6 @@ public class MethodAnalyzer {
if (objectRegisterType.category == RegisterType.Category.Null) { if (objectRegisterType.category == RegisterType.Category.Null) {
return false; return false;
//throw new ValidationException("Unodexable instructions not supported yet");
//TODO: handle unodexable instruction
} }
FieldIdItem fieldIdItem = deodexUtil.lookupField(objectRegisterType.type, fieldOffset); FieldIdItem fieldIdItem = deodexUtil.lookupField(objectRegisterType.type, fieldOffset);
@ -2879,8 +2851,6 @@ public class MethodAnalyzer {
if (objectRegisterType.category == RegisterType.Category.Null) { if (objectRegisterType.category == RegisterType.Category.Null) {
return false; return false;
//throw new ValidationException("Unodexable instructions not supported yet");
//TODO: handle unodexable instruction
} }
MethodIdItem methodIdItem = null; MethodIdItem methodIdItem = null;
@ -3062,9 +3032,8 @@ public class MethodAnalyzer {
private static void checkRegister(RegisterType registerType, int registerNumber, EnumSet validCategories) { private static void checkRegister(RegisterType registerType, int registerNumber, EnumSet validCategories) {
if (!validCategories.contains(registerType.category)) { if (!validCategories.contains(registerType.category)) {
//TODO: add expected categories to error message throw new ValidationException(String.format("Invalid register type %s for register v%d.",
throw new ValidationException(String.format("Invalid register type for register v%d. Expecting one of: " + registerType.toString(), registerNumber));
"but got %s", registerNumber, registerType.toString()));
} }
} }

View File

@ -1,10 +1,7 @@
package org.jf.dexlib.Code.Analysis; package org.jf.dexlib.Code.Analysis;
import org.jf.dexlib.ClassDefItem;
import org.jf.dexlib.TypeIdItem; import org.jf.dexlib.TypeIdItem;
import static org.jf.dexlib.Code.Analysis.ClassPath.ClassDef; import static org.jf.dexlib.Code.Analysis.ClassPath.ClassDef;
import static org.jf.dexlib.Code.Analysis.ClassPath.PrimitiveClassDef;
import static org.jf.dexlib.Code.Analysis.ClassPath.ArrayClassDef;
import java.util.HashMap; import java.util.HashMap;
public class RegisterType { public class RegisterType {