Exit on the first error by default, but add the -I option for ignoring errors and continuing with disassembly

git-svn-id: https://smali.googlecode.com/svn/trunk@701 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com
2010-04-03 23:03:25 +00:00
parent 0808ee81c6
commit 2371e35aae
4 changed files with 55 additions and 12 deletions

View File

@ -52,7 +52,7 @@ public class baksmali {
String[] classPathDirs, String bootClassPath, String extraBootClassPath, String[] classPathDirs, String bootClassPath, String extraBootClassPath,
boolean noParameterRegisters, boolean useLocalsDirective, boolean noParameterRegisters, boolean useLocalsDirective,
boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets, boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets,
int registerInfo, boolean verify) int registerInfo, boolean verify, boolean ignoreErrors)
{ {
baksmali.noParameterRegisters = noParameterRegisters; baksmali.noParameterRegisters = noParameterRegisters;
baksmali.useLocalsDirective = useLocalsDirective; baksmali.useLocalsDirective = useLocalsDirective;
@ -64,6 +64,16 @@ public class baksmali {
baksmali.bootClassPath = bootClassPath; baksmali.bootClassPath = bootClassPath;
baksmali.verify = verify; baksmali.verify = verify;
ClassPath.ClassPathErrorHandler classPathErrorHandler = null;
if (ignoreErrors) {
classPathErrorHandler = new ClassPath.ClassPathErrorHandler() {
public void ClassPathError(String className, Exception ex) {
System.err.println(String.format("Skipping %s", className));
ex.printStackTrace(System.err);
}
};
}
if (registerInfo != 0 || deodex || verify) { if (registerInfo != 0 || deodex || verify) {
try { try {
String[] extraBootClassPathArray = null; String[] extraBootClassPathArray = null;
@ -80,14 +90,15 @@ public class baksmali {
if (extraBootClassPathArray == null && isExtJar(dexFilePath)) { if (extraBootClassPathArray == null && isExtJar(dexFilePath)) {
extraBootClassPathArray = new String[] {"framework.jar"}; extraBootClassPathArray = new String[] {"framework.jar"};
} }
ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile); ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile,
classPathErrorHandler);
} else { } else {
String[] bootClassPathArray = null; String[] bootClassPathArray = null;
if (bootClassPath != null) { if (bootClassPath != null) {
bootClassPathArray = bootClassPath.split(":"); bootClassPathArray = bootClassPath.split(":");
} }
ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray, ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray,
dexFilePath, dexFile); dexFilePath, dexFile, classPathErrorHandler);
} }
} catch (Exception ex) { } catch (Exception ex) {
System.err.println("\n\nError occured while loading boot class path files. Aborting."); System.err.println("\n\nError occured while loading boot class path files. Aborting.");
@ -189,6 +200,10 @@ public class baksmali {
} }
} }
} }
if (!ignoreErrors && classDefinition.hadValidationErrors()) {
System.exit(1);
}
} }
} }

View File

@ -121,7 +121,7 @@ public class deodexCheck {
} }
ClassPath.InitializeClassPath(bootClassPathDirsArray, bootClassPath==null?null:bootClassPath.split(":"), null, ClassPath.InitializeClassPath(bootClassPathDirsArray, bootClassPath==null?null:bootClassPath.split(":"), null,
null, null); null, null, null);
ClassPath.validateAgainstDeodexerant(deodexerantHost, deodexerantPort, classStartIndex); ClassPath.validateAgainstDeodexerant(deodexerantHost, deodexerantPort, classStartIndex);
} }

View File

@ -104,6 +104,7 @@ public class main {
boolean addCodeOffsets = false; boolean addCodeOffsets = false;
boolean deodex = false; boolean deodex = false;
boolean verify = false; boolean verify = false;
boolean ignoreErrors = false;
int registerInfo = 0; int registerInfo = 0;
@ -209,6 +210,9 @@ public class main {
doDump = true; doDump = true;
dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump");
break; break;
case 'I':
ignoreErrors = true;
break;
case 'W': case 'W':
write = true; write = true;
outputDexFileName = commandLine.getOptionValue("W"); outputDexFileName = commandLine.getOptionValue("W");
@ -273,7 +277,7 @@ public class main {
baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory, baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory,
bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(), bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(),
noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets, noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets,
registerInfo, verify); registerInfo, verify, ignoreErrors);
} }
if ((doDump || write) && !dexFile.isOdex()) { if ((doDump || write) && !dexFile.isOdex()) {
@ -411,6 +415,12 @@ public class main {
.withArgName("FILE") .withArgName("FILE")
.create("D"); .create("D");
Option ignoreErrorsOption = OptionBuilder.withLongOpt("ignore-errors")
.withDescription("ignores any non-fatal errors that occur while disassembling/deodexing," +
" ignoring the class if needed, and continuing with the next class. The default" +
" behavior is to stop disassembling and exit once an error is encountered")
.create("I");
Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly")
.withDescription("suppresses the output of the disassembly") .withDescription("suppresses the output of the disassembly")
.create("N"); .create("N");
@ -448,6 +458,7 @@ public class main {
basicOptions.addOption(codeOffsetOption); basicOptions.addOption(codeOffsetOption);
debugOptions.addOption(dumpOption); debugOptions.addOption(dumpOption);
debugOptions.addOption(ignoreErrorsOption);
debugOptions.addOption(noDisassemblyOption); debugOptions.addOption(noDisassemblyOption);
debugOptions.addOption(writeDexOption); debugOptions.addOption(writeDexOption);
debugOptions.addOption(sortOption); debugOptions.addOption(sortOption);

View File

@ -53,6 +53,11 @@ public class ClassPath {
private static final Pattern dalvikCacheOdexPattern = Pattern.compile("@([^@]+)@classes.dex$"); private static final Pattern dalvikCacheOdexPattern = Pattern.compile("@([^@]+)@classes.dex$");
public static interface ClassPathErrorHandler {
void ClassPathError(String className, Exception ex);
}
/** /**
* Initialize the class path using the dependencies from an odex file * Initialize the class path using the dependencies from an odex file
* @param classPathDirs The directories to search for boot class path files * @param classPathDirs The directories to search for boot class path files
@ -60,9 +65,12 @@ public class ClassPath {
* from the odex file * from the odex file
* @param dexFilePath The path of the dex file (used for error reporting purposes only) * @param dexFilePath The path of the dex file (used for error reporting purposes only)
* @param dexFile The DexFile to load - it must represents an odex file * @param dexFile The DexFile to load - it must represents an odex file
* @param errorHandler a ClassPathErrorHandler object to receive and handle any errors that occur while loading
* classes
*/ */
public static void InitializeClassPathFromOdex(String[] classPathDirs, String[] extraBootClassPathEntries, public static void InitializeClassPathFromOdex(String[] classPathDirs, String[] extraBootClassPathEntries,
String dexFilePath, DexFile dexFile) { String dexFilePath, DexFile dexFile,
ClassPathErrorHandler errorHandler) {
if (!dexFile.isOdex()) { if (!dexFile.isOdex()) {
throw new ExceptionWithContext("Cannot use InitialiazeClassPathFromOdex with a non-odex DexFile"); throw new ExceptionWithContext("Cannot use InitialiazeClassPathFromOdex with a non-odex DexFile");
} }
@ -99,7 +107,8 @@ public class ClassPath {
} }
theClassPath = new ClassPath(); theClassPath = new ClassPath();
theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile); theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile,
errorHandler);
} }
/** /**
@ -108,15 +117,19 @@ public class ClassPath {
* @param bootClassPath A list of the boot class path entries to search for and load * @param bootClassPath A list of the boot class path entries to search for and load
* @param dexFilePath The path of the dex file (used for error reporting purposes only) * @param dexFilePath The path of the dex file (used for error reporting purposes only)
* @param dexFile the DexFile to load * @param dexFile the DexFile to load
* @param errorHandler a ClassPathErrorHandler object to receive and handle any errors that occur while loading
* classes
*/ */
public static void InitializeClassPath(String[] classPathDirs, String[] bootClassPath, public static void InitializeClassPath(String[] classPathDirs, String[] bootClassPath,
String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile) { String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile,
ClassPathErrorHandler errorHandler) {
if (theClassPath != null) { if (theClassPath != null) {
throw new ExceptionWithContext("Cannot initialize ClassPath multiple times"); throw new ExceptionWithContext("Cannot initialize ClassPath multiple times");
} }
theClassPath = new ClassPath(); theClassPath = new ClassPath();
theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile); theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile,
errorHandler);
} }
private ClassPath() { private ClassPath() {
@ -124,7 +137,7 @@ public class ClassPath {
} }
private void initClassPath(String[] classPathDirs, String[] bootClassPath, String[] extraBootClassPathEntries, private void initClassPath(String[] classPathDirs, String[] bootClassPath, String[] extraBootClassPathEntries,
String dexFilePath, DexFile dexFile) { String dexFilePath, DexFile dexFile, ClassPathErrorHandler errorHandler) {
tempClasses = new LinkedHashMap<String, TempClassInfo>(); tempClasses = new LinkedHashMap<String, TempClassInfo>();
if (bootClassPath != null) { if (bootClassPath != null) {
@ -150,8 +163,12 @@ public class ClassPath {
classDef = ClassPath.loadClassDef(classType); classDef = ClassPath.loadClassDef(classType);
assert classDef != null; assert classDef != null;
} catch (Exception ex) { } catch (Exception ex) {
System.err.println(String.format("Skipping %s", classType)); if (errorHandler != null) {
ex.printStackTrace(System.err); errorHandler.ClassPathError(classType, ex);
} else {
throw ExceptionWithContext.withContext(ex,
String.format("Error while loading ClassPath class %s", classType));
}
} }
if (classType.equals("Ljava/lang/Object;")) { if (classType.equals("Ljava/lang/Object;")) {