aboutsummaryrefslogtreecommitdiff
path: root/baksmali
diff options
context:
space:
mode:
authorBen Gruver <bgruv@google.com>2015-10-01 08:34:21 -0700
committerBen Gruver <bgruv@google.com>2015-10-01 08:34:21 -0700
commitea3fdd7e860db85a062bbadc90f3a5a7555d0d25 (patch)
tree4aae5978087484137ef0a55da1c5d38059c8d102 /baksmali
parent546fdfe3d10ed255daf016d9707c12ac659dd50e (diff)
parenta9dcd62b92ceac9cadb5a3b828852f13349ae78e (diff)
downloadsmali-ea3fdd7e860db85a062bbadc90f3a5a7555d0d25.tar.gz
Merge branch 'master' into smalidea
Diffstat (limited to 'baksmali')
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java3
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java5
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/baksmali.java9
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java4
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/dump.java2
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/main.java53
-rw-r--r--baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java2
-rw-r--r--baksmali/src/test/java/org/jf/baksmali/InterfaceOrderTest.java41
-rw-r--r--baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali1
-rw-r--r--baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali2
-rw-r--r--baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali1
-rw-r--r--baksmali/src/test/resources/InterfaceOrderTest/InterfaceOrder.smali37
12 files changed, 135 insertions, 25 deletions
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java
index 9c171f49..2529af8a 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java
@@ -146,8 +146,7 @@ public class ClassDefinition {
}
private void writeInterfaces(IndentingWriter writer) throws IOException {
- List<String> interfaces = Lists.newArrayList(classDef.getInterfaces());
- Collections.sort(interfaces);
+ List<String> interfaces = classDef.getInterfaces();
if (interfaces.size() != 0) {
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 4081a75c..6e009fb7 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java
@@ -366,7 +366,8 @@ public class MethodDefinition {
private List<MethodItem> getMethodItems() {
ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>();
- if ((classDef.options.registerInfo != 0) || (classDef.options.deodex && needsAnalyzed())) {
+ if ((classDef.options.registerInfo != 0) || (classDef.options.normalizeVirtualMethods) ||
+ (classDef.options.deodex && needsAnalyzed())) {
addAnalyzedInstructionMethodItems(methodItems);
} else {
addInstructionMethodItems(methodItems);
@@ -460,7 +461,7 @@ public class MethodDefinition {
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method,
- classDef.options.inlineResolver);
+ classDef.options.inlineResolver, classDef.options.normalizeVirtualMethods);
AnalysisException analysisException = methodAnalyzer.getAnalysisException();
if (analysisException != null) {
diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmali.java b/baksmali/src/main/java/org/jf/baksmali/baksmali.java
index 47fa406d..1e297029 100644
--- a/baksmali/src/main/java/org/jf/baksmali/baksmali.java
+++ b/baksmali/src/main/java/org/jf/baksmali/baksmali.java
@@ -44,19 +44,18 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.*;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
public class baksmali {
public static boolean disassembleDexFile(DexFile dexFile, final baksmaliOptions options) {
- if (options.registerInfo != 0 || options.deodex) {
+ if (options.registerInfo != 0 || options.deodex || options.normalizeVirtualMethods) {
try {
Iterable<String> extraClassPathEntries;
if (options.extraClassPathEntries != null) {
diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java b/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java
index b6cc1571..5dd060f1 100644
--- a/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java
+++ b/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java
@@ -36,6 +36,7 @@ import org.jf.dexlib2.analysis.ClassPath;
import org.jf.dexlib2.analysis.InlineMethodResolver;
import org.jf.dexlib2.util.SyntheticAccessorResolver;
+import javax.annotation.Nullable;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
@@ -54,7 +55,7 @@ public class baksmaliOptions {
public int apiLevel = 15;
public String outputDirectory = "out";
- public String dexEntry = "classes.dex";
+ @Nullable public String dexEntry = null;
public List<String> bootClassPathDirs = Lists.newArrayList();
public List<String> bootClassPathEntries = Lists.newArrayList();
@@ -75,6 +76,7 @@ public class baksmaliOptions {
public boolean ignoreErrors = false;
public boolean checkPackagePrivateAccess = false;
public boolean useImplicitReferences = false;
+ public boolean normalizeVirtualMethods = false;
public File customInlineDefinitions = null;
public InlineMethodResolver inlineResolver = null;
public int registerInfo = 0;
diff --git a/baksmali/src/main/java/org/jf/baksmali/dump.java b/baksmali/src/main/java/org/jf/baksmali/dump.java
index 1ef7df0e..57a48af8 100644
--- a/baksmali/src/main/java/org/jf/baksmali/dump.java
+++ b/baksmali/src/main/java/org/jf/baksmali/dump.java
@@ -52,7 +52,7 @@ public class dump {
consoleWidth = 120;
}
- RawDexFile rawDexFile = new RawDexFile(new Opcodes(apiLevel, experimental), dexFile);
+ RawDexFile rawDexFile = new RawDexFile(Opcodes.forApi(apiLevel), dexFile);
DexAnnotator annotator = new DexAnnotator(rawDexFile, consoleWidth);
annotator.writeAnnotations(writer);
} catch (IOException ex) {
diff --git a/baksmali/src/main/java/org/jf/baksmali/main.java b/baksmali/src/main/java/org/jf/baksmali/main.java
index 71598fa6..17ec3839 100644
--- a/baksmali/src/main/java/org/jf/baksmali/main.java
+++ b/baksmali/src/main/java/org/jf/baksmali/main.java
@@ -31,9 +31,11 @@ package org.jf.baksmali;
import com.google.common.collect.Lists;
import org.apache.commons.cli.*;
import org.jf.dexlib2.DexFileFactory;
+import org.jf.dexlib2.DexFileFactory.MultipleDexFilesException;
import org.jf.dexlib2.analysis.InlineMethodResolver;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexBackedOdexFile;
+import org.jf.dexlib2.dexbacked.OatFile.OatDexFile;
import org.jf.util.ConsoleUtil;
import org.jf.util.SmaliHelpFormatter;
@@ -217,6 +219,9 @@ public class main {
case 'k':
options.checkPackagePrivateAccess = true;
break;
+ case 'n':
+ options.normalizeVirtualMethods = true;
+ break;
case 'N':
disassemble = false;
break;
@@ -256,10 +261,20 @@ public class main {
}
//Read in and parse the dex file
- DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, options.dexEntry,
- options.apiLevel, options.experimental);
+ DexBackedDexFile dexFile = null;
+ try {
+ dexFile = DexFileFactory.loadDexFile(dexFileFile, options.dexEntry, options.apiLevel, options.experimental);
+ } catch (MultipleDexFilesException ex) {
+ System.err.println(String.format("%s contains multiple dex files. You must specify which one to " +
+ "disassemble with the -e option", dexFileFile.getName()));
+ System.err.println("Valid entries include:");
+ for (OatDexFile oatDexFile: ex.oatFile.getDexFiles()) {
+ System.err.println(oatDexFile.filename);
+ }
+ System.exit(1);
+ }
- if (dexFile.isOdexFile()) {
+ if (dexFile.hasOdexOpcodes()) {
if (!options.deodex) {
System.err.println("Warning: You are disassembling an odex file without deodexing it. You");
System.err.println("won't be able to re-assemble the results unless you deodex it with the -x");
@@ -270,7 +285,7 @@ public class main {
options.deodex = false;
}
- if (!setBootClassPath && (options.deodex || options.registerInfo != 0)) {
+ if (!setBootClassPath && (options.deodex || options.registerInfo != 0 || options.normalizeVirtualMethods)) {
if (dexFile instanceof DexBackedOdexFile) {
options.bootClassPathEntries = ((DexBackedOdexFile)dexFile).getDependencies();
} else {
@@ -391,9 +406,9 @@ public class main {
.create("r");
Option classPathOption = OptionBuilder.withLongOpt("bootclasspath")
- .withDescription("the bootclasspath jars to use, for analysis. Defaults to " +
- "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If the value begins with a " +
- ":, it will be appended to the default bootclasspath instead of replacing it")
+ .withDescription("A colon-separated list of bootclasspath jar/oat files to use for analysis. Add an " +
+ "initial colon to specify that the jars/oats should be appended to the default bootclasspath " +
+ "instead of replacing it")
.hasOptionalArg()
.withArgName("BOOTCLASSPATH")
.create("c");
@@ -445,6 +460,10 @@ public class main {
"4.2.1.")
.create("k");
+ Option normalizeVirtualMethods = OptionBuilder.withLongOpt("normalize-virtual-methods")
+ .withDescription("Normalize virtual method references to the reference the base method.")
+ .create("n");
+
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
.withDescription("dumps the given dex file into a single annotated dump file named FILE" +
" (<dexfile>.dump by default), along with the normal disassembly")
@@ -494,6 +513,7 @@ public class main {
basicOptions.addOption(noImplicitReferencesOption);
basicOptions.addOption(dexEntryOption);
basicOptions.addOption(checkPackagePrivateAccessOption);
+ basicOptions.addOption(normalizeVirtualMethods);
debugOptions.addOption(dumpOption);
debugOptions.addOption(ignoreErrorsOption);
@@ -547,8 +567,7 @@ public class main {
"/system/framework/services.jar",
"/system/framework/apache-xml.jar",
"/system/framework/filterfw.jar");
-
- } else {
+ } else if (apiLevel < 21) {
// this is correct as of api 17/4.2.2
return Lists.newArrayList(
"/system/framework/core.jar",
@@ -561,6 +580,22 @@ public class main {
"/system/framework/android.policy.jar",
"/system/framework/services.jar",
"/system/framework/apache-xml.jar");
+ } else { // api >= 21
+ // TODO: verify, add new ones?
+ return Lists.newArrayList(
+ "/system/framework/core-libart.jar",
+ "/system/framework/conscrypt.jar",
+ "/system/framework/okhttp.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/voip-common.jar",
+ "/system/framework/ims-common.jar",
+ "/system/framework/mms-common.jar",
+ "/system/framework/android.policy.jar",
+ "/system/framework/apache-xml.jar");
}
}
}
diff --git a/baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java b/baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java
index 35304f7e..1fbafeab 100644
--- a/baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java
+++ b/baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java
@@ -81,7 +81,7 @@ public class DisassemblyTest {
String inputFilename = getInputFilename(testName);
byte[] inputBytes = BaksmaliTestUtils.readResourceBytesFully(getInputFilename(testName));
- DexBackedDexFile inputDex = new DexBackedDexFile(new Opcodes(options.apiLevel, false), inputBytes);
+ DexBackedDexFile inputDex = new DexBackedDexFile(Opcodes.forApi(options.apiLevel), inputBytes);
Assert.assertEquals(1, inputDex.getClassCount());
ClassDef inputClass = Iterables.getFirst(inputDex.getClasses(), null);
Assert.assertNotNull(inputClass);
diff --git a/baksmali/src/test/java/org/jf/baksmali/InterfaceOrderTest.java b/baksmali/src/test/java/org/jf/baksmali/InterfaceOrderTest.java
new file mode 100644
index 00000000..d85d7913
--- /dev/null
+++ b/baksmali/src/test/java/org/jf/baksmali/InterfaceOrderTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015, 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.junit.Test;
+
+public class InterfaceOrderTest extends IdenticalRoundtripTest {
+ @Test
+ public void testInterfaceOrder() {
+ runTest("InterfaceOrder", new baksmaliOptions());
+ }
+}
diff --git a/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali b/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali
index b1f30c9a..fd43b021 100644
--- a/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali
+++ b/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali
@@ -22,7 +22,6 @@
# return-void
# .end method
-
.method private clah()V
.registers 1
diff --git a/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali b/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali
index 8d87c1d8..52865737 100644
--- a/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali
+++ b/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali
@@ -17,7 +17,6 @@
# .end method
-
# virtual methods
.method public alah()V
.registers 1
@@ -40,7 +39,6 @@
# return-void
# .end method
-
.method public clah()V
.registers 1
diff --git a/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali b/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali
index 74af4c58..3c080024 100644
--- a/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali
+++ b/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali
@@ -22,7 +22,6 @@
# return-void
# .end method
-
.method public clah()V
.registers 1
diff --git a/baksmali/src/test/resources/InterfaceOrderTest/InterfaceOrder.smali b/baksmali/src/test/resources/InterfaceOrderTest/InterfaceOrder.smali
new file mode 100644
index 00000000..b4745cb3
--- /dev/null
+++ b/baksmali/src/test/resources/InterfaceOrderTest/InterfaceOrder.smali
@@ -0,0 +1,37 @@
+.class public LInterfaceOrder;
+.super Ljava/lang/Object;
+
+# Note how these two interfaces are not in alphabetical order
+.implements Ljava/io/Serializable;
+.implements Ljava/util/EventListener;
+.implements Ljava/lang/Runnable;
+.implements Ljava/io/Flushable;
+.implements Ljava/lang/Clonable;
+.implements Ljava/util/Observer;
+.implements Ljava/io/Closeable;
+
+# direct methods
+.method public constructor <init>()V
+ .registers 1
+ return-void
+.end method
+
+.method public close()V
+ .registers 1
+ return-void
+.end method
+
+.method public flush()V
+ .registers 1
+ return-void
+.end method
+
+.method public run()V
+ .registers 1
+ return-void
+.end method
+
+.method public update(Ljava/util/Observable;Ljava/lang/Object;)V
+ .registers 3
+ return-void
+.end method