aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Light <allight@google.com>2015-09-29 00:21:37 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-29 00:21:37 +0000
commitead82c22febb4fd84a27ff4713a049808b75ea60 (patch)
treede2d847e62f20a169d2eb23b5bf3bac140861d26
parent42ea50b665e6350789d881c2920ca351e7146273 (diff)
parenta0faada87c23afc2c8cfc4621ea481f44018bcbf (diff)
downloadsmali-ead82c22febb4fd84a27ff4713a049808b75ea60.tar.gz
am a0faada8: Merge "Merge remote-tracking branch \'aosp/upstream-master\' into aosp/master"
* commit 'a0faada87c23afc2c8cfc4621ea481f44018bcbf': Bump the version number to 2.0.8 Make smali respect order of implements Add ability to list methods/fields/types when assembling with smali Update README.md Handle invalid debug item offsets more gracefully Add backwards compatible version of DexFileFactory.loadDexFile and Opcodes Replace a missed usage of Iterators.emptyIterator() Bump the version number to 2.0.7 Remove usages of the deprecated Iterators.emptyIterator() method Add the generated accessorTest to source control Bump the version number to 2.0.6 Ensure that java 6 is used for release builds
-rw-r--r--README.md10
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java3
-rw-r--r--baksmali/src/test/java/org/jf/baksmali/InterfaceOrderTest.java41
-rw-r--r--baksmali/src/test/resources/InterfaceOrderTest/InterfaceOrder.smali37
-rw-r--r--build.gradle22
-rw-r--r--dexlib2/build.gradle47
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java11
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java4
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java28
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java13
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java4
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java11
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java4
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java12
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java7
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java13
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java5
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java2
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java32
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java13
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java2
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java10
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java2
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java6
-rw-r--r--dexlib2/src/test/resources/accessorTest.dexbin0 -> 28940 bytes
-rw-r--r--smali/src/main/java/org/jf/smali/main.java85
26 files changed, 323 insertions, 101 deletions
diff --git a/README.md b/README.md
index 52c24db9..57848991 100644
--- a/README.md
+++ b/README.md
@@ -2,16 +2,16 @@
smali/baksmali is an assembler/disassembler for the dex format used by dalvik, Android's Java VM implementation. The syntax is loosely based on Jasmin's/dedexer's syntax, and supports the full functionality of the dex format (annotations, debug info, line info, etc.)
-The primary webpage is http://smali.googlecode.com, and the source is also mirrored at https://github.com/jesusfreke/smali. If you are interested in submitting a patch, feel free to send me a pull request on either site.
+Downloads are at https://bitbucket.org/JesusFreke/smali/downloads. If you are interested in submitting a patch, feel free to send me a pull request here.
#### Support
-- [googlecode Issue tracker](https://code.google.com/p/smali/issues/list) - For any bugs/issues/feature requests
-- [#smali on freenode](http://webchat.freenode.net/?channels=smali) - Free free to drop by and ask a question. Don't expect an instant response, but if you hang around someone will respond. Think of it more in terms of.. multi-player notepad.
+- [github Issue tracker](https://github.com/JesusFreke/smali/issues) - For any bugs/issues/feature requests
+- [#smali on freenode](http://webchat.freenode.net/?channels=smali) - Free free to drop by and ask a question. Don't expect an instant response, but if you hang around someone will respond.
#### Some useful links for getting started with smali
- [Official dex bytecode reference](https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html)
-- [Registers wiki page](https://code.google.com/p/smali/wiki/Registers)
-- [Types, Methods and Fields wiki page](https://code.google.com/p/smali/wiki/TypesMethodsAndFields)
+- [Registers wiki page](https://github.com/JesusFreke/smali/wiki/Registers)
+- [Types, Methods and Fields wiki page](https://github.com/JesusFreke/smali/wiki/TypesMethodsAndFields)
- [Official dex format reference](https://source.android.com/devices/tech/dalvik/dex-format.html)
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/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/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
diff --git a/build.gradle b/build.gradle
index f0d1e00a..edf156fe 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,7 +31,7 @@
apply plugin: 'idea'
-version = '2.0.5'
+version = '2.0.8'
def jarVersion = version
@@ -57,6 +57,11 @@ if (!('release' in gradle.startParameter.taskNames)) {
// use something like module-1.2.3-dev.jar for the jar name, rather than the full
// module-1.2.3-001afe02-dirty.jar
jarVersion = baseVersion + '-dev'
+} else {
+ if (System.env.JDK6_HOME == null && !JavaVersion.current().isJava6()) {
+ throw new InvalidUserDataException("bzzzzzzzt. Release builds must be performed with java 6. " +
+ "Either run gradle with java 6, or define the JDK6_HOME environment variable.")
+ }
}
// Note: please don't use this. This is strictly for the official releases
@@ -79,6 +84,19 @@ subprojects {
}
}
+ if (System.env.JDK6_HOME != null) {
+ sourceCompatibility = 1.6
+ targetCompatibility = 1.6
+
+ tasks.withType(JavaCompile) {
+ doFirst {
+ options.fork = true
+ options.bootClasspath = "$System.env.JDK6_HOME/jre/lib/rt.jar"
+ options.bootClasspath += "$File.pathSeparator$System.env.JDK6_HOME/jre/lib/jsse.jar"
+ }
+ }
+ }
+
version = parent.version
ext {
@@ -90,7 +108,7 @@ subprojects {
stringtemplate: 'org.antlr:stringtemplate:3.2.1',
commons_cli: 'commons-cli:commons-cli:1.2',
jflex: 'de.jflex:jflex:1.4.3',
- jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.1',
+ jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.2',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
dx: 'com.google.android.tools:dx:1.7'
]
diff --git a/dexlib2/build.gradle b/dexlib2/build.gradle
index dc3e853a..8fbe5ffe 100644
--- a/dexlib2/build.gradle
+++ b/dexlib2/build.gradle
@@ -29,6 +29,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+ext.testAccessorOutputDir = file("${buildDir}/generated-src/accessorTest/java")
+ext.testAccessorOutputFile = file("${testAccessorOutputDir}/org/jf/dexlib2/AccessorTypes.java")
+
+sourceSets {
+ accessorTest {
+ java {
+ srcDir testAccessorOutputDir
+ }
+ }
+}
+
configurations {
accessorTestGenerator
dx
@@ -46,9 +57,6 @@ dependencies {
dx depends.dx
}
-ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources")
-ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java")
-
// You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file
// e.g. ./gradlew ragel
task ragel(type:Exec) {
@@ -59,48 +67,31 @@ task ragel(type:Exec) {
}
task generateAccessorTestSource(type: JavaExec) {
- doFirst {
- file(testAccessorOutputFile.parent).mkdirs()
- }
-
+ file(testAccessorOutputFile.parent).mkdirs()
outputs.dir file(testAccessorOutputDir)
- sourceSets['test'].java.srcDir file(testAccessorOutputDir)
classpath = configurations.accessorTestGenerator
main = 'org.jf.dexlib2.AccessorTestGenerator'
args testAccessorOutputFile
}
-compileTestJava.dependsOn generateAccessorTestSource
-
-task generateAccessorTestDex(type: JavaExec, dependsOn: compileTestJava) {
- def outputDex = file(new File(sourceSets.test.output.resourcesDir, 'accessorTest.dex'))
+compileAccessorTestJava.dependsOn(generateAccessorTestSource)
- doFirst {
- file(outputDex.parent).mkdirs()
-
- // this has to be done in doFirst, so that the generated classes will be available.
- // otherwise, it the tree will be populated while the build is being configured,
- // which is before the compileTestJava has run
- fileTree(project.sourceSets.test.output.classesDir) {
- include 'org/jf/dexlib2/AccessorTypes*.class'
- }.each { File file ->
- args file
- }
- }
+// You must manually execute this task to regenerate src/test/resources/accessorTest.dex
+task generateAccessorTestDex(type: JavaExec, dependsOn: compileAccessorTestJava) {
+ def outputDex = file('src/test/resources/accessorTest.dex')
+ file(outputDex.parent).mkdirs()
- inputs.dir(project.sourceSets.test.output.classesDir)
+ inputs.dir(project.sourceSets.accessorTest.output.classesDir)
outputs.file outputDex
main 'com.android.dx.command.Main'
classpath = configurations.dx
- workingDir project.sourceSets.test.output.classesDir
- //executable 'dx'
args '--dex'
args '--no-strict'
args "--output=${outputDex}"
+ args sourceSets.accessorTest.output.classesDir
}
-test.dependsOn generateAccessorTestDex
uploadArchives {
repositories.mavenDeployer {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
index a1ddee2e..113b60a3 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
@@ -45,12 +45,23 @@ import java.util.zip.ZipFile;
public final class DexFileFactory {
@Nonnull
+ public static DexBackedDexFile loadDexFile(String path, int api)
+ throws IOException {
+ return loadDexFile(path, api, false);
+ }
+
+ @Nonnull
public static DexBackedDexFile loadDexFile(String path, int api, boolean experimental)
throws IOException {
return loadDexFile(new File(path), "classes.dex", new Opcodes(api, experimental));
}
@Nonnull
+ public static DexBackedDexFile loadDexFile(File dexFile, int api) throws IOException {
+ return loadDexFile(dexFile, api, false);
+ }
+
+ @Nonnull
public static DexBackedDexFile loadDexFile(File dexFile, int api, boolean experimental)
throws IOException {
return loadDexFile(dexFile, "classes.dex", new Opcodes(api, experimental));
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
index dd876813..e718e275 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
@@ -40,6 +40,10 @@ public class Opcodes {
private final Opcode[] opcodesByValue;
private final HashMap<String, Opcode> opcodesByName;
+ public Opcodes(int api) {
+ this(api, false);
+ }
+
public Opcodes(int api, boolean experimental) {
opcodesByValue = new Opcode[256];
opcodesByName = Maps.newHashMap();
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java
index fc1dc62f..7e8a2829 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java
@@ -33,6 +33,7 @@ package org.jf.dexlib2.analysis.reflection;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils;
@@ -48,6 +49,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.AbstractSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
/**
@@ -78,23 +80,17 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef {
return ReflectionUtils.javaToDexName(superClass.getName());
}
- @Nonnull @Override public Set<String> getInterfaces() {
- return new AbstractSet<String>() {
- @Nonnull @Override public Iterator<String> iterator() {
- return Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() {
- @Nullable @Override public String apply(@Nullable Class input) {
- if (input == null) {
- return null;
- }
- return ReflectionUtils.javaToDexName(input.getName());
- }
- });
+ @Nonnull @Override public List<String> getInterfaces() {
+ return ImmutableList.copyOf(Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() {
+ @Nullable
+ @Override
+ public String apply(@Nullable Class input) {
+ if (input == null) {
+ return null;
+ }
+ return ReflectionUtils.javaToDexName(input.getName());
}
-
- @Override public int size() {
- return cls.getInterfaces().length;
- }
- };
+ }));
}
@Nullable @Override public String getSourceFile() {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
index 9596a278..88f1dce9 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
@@ -31,6 +31,7 @@
package org.jf.dexlib2.dexbacked;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.jf.dexlib2.base.reference.BaseTypeReference;
@@ -47,7 +48,9 @@ import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import java.util.AbstractList;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@@ -114,21 +117,21 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull
@Override
- public Set<String> getInterfaces() {
+ public List<String> getInterfaces() {
final int interfacesOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.INTERFACES_OFFSET);
if (interfacesOffset > 0) {
final int size = dexFile.readSmallUint(interfacesOffset);
- return new FixedSizeSet<String>() {
- @Nonnull
+ return new AbstractList<String>() {
@Override
- public String readItem(int index) {
+ @Nonnull
+ public String get(int index) {
return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
}
@Override public int size() { return size; }
};
}
- return ImmutableSet.of();
+ return ImmutableList.of();
}
@Nonnull
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
index f26b7e12..eccb9218 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
@@ -32,7 +32,7 @@
package org.jf.dexlib2.dexbacked;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterators;
+import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.dexbacked.raw.MethodIdItem;
import org.jf.dexlib2.dexbacked.raw.ProtoIdItem;
@@ -152,7 +152,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
if (methodImpl != null) {
return methodImpl.getParameterNames(null);
}
- return Iterators.emptyIterator();
+ return ImmutableSet.<String>of().iterator();
}
@Nonnull
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
index 0c06b1d7..676d86cd 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
@@ -123,7 +123,16 @@ public class DexBackedMethodImplementation implements MethodImplementation {
@Nonnull
private DebugInfo getDebugInfo() {
- return DebugInfo.newOrEmpty(dexFile, dexFile.readSmallUint(codeOffset + CodeItem.DEBUG_INFO_OFFSET), this);
+ int debugOffset = dexFile.readInt(codeOffset + CodeItem.DEBUG_INFO_OFFSET);
+
+ if (debugOffset == -1 || debugOffset == 0) {
+ return DebugInfo.newOrEmpty(dexFile, 0, this);
+ }
+ if (debugOffset < 0) {
+ System.err.println("%s: Invalid debug offset");
+ return DebugInfo.newOrEmpty(dexFile, 0, this);
+ }
+ return DebugInfo.newOrEmpty(dexFile, debugOffset, this);
}
@Nonnull @Override
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
index 9c79e270..27d72ad1 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
@@ -100,10 +100,10 @@ public class CodeItem {
int triesCount = reader.readUshort();
out.annotate(2, "tries_size = %d", triesCount);
- int debugInfoOffset = reader.readSmallUint();
+ int debugInfoOffset = reader.readInt();
out.annotate(4, "debug_info_off = 0x%x", debugInfoOffset);
- if (debugInfoOffset != 0) {
+ if (debugInfoOffset > 0) {
addDebugInfoIdentity(debugInfoOffset, itemIdentity);
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
index 6759820e..8a32b5f6 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
@@ -31,12 +31,12 @@
package org.jf.dexlib2.dexbacked.util;
-import com.google.common.collect.Iterators;
+import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.AccessFlags;
import org.jf.dexlib2.DebugItemType;
+import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexBackedMethod;
import org.jf.dexlib2.dexbacked.DexBackedMethodImplementation;
-import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.dexlib2.iface.debug.DebugItem;
@@ -70,9 +70,13 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
private static class EmptyDebugInfo extends DebugInfo {
public static final EmptyDebugInfo INSTANCE = new EmptyDebugInfo();
private EmptyDebugInfo() {}
- @Nonnull @Override public Iterator<DebugItem> iterator() { return Iterators.emptyIterator(); }
+
+ @Nonnull @Override public Iterator<DebugItem> iterator() {
+ return ImmutableSet.<DebugItem>of().iterator();
+ }
+
@Nonnull @Override public Iterator<String> getParameterNames(@Nullable DexReader reader) {
- return Iterators.emptyIterator();
+ return ImmutableSet.<String>of().iterator();
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java
index 31d7fb99..78e17b15 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java
@@ -35,6 +35,7 @@ import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import java.util.List;
import java.util.Set;
/**
@@ -72,11 +73,11 @@ public interface ClassDef extends TypeReference, Annotatable {
@Nullable String getSuperclass();
/**
- * Gets a set of the interfaces that this class implements.
+ * Gets a list of the interfaces that this class implements.
*
- * @return A set of the interfaces that this class implements
+ * @return A list of the interfaces that this class implements
*/
- @Nonnull Set<String> getInterfaces();
+ @Nonnull List<String> getInterfaces();
/**
* Gets the name of the primary source file that this class is defined in, if available.
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java
index 42e14549..8bdfff26 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java
@@ -47,12 +47,13 @@ import javax.annotation.Nullable;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
@Nonnull protected final String type;
protected final int accessFlags;
@Nullable protected final String superclass;
- @Nonnull protected final ImmutableSet<String> interfaces;
+ @Nonnull protected final ImmutableList<String> interfaces;
@Nullable protected final String sourceFile;
@Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations;
@Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields;
@@ -78,7 +79,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
this.type = type;
this.accessFlags = accessFlags;
this.superclass = superclass;
- this.interfaces = interfaces==null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(interfaces);
+ this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
this.sourceFile = sourceFile;
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
@@ -100,7 +101,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
this.type = type;
this.accessFlags = accessFlags;
this.superclass = superclass;
- this.interfaces = interfaces==null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(interfaces);
+ this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
this.sourceFile = sourceFile;
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
this.staticFields = ImmutableField.immutableSetOf(staticFields);
@@ -112,7 +113,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
public ImmutableClassDef(@Nonnull String type,
int accessFlags,
@Nullable String superclass,
- @Nullable ImmutableSet<String> interfaces,
+ @Nullable ImmutableList<String> interfaces,
@Nullable String sourceFile,
@Nullable ImmutableSet<? extends ImmutableAnnotation> annotations,
@Nullable ImmutableSortedSet<? extends ImmutableField> staticFields,
@@ -122,7 +123,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
this.type = type;
this.accessFlags = accessFlags;
this.superclass = superclass;
- this.interfaces = ImmutableUtils.nullToEmptySet(interfaces);
+ this.interfaces = ImmutableUtils.nullToEmptyList(interfaces);
this.sourceFile = sourceFile;
this.annotations = ImmutableUtils.nullToEmptySet(annotations);
this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields);
@@ -151,7 +152,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Override public String getType() { return type; }
@Override public int getAccessFlags() { return accessFlags; }
@Nullable @Override public String getSuperclass() { return superclass; }
- @Nonnull @Override public ImmutableSet<String> getInterfaces() { return interfaces; }
+ @Nonnull @Override public ImmutableList<String> getInterfaces() { return interfaces; }
@Nullable @Override public String getSourceFile() { return sourceFile; }
@Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; }
@Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; }
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java
index ad246e5b..7e34ee33 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/rewriter/ClassDefRewriter.java
@@ -41,6 +41,7 @@ import org.jf.dexlib2.iface.Method;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
public class ClassDefRewriter implements Rewriter<ClassDef> {
@@ -73,8 +74,8 @@ public class ClassDefRewriter implements Rewriter<ClassDef> {
return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), classDef.getSuperclass());
}
- @Override @Nonnull public Set<String> getInterfaces() {
- return RewriterUtils.rewriteSet(rewriters.getTypeRewriter(), classDef.getInterfaces());
+ @Override @Nonnull public List<String> getInterfaces() {
+ return RewriterUtils.rewriteList(rewriters.getTypeRewriter(), classDef.getInterfaces());
}
@Override @Nullable public String getSourceFile() {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java
index bb2e4a72..d28dd444 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java
@@ -53,7 +53,7 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
@Nonnull TypeKey getType(@Nonnull ClassKey key);
int getAccessFlags(@Nonnull ClassKey key);
@Nullable TypeKey getSuperclass(@Nonnull ClassKey key);
- @Nullable TypeListKey getSortedInterfaces(@Nonnull ClassKey key);
+ @Nullable TypeListKey getInterfaces(@Nonnull ClassKey key);
@Nullable StringKey getSourceFile(@Nonnull ClassKey key);
@Nullable Collection<? extends EncodedValue> getStaticInitializers(@Nonnull ClassKey key);
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
index 0650ab3c..be23978e 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
@@ -58,6 +58,7 @@ import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.dexlib2.util.InstructionUtil;
import org.jf.dexlib2.util.MethodUtil;
+import org.jf.dexlib2.util.ReferenceUtil;
import org.jf.dexlib2.writer.io.DeferredOutputStream;
import org.jf.dexlib2.writer.io.DeferredOutputStreamFactory;
import org.jf.dexlib2.writer.io.DexDataStore;
@@ -196,6 +197,33 @@ public abstract class DexWriter<
classSection.getItems().size() * ClassDefItem.ITEM_SIZE;
}
+ @Nonnull
+ public List<String> getMethodReferences() {
+ List<String> methodReferences = Lists.newArrayList();
+ for (Entry<? extends MethodRefKey, Integer> methodReference: methodSection.getItems()) {
+ methodReferences.add(ReferenceUtil.getMethodDescriptor(methodReference.getKey()));
+ }
+ return methodReferences;
+ }
+
+ @Nonnull
+ public List<String> getFieldReferences() {
+ List<String> fieldReferences = Lists.newArrayList();
+ for (Entry<? extends FieldRefKey, Integer> fieldReference: fieldSection.getItems()) {
+ fieldReferences.add(ReferenceUtil.getFieldDescriptor(fieldReference.getKey()));
+ }
+ return fieldReferences;
+ }
+
+ @Nonnull
+ public List<String> getTypeReferences() {
+ List<String> classReferences = Lists.newArrayList();
+ for (Entry<? extends TypeKey, Integer> typeReference: typeSection.getItems()) {
+ classReferences.add(typeReference.getKey().toString());
+ }
+ return classReferences;
+ }
+
public void writeTo(@Nonnull DexDataStore dest) throws IOException {
this.writeTo(dest, MemoryDeferredOutputStream.getFactory());
}
@@ -405,7 +433,7 @@ public abstract class DexWriter<
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, superEntry);
// then, try to write interfaces
- for (TypeKey interfaceTypeKey: typeListSection.getTypes(classSection.getSortedInterfaces(key))) {
+ for (TypeKey interfaceTypeKey: typeListSection.getTypes(classSection.getInterfaces(key))) {
Map.Entry<? extends ClassKey, Integer> interfaceEntry = classSection.getClassEntryByType(interfaceTypeKey);
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, interfaceEntry);
}
@@ -418,7 +446,7 @@ public abstract class DexWriter<
indexWriter.writeInt(typeSection.getItemIndex(classSection.getType(key)));
indexWriter.writeInt(classSection.getAccessFlags(key));
indexWriter.writeInt(typeSection.getNullableItemIndex(classSection.getSuperclass(key)));
- indexWriter.writeInt(typeListSection.getNullableItemOffset(classSection.getSortedInterfaces(key)));
+ indexWriter.writeInt(typeListSection.getNullableItemOffset(classSection.getInterfaces(key)));
indexWriter.writeInt(stringSection.getNullableItemIndex(classSection.getSourceFile(key)));
indexWriter.writeInt(classSection.getAnnotationDirectoryOffset(key));
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java
index f19a2e7f..10215925 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java
@@ -31,6 +31,7 @@
package org.jf.dexlib2.writer.builder;
+import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.*;
import org.jf.dexlib2.base.reference.BaseTypeReference;
@@ -101,16 +102,8 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Override public SortedSet<BuilderMethod> getVirtualMethods() { return virtualMethods; }
@Nonnull @Override
- public Set<String> getInterfaces() {
- return new AbstractSet<String>() {
- @Nonnull @Override public Iterator<String> iterator() {
- return Iterators.transform(interfaces.iterator(), Functions.toStringFunction());
- }
-
- @Override public int size() {
- return interfaces.size();
- }
- };
+ public List<String> getInterfaces() {
+ return Lists.transform(this.interfaces, Functions.toStringFunction());
}
@Nonnull @Override public Collection<BuilderField> getFields() {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java
index 8ab53db8..29980f32 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java
@@ -122,7 +122,7 @@ public class BuilderClassPool implements ClassSection<BuilderStringReference, Bu
return builderClassDef.superclass;
}
- @Nullable @Override public BuilderTypeList getSortedInterfaces(@Nonnull BuilderClassDef builderClassDef) {
+ @Nullable @Override public BuilderTypeList getInterfaces(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.interfaces;
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java
index 469a3324..9a727b27 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java
@@ -35,6 +35,7 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.MethodImplementation;
@@ -117,16 +118,15 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
if (interfaces == null) {
interfaces = ImmutableList.of();
} else {
- interfaces = Lists.newArrayList(interfaces);
- Collections.sort(interfaces);
- String prev = null;
+ Set<String> interfaces_copy = Sets.newHashSet(interfaces);
Iterator<String> interfaceIterator = interfaces.iterator();
while (interfaceIterator.hasNext()) {
String iface = interfaceIterator.next();
- if (prev != null && iface.equals(prev)) {
+ if (!interfaces_copy.contains(iface)) {
interfaceIterator.remove();
+ } else {
+ interfaces_copy.remove(iface);
}
- prev = iface;
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java
index 96eca2ae..0389973a 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java
@@ -250,7 +250,7 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
return classDef.getSuperclass();
}
- @Nullable @Override public TypeListPool.Key<SortedSet<String>> getSortedInterfaces(@Nonnull PoolClassDef classDef) {
+ @Nullable @Override public TypeListPool.Key<List<String>> getInterfaces(@Nonnull PoolClassDef classDef) {
return classDef.interfaces;
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java
index fe897d26..00958fb8 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java
@@ -43,7 +43,7 @@ import java.util.*;
class PoolClassDef extends BaseTypeReference implements ClassDef {
@Nonnull final ClassDef classDef;
- @Nonnull final TypeListPool.Key<SortedSet<String>> interfaces;
+ @Nonnull final TypeListPool.Key<List<String>> interfaces;
@Nonnull final ImmutableSortedSet<Field> staticFields;
@Nonnull final ImmutableSortedSet<Field> instanceFields;
@Nonnull final ImmutableSortedSet<PoolMethod> directMethods;
@@ -56,7 +56,7 @@ class PoolClassDef extends BaseTypeReference implements ClassDef {
PoolClassDef(@Nonnull ClassDef classDef) {
this.classDef = classDef;
- interfaces = new TypeListPool.Key<SortedSet<String>>(ImmutableSortedSet.copyOf(classDef.getInterfaces()));
+ interfaces = new TypeListPool.Key<List<String>>(ImmutableList.copyOf(classDef.getInterfaces()));
staticFields = ImmutableSortedSet.copyOf(classDef.getStaticFields());
instanceFields = ImmutableSortedSet.copyOf(classDef.getInstanceFields());
directMethods = ImmutableSortedSet.copyOf(
@@ -77,7 +77,7 @@ class PoolClassDef extends BaseTypeReference implements ClassDef {
return classDef.getSuperclass();
}
- @Nonnull @Override public SortedSet<String> getInterfaces() {
+ @Nonnull @Override public List<String> getInterfaces() {
return interfaces.types;
}
diff --git a/dexlib2/src/test/resources/accessorTest.dex b/dexlib2/src/test/resources/accessorTest.dex
new file mode 100644
index 00000000..456f85f4
--- /dev/null
+++ b/dexlib2/src/test/resources/accessorTest.dex
Binary files differ
diff --git a/smali/src/main/java/org/jf/smali/main.java b/smali/src/main/java/org/jf/smali/main.java
index 31f65a88..98fb7a1f 100644
--- a/smali/src/main/java/org/jf/smali/main.java
+++ b/smali/src/main/java/org/jf/smali/main.java
@@ -28,7 +28,9 @@
package org.jf.smali;
+import com.google.common.base.Strings;
import com.google.common.collect.Lists;
+import com.google.common.collect.Ordering;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenSource;
@@ -113,6 +115,15 @@ public class main {
boolean printTokens = false;
boolean experimental = false;
+ boolean listMethods = false;
+ String methodListFilename = null;
+
+ boolean listFields = false;
+ String fieldListFilename = null;
+
+ boolean listTypes = false;
+ String typeListFilename = null;
+
int apiLevel = 15;
String outputDexFile = "out.dex";
@@ -153,6 +164,18 @@ public class main {
case 'j':
jobs = Integer.parseInt(commandLine.getOptionValue("j"));
break;
+ case 'm':
+ listMethods = true;
+ methodListFilename = commandLine.getOptionValue("m");
+ break;
+ case 'f':
+ listFields = true;
+ fieldListFilename = commandLine.getOptionValue("f");
+ break;
+ case 't':
+ listTypes = true;
+ typeListFilename = commandLine.getOptionValue("t");
+ break;
case 'V':
verboseErrors = true;
break;
@@ -232,6 +255,27 @@ public class main {
System.exit(1);
}
+ if (listMethods) {
+ if (Strings.isNullOrEmpty(methodListFilename)) {
+ methodListFilename = outputDexFile + ".methods";
+ }
+ writeReferences(dexBuilder.getMethodReferences(), methodListFilename);
+ }
+
+ if (listFields) {
+ if (Strings.isNullOrEmpty(fieldListFilename)) {
+ fieldListFilename = outputDexFile + ".fields";
+ }
+ writeReferences(dexBuilder.getFieldReferences(), fieldListFilename);
+ }
+
+ if (listTypes) {
+ if (Strings.isNullOrEmpty(typeListFilename)) {
+ typeListFilename = outputDexFile + ".types";
+ }
+ writeReferences(dexBuilder.getTypeReferences(), typeListFilename);
+ }
+
dexBuilder.writeTo(new FileDataStore(new File(outputDexFile)));
} catch (RuntimeException ex) {
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
@@ -244,6 +288,23 @@ public class main {
}
}
+ private static void writeReferences(List<String> references, String filename) {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
+
+ for (String reference: Ordering.natural().sortedCopy(references)) {
+ writer.println(reference);
+ }
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
private static void getSmaliFilesInDir(@Nonnull File dir, @Nonnull Set<File> smaliFiles) {
File[] files = dir.listFiles();
if (files != null) {
@@ -378,6 +439,27 @@ public class main {
.withArgName("API_LEVEL")
.create("a");
+ Option listMethodsOption = OptionBuilder.withLongOpt("list-methods")
+ .withDescription("Lists all the method references to FILE" +
+ " (<output_dex_filename>.methods by default)")
+ .hasOptionalArg()
+ .withArgName("FILE")
+ .create("m");
+
+ Option listFieldsOption = OptionBuilder.withLongOpt("list-fields")
+ .withDescription("Lists all the field references to FILE" +
+ " (<output_dex_filename>.fields by default)")
+ .hasOptionalArg()
+ .withArgName("FILE")
+ .create("f");
+
+ Option listClassesOption = OptionBuilder.withLongOpt("list-types")
+ .withDescription("Lists all the type references to FILE" +
+ " (<output_dex_filename>.types by default)")
+ .hasOptionalArg()
+ .withArgName("FILE")
+ .create("t");
+
Option experimentalOption = OptionBuilder.withLongOpt("experimental")
.withDescription("enable experimental opcodes to be assembled, even if they " +
" aren't necessarily supported by the Android runtime yet")
@@ -405,6 +487,9 @@ public class main {
basicOptions.addOption(apiLevelOption);
basicOptions.addOption(experimentalOption);
basicOptions.addOption(jobsOption);
+ basicOptions.addOption(listMethodsOption);
+ basicOptions.addOption(listFieldsOption);
+ basicOptions.addOption(listClassesOption);
debugOptions.addOption(verboseErrorsOption);
debugOptions.addOption(printTokensOption);