From 4b171afedb983fb811990beeec6a15e30a90b455 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 11 May 2013 13:37:19 -0700 Subject: [PATCH] Misc baksmali cleanup --- .../Adaptors/Format/ArrayDataMethodItem.java | 2 +- .../baksmali/Adaptors/MethodDefinition.java | 4 +- .../main/java/org/jf/baksmali/baksmali.java | 202 +++++++---------- .../java/org/jf/baksmali/baksmaliOptions.java | 25 ++- .../src/main/java/org/jf/baksmali/dump.java | 4 +- .../src/main/java/org/jf/baksmali/main.java | 207 ++++++++++-------- .../src/main/java/org/jf/baksmali/temp.java | 50 ----- 7 files changed, 226 insertions(+), 268 deletions(-) delete mode 100644 baksmali/src/main/java/org/jf/baksmali/temp.java diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/ArrayDataMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/ArrayDataMethodItem.java index d61b32ab..f621a589 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/ArrayDataMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/ArrayDataMethodItem.java @@ -62,7 +62,7 @@ public class ArrayDataMethodItem extends InstructionMethodItem { break; } - for (Number number: instruction.getArrayElements()) { + for (Number number: elements) { LongRenderer.writeSignedIntOrLongTo(writer, number.longValue()); writer.write(suffix); writer.write("\n"); diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java index 80623257..611936b6 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java @@ -176,9 +176,7 @@ public class MethodDefinition { writer.write('\n'); List methodItems = getMethodItems(); - int size = methodItems.size(); - for (int i=0; i extraBootClassPaths = null; - if (extraBootClassPath != null && extraBootClassPath.length() > 0) { - assert extraBootClassPath.charAt(0) == ':'; - extraBootClassPaths = Splitter.on(':').split(extraBootClassPath.substring(1)); + Iterable extraClassPathEntries; + if (options.extraClassPathEntries != null) { + extraClassPathEntries = options.extraClassPathEntries; } else { - extraBootClassPaths = ImmutableList.of(); + extraClassPathEntries = ImmutableList.of(); } - Iterable bootClassPaths = null; - if (bootClassPath != null) { - bootClassPaths = Splitter.on(':').split(bootClassPath); - } else if (dexFile instanceof DexBackedOdexFile) { - bootClassPaths = ((DexBackedOdexFile)dexFile).getDependencies(); - }else { - bootClassPaths = ImmutableList.of(); - } - - options.classPath = ClassPath.fromClassPath(Arrays.asList(classPathDirs), - Iterables.concat(bootClassPaths, extraBootClassPaths), dexFile, apiLevel); - - if (inlineTable != null) { - options.inlineResolver = new CustomInlineMethodResolver(options.classPath, new File(inlineTable)); - } else if (dexFile instanceof DexBackedOdexFile) { - options.inlineResolver = InlineMethodResolver.createInlineMethodResolver(((DexBackedOdexFile) dexFile).getOdexVersion()); - } + options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, + Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, + options.apiLevel); } catch (Exception ex) { System.err.println("\n\nError occured while loading boot class path files. Aborting."); ex.printStackTrace(System.err); @@ -102,10 +63,10 @@ public class baksmali { } } - File outputDirectoryFile = new File(outputDirectory); + File outputDirectoryFile = new File(options.outputDirectory); if (!outputDirectoryFile.exists()) { if (!outputDirectoryFile.mkdirs()) { - System.err.println("Can't create the output directory " + outputDirectory); + System.err.println("Can't create the output directory " + options.outputDirectory); System.exit(1); } } @@ -122,85 +83,84 @@ public class baksmali { }); classDefs = ImmutableList.copyOf(classDefs); - if (!noAccessorComments) { + if (!options.noAccessorComments) { options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs); } ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali"); for (ClassDef classDef: classDefs) { - /** - * The path for the disassembly file is based on the package name - * The class descriptor will look something like: - * Ljava/lang/Object; - * Where the there is leading 'L' and a trailing ';', and the parts of the - * package name are separated by '/' - */ - - String classDescriptor = classDef.getType(); - - //validate that the descriptor is formatted like we expect - if (classDescriptor.charAt(0) != 'L' || - classDescriptor.charAt(classDescriptor.length()-1) != ';') { - System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); - continue; - } - - File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor); - - //create and initialize the top level string template - ClassDefinition classDefinition = new ClassDefinition(options, classDef); - - //write the disassembly - Writer writer = null; - try - { - File smaliParent = smaliFile.getParentFile(); - if (!smaliParent.exists()) { - if (!smaliParent.mkdirs()) { - System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class"); - continue; - } - } - - if (!smaliFile.exists()){ - if (!smaliFile.createNewFile()) { - System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class"); - continue; - } - } - - BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(smaliFile), "UTF8")); - - writer = new IndentingWriter(bufWriter); - classDefinition.writeTo((IndentingWriter)writer); - } catch (Exception ex) { - System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); - ex.printStackTrace(); - smaliFile.delete(); - } - finally - { - if (writer != null) { - try { - writer.close(); - } catch (Throwable ex) { - System.err.println("\n\nError occured while closing file " + smaliFile.toString()); - ex.printStackTrace(); - } - } - } - - if (!ignoreErrors && classDefinition.hadValidationErrors()) { - System.exit(1); - } + disassembleClass(classDef, fileNameHandler, options); } } - private static final Pattern extJarPattern = Pattern.compile("(?:^|\\\\|/)ext.(?:jar|odex)$"); - private static boolean isExtJar(String dexFilePath) { - Matcher m = extJarPattern.matcher(dexFilePath); - return m.find(); + private static void disassembleClass(ClassDef classDef, ClassFileNameHandler fileNameHandler, + baksmaliOptions options) { + /** + * The path for the disassembly file is based on the package name + * The class descriptor will look something like: + * Ljava/lang/Object; + * Where the there is leading 'L' and a trailing ';', and the parts of the + * package name are separated by '/' + */ + String classDescriptor = classDef.getType(); + + //validate that the descriptor is formatted like we expect + if (classDescriptor.charAt(0) != 'L' || + classDescriptor.charAt(classDescriptor.length()-1) != ';') { + System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); + return; + } + + File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor); + + //create and initialize the top level string template + ClassDefinition classDefinition = new ClassDefinition(options, classDef); + + //write the disassembly + Writer writer = null; + try + { + File smaliParent = smaliFile.getParentFile(); + if (!smaliParent.exists()) { + if (!smaliParent.mkdirs()) { + System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class"); + return; + } + } + + if (!smaliFile.exists()){ + if (!smaliFile.createNewFile()) { + System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class"); + return; + } + } + + BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(smaliFile), "UTF8")); + + writer = new IndentingWriter(bufWriter); + classDefinition.writeTo((IndentingWriter)writer); + } catch (Exception ex) { + System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); + ex.printStackTrace(); + // noinspection ResultOfMethodCallIgnored + smaliFile.delete(); + } + finally + { + if (writer != null) { + try { + writer.close(); + } catch (Throwable ex) { + System.err.println("\n\nError occured while closing file " + smaliFile.toString()); + ex.printStackTrace(); + } + } + } + + if (!options.ignoreErrors && classDefinition.hadValidationErrors()) { + System.exit(1); + } } } diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java b/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java index 210478d5..9f0e043d 100644 --- a/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java +++ b/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java @@ -31,10 +31,14 @@ package org.jf.baksmali; +import com.google.common.collect.Lists; import org.jf.dexlib2.analysis.ClassPath; import org.jf.dexlib2.analysis.InlineMethodResolver; import org.jf.dexlib2.util.SyntheticAccessorResolver; +import java.util.Arrays; +import java.util.List; + public class baksmaliOptions { // register info values public static final int ALL = 1; @@ -45,6 +49,13 @@ public class baksmaliOptions { public static final int MERGE = 32; public static final int FULLMERGE = 64; + public int apiLevel = 15; + public String outputDirectory = "out"; + public List bootClassPathDirs = Lists.newArrayList(); + + public List bootClassPathEntries = Lists.newArrayList(); + public List extraClassPathEntries = Lists.newArrayList(); + public boolean noParameterRegisters = false; public boolean useLocalsDirective = false; public boolean useSequentialLabels = false; @@ -52,10 +63,22 @@ public class baksmaliOptions { public boolean addCodeOffsets = false; public boolean noAccessorComments = false; public boolean deodex = false; + public boolean ignoreErrors = false; + public boolean checkPackagePrivateAccess = false; public InlineMethodResolver inlineResolver = null; public int registerInfo = 0; - public String bootClassPath; public ClassPath classPath = null; public SyntheticAccessorResolver syntheticAccessorResolver = null; + + public void setBootClassPath(String bootClassPath) { + bootClassPathEntries = Lists.newArrayList(bootClassPath.split(":")); + } + + public void addExtraClassPath(String extraClassPath) { + if (extraClassPath.startsWith(":")) { + extraClassPath = extraClassPath.substring(1); + } + extraClassPathEntries.addAll(Arrays.asList(extraClassPath.split(":"))); + } } diff --git a/baksmali/src/main/java/org/jf/baksmali/dump.java b/baksmali/src/main/java/org/jf/baksmali/dump.java index c7123a58..bd040e6d 100644 --- a/baksmali/src/main/java/org/jf/baksmali/dump.java +++ b/baksmali/src/main/java/org/jf/baksmali/dump.java @@ -40,9 +40,7 @@ import java.io.IOException; import java.io.Writer; public class dump { - public static void dump(DexBackedDexFile dexFile, String dumpFileName, int apiLevel) - throws IOException { - + public static void dump(DexBackedDexFile dexFile, String dumpFileName, int apiLevel) throws IOException { if (dumpFileName != null) { Writer writer = null; diff --git a/baksmali/src/main/java/org/jf/baksmali/main.java b/baksmali/src/main/java/org/jf/baksmali/main.java index 03386ccb..e86b2162 100644 --- a/baksmali/src/main/java/org/jf/baksmali/main.java +++ b/baksmali/src/main/java/org/jf/baksmali/main.java @@ -28,16 +28,19 @@ package org.jf.baksmali; +import com.google.common.collect.Lists; import org.apache.commons.cli.*; import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.analysis.CustomInlineMethodResolver; import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexBackedOdexFile; import org.jf.util.ConsoleUtil; import org.jf.util.SmaliHelpFormatter; +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -63,6 +66,7 @@ public class main { properties.load(templateStream); version = properties.getProperty("application.version"); } catch (IOException ex) { + // ignore } VERSION = version; } @@ -76,7 +80,7 @@ public class main { /** * Run! */ - public static void main(String[] args) { + public static void main(String[] args) throws IOException { Locale locale = new Locale("en", "US"); Locale.setDefault(locale); @@ -90,37 +94,18 @@ public class main { return; } + baksmaliOptions options = new baksmaliOptions(); + boolean disassemble = true; boolean doDump = false; - boolean noParameterRegisters = false; - boolean useLocalsDirective = false; - boolean useSequentialLabels = false; - boolean outputDebugInfo = true; - boolean addCodeOffsets = false; - boolean noAccessorComments = false; - boolean deodex = false; - boolean ignoreErrors = false; - boolean checkPackagePrivateAccess = false; - - int apiLevel = 15; - - int registerInfo = 0; - - String outputDirectory = "out"; String dumpFileName = null; - String inputDexFileName = null; - String bootClassPath = null; - StringBuffer extraBootClassPathEntries = new StringBuffer(); - List bootClassPathDirs = new ArrayList(); - bootClassPathDirs.add("."); - String inlineTable = null; String[] remainingArgs = commandLine.getArgs(); - Option[] options = commandLine.getOptions(); + Option[] clOptions = commandLine.getOptions(); - for (int i=0; i getDefaultBootClassPathForApi(int apiLevel) { + if (apiLevel < 9) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar"); + } else if (apiLevel < 12) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/core-junit.jar"); + } else if (apiLevel < 14) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/apache-xml.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/core-junit.jar"); + } else if (apiLevel < 16) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/core-junit.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/apache-xml.jar", + "/system/framework/filterfw.jar"); + + } else { + // this is correct as of api 17/4.2.2 + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/core-junit.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/telephony-common.jar", + "/system/framework/mms-common.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/apache-xml.jar"); + } + } } \ No newline at end of file diff --git a/baksmali/src/main/java/org/jf/baksmali/temp.java b/baksmali/src/main/java/org/jf/baksmali/temp.java deleted file mode 100644 index 2b34c0f9..00000000 --- a/baksmali/src/main/java/org/jf/baksmali/temp.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.jf.baksmali; - -import org.jf.dexlib2.dexbacked.BaseDexBuffer; - -public class temp { - public static void main(String[] args) { - BaseDexBuffer bdb = new BaseDexBuffer(new byte[]{1,2,3,4,5,6,7,8}); - long start = System.nanoTime(); - - for (long i=0; i<10000000000l; i++) { - bdb.readLong(0); - } - - long end = System.nanoTime(); - - System.out.println((end-start)/1E9d); - } - -}