Add better support for the case when an odex file has missing classes

git-svn-id: https://smali.googlecode.com/svn/trunk@693 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2010-04-03 23:02:48 +00:00
parent 19b601436a
commit c1cc0e0934
3 changed files with 29 additions and 11 deletions

View File

@ -321,10 +321,10 @@ public class ClassDefinition {
MethodDefinition methodDefinition = new MethodDefinition(method); MethodDefinition methodDefinition = new MethodDefinition(method);
methodDefinition.writeTo(writer, annotationSet, parameterAnnotationList); methodDefinition.writeTo(writer, annotationSet, parameterAnnotationList);
ValidationException validationException = methodDefinition.getValidationException(); ValidationException validationException = methodDefinition.getValidationException();
if (validationException != null) { if (validationException != null) {
System.err.println(String.format("Error while disassembling method %s. Continuing.",
method.method.getMethodString()));
validationException.printStackTrace(System.err); validationException.printStackTrace(System.err);
this.validationErrors = true; this.validationErrors = true;
} }

View File

@ -113,6 +113,15 @@ public class baksmali {
* package name are separated by '/' * package name are separated by '/'
*/ */
if (registerInfo != 0 || deodex || verify) {
//If we are analyzing the bytecode, make sure that this class is loaded into the ClassPath. If it isn't
//then there was some error while loading it, and we should skip it
ClassPath.ClassDef classDef = ClassPath.getClassDef(classDefItem.getClassType(), false);
if (classDef == null || classDef instanceof ClassPath.UnresolvedClassDef) {
continue;
}
}
String classDescriptor = classDefItem.getClassType().getTypeDescriptor(); String classDescriptor = classDefItem.getClassType().getTypeDescriptor();
//validate that the descriptor is formatted like we expect //validate that the descriptor is formatted like we expect
@ -179,11 +188,6 @@ public class baksmali {
} }
} }
} }
//TODO: GROT
if (classDefinition.hadValidationErrors()) {
System.exit(1);
}
} }
} }

View File

@ -145,7 +145,15 @@ public class ClassPath {
for (String classType: tempClasses.keySet()) { for (String classType: tempClasses.keySet()) {
ClassDef classDef = ClassPath.loadClassDef(classType); ClassDef classDef = null;
try {
classDef = ClassPath.loadClassDef(classType);
assert classDef != null;
} catch (Exception ex) {
System.err.println(String.format("Skipping %s", classType));
ex.printStackTrace(System.err);
}
if (classType.equals("Ljava/lang/Object;")) { if (classType.equals("Ljava/lang/Object;")) {
this.javaLangObjectClassDef = classDef; this.javaLangObjectClassDef = classDef;
} }
@ -240,7 +248,7 @@ public class ClassPath {
* This method checks if the given class has been loaded yet. If it has, it returns the loaded ClassDef. If not, * This method checks if the given class has been loaded yet. If it has, it returns the loaded ClassDef. If not,
* then it looks up the TempClassItem for the given class and (possibly recursively) loads the ClassDef. * then it looks up the TempClassItem for the given class and (possibly recursively) loads the ClassDef.
* @param classType the class to load * @param classType the class to load
* @return the existing or newly loaded ClassDef object for the given class * @return the existing or newly loaded ClassDef object for the given class, or null if the class cannot be found
*/ */
private static ClassDef loadClassDef(String classType) { private static ClassDef loadClassDef(String classType) {
ClassDef classDef = getClassDef(classType, false); ClassDef classDef = getClassDef(classType, false);
@ -248,7 +256,7 @@ public class ClassPath {
if (classDef == null) { if (classDef == null) {
TempClassInfo classInfo = theClassPath.tempClasses.get(classType); TempClassInfo classInfo = theClassPath.tempClasses.get(classType);
if (classInfo == null) { if (classInfo == null) {
throw new ExceptionWithContext(String.format("Could not find class %s", classType)); return null;
} }
try { try {
@ -755,6 +763,9 @@ public class ClassPath {
} }
ClassDef superclass = ClassPath.loadClassDef(superclassType); ClassDef superclass = ClassPath.loadClassDef(superclassType);
if (superclass == null) {
throw new ClassNotFoundException(String.format("Could not find superclass %s", superclassType));
}
if (!isInterface && superclass.isInterface) { if (!isInterface && superclass.isInterface) {
throw new ValidationException("Class " + classType + " has the interface " + superclass.classType + throw new ValidationException("Class " + classType + " has the interface " + superclass.classType +
@ -787,6 +798,9 @@ public class ClassPath {
if (classInfo.interfaces != null) { if (classInfo.interfaces != null) {
for (String interfaceType: classInfo.interfaces) { for (String interfaceType: classInfo.interfaces) {
ClassDef interfaceDef = ClassPath.loadClassDef(interfaceType); ClassDef interfaceDef = ClassPath.loadClassDef(interfaceType);
if (interfaceDef == null) {
throw new ClassNotFoundException(String.format("Could not find interface %s", interfaceType));
}
assert interfaceDef.isInterface(); assert interfaceDef.isInterface();
implementedInterfaceSet.add(interfaceDef); implementedInterfaceSet.add(interfaceDef);
@ -813,7 +827,7 @@ public class ClassPath {
if (!interfaceTable.containsKey(interfaceType)) { if (!interfaceTable.containsKey(interfaceType)) {
ClassDef interfaceDef = ClassPath.loadClassDef(interfaceType); ClassDef interfaceDef = ClassPath.loadClassDef(interfaceType);
if (interfaceDef == null) { if (interfaceDef == null) {
throw new ValidationException(String.format("Could not resolve type %s", interfaceType)); throw new ClassNotFoundException(String.format("Could not find interface %s", interfaceType));
} }
interfaceTable.put(interfaceType, interfaceDef); interfaceTable.put(interfaceType, interfaceDef);