From 2371e35aaeaf2ed4d7c571fb3286090eb01b717d Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Sat, 3 Apr 2010 23:03:25 +0000 Subject: [PATCH] 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 --- .../main/java/org/jf/baksmali/baksmali.java | 21 +++++++++++-- .../java/org/jf/baksmali/deodexCheck.java | 2 +- .../src/main/java/org/jf/baksmali/main.java | 13 +++++++- .../jf/dexlib/Code/Analysis/ClassPath.java | 31 ++++++++++++++----- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmali.java b/baksmali/src/main/java/org/jf/baksmali/baksmali.java index ed0fc307..0dca42c3 100644 --- a/baksmali/src/main/java/org/jf/baksmali/baksmali.java +++ b/baksmali/src/main/java/org/jf/baksmali/baksmali.java @@ -52,7 +52,7 @@ public class baksmali { String[] classPathDirs, String bootClassPath, String extraBootClassPath, boolean noParameterRegisters, boolean useLocalsDirective, boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets, - int registerInfo, boolean verify) + int registerInfo, boolean verify, boolean ignoreErrors) { baksmali.noParameterRegisters = noParameterRegisters; baksmali.useLocalsDirective = useLocalsDirective; @@ -64,6 +64,16 @@ public class baksmali { baksmali.bootClassPath = bootClassPath; 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) { try { String[] extraBootClassPathArray = null; @@ -80,14 +90,15 @@ public class baksmali { if (extraBootClassPathArray == null && isExtJar(dexFilePath)) { extraBootClassPathArray = new String[] {"framework.jar"}; } - ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile); + ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile, + classPathErrorHandler); } else { String[] bootClassPathArray = null; if (bootClassPath != null) { bootClassPathArray = bootClassPath.split(":"); } ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray, - dexFilePath, dexFile); + dexFilePath, dexFile, classPathErrorHandler); } } catch (Exception ex) { 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); + } } } diff --git a/baksmali/src/main/java/org/jf/baksmali/deodexCheck.java b/baksmali/src/main/java/org/jf/baksmali/deodexCheck.java index d38670d4..8d38d017 100644 --- a/baksmali/src/main/java/org/jf/baksmali/deodexCheck.java +++ b/baksmali/src/main/java/org/jf/baksmali/deodexCheck.java @@ -121,7 +121,7 @@ public class deodexCheck { } ClassPath.InitializeClassPath(bootClassPathDirsArray, bootClassPath==null?null:bootClassPath.split(":"), null, - null, null); + null, null, null); ClassPath.validateAgainstDeodexerant(deodexerantHost, deodexerantPort, classStartIndex); } diff --git a/baksmali/src/main/java/org/jf/baksmali/main.java b/baksmali/src/main/java/org/jf/baksmali/main.java index 161f7050..66abb1fd 100644 --- a/baksmali/src/main/java/org/jf/baksmali/main.java +++ b/baksmali/src/main/java/org/jf/baksmali/main.java @@ -104,6 +104,7 @@ public class main { boolean addCodeOffsets = false; boolean deodex = false; boolean verify = false; + boolean ignoreErrors = false; int registerInfo = 0; @@ -209,6 +210,9 @@ public class main { doDump = true; dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); break; + case 'I': + ignoreErrors = true; + break; case 'W': write = true; outputDexFileName = commandLine.getOptionValue("W"); @@ -273,7 +277,7 @@ public class main { baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory, bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(), noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets, - registerInfo, verify); + registerInfo, verify, ignoreErrors); } if ((doDump || write) && !dexFile.isOdex()) { @@ -411,6 +415,12 @@ public class main { .withArgName("FILE") .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") .withDescription("suppresses the output of the disassembly") .create("N"); @@ -448,6 +458,7 @@ public class main { basicOptions.addOption(codeOffsetOption); debugOptions.addOption(dumpOption); + debugOptions.addOption(ignoreErrorsOption); debugOptions.addOption(noDisassemblyOption); debugOptions.addOption(writeDexOption); debugOptions.addOption(sortOption); 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 2d966607..ae8cb296 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 @@ -53,6 +53,11 @@ public class ClassPath { 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 * @param classPathDirs The directories to search for boot class path files @@ -60,9 +65,12 @@ public class ClassPath { * from the odex file * @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 errorHandler a ClassPathErrorHandler object to receive and handle any errors that occur while loading + * classes */ public static void InitializeClassPathFromOdex(String[] classPathDirs, String[] extraBootClassPathEntries, - String dexFilePath, DexFile dexFile) { + String dexFilePath, DexFile dexFile, + ClassPathErrorHandler errorHandler) { if (!dexFile.isOdex()) { throw new ExceptionWithContext("Cannot use InitialiazeClassPathFromOdex with a non-odex DexFile"); } @@ -99,7 +107,8 @@ public class 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 dexFilePath The path of the dex file (used for error reporting purposes only) * @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, - String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile) { + String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile, + ClassPathErrorHandler errorHandler) { if (theClassPath != null) { throw new ExceptionWithContext("Cannot initialize ClassPath multiple times"); } theClassPath = new ClassPath(); - theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile); + theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile, + errorHandler); } private ClassPath() { @@ -124,7 +137,7 @@ public class ClassPath { } private void initClassPath(String[] classPathDirs, String[] bootClassPath, String[] extraBootClassPathEntries, - String dexFilePath, DexFile dexFile) { + String dexFilePath, DexFile dexFile, ClassPathErrorHandler errorHandler) { tempClasses = new LinkedHashMap(); if (bootClassPath != null) { @@ -150,8 +163,12 @@ public class ClassPath { classDef = ClassPath.loadClassDef(classType); assert classDef != null; } catch (Exception ex) { - System.err.println(String.format("Skipping %s", classType)); - ex.printStackTrace(System.err); + if (errorHandler != null) { + errorHandler.ClassPathError(classType, ex); + } else { + throw ExceptionWithContext.withContext(ex, + String.format("Error while loading ClassPath class %s", classType)); + } } if (classType.equals("Ljava/lang/Object;")) {