aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java28
-rw-r--r--smali/src/main/java/org/jf/smali/main.java85
2 files changed, 113 insertions, 0 deletions
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..916147ec 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());
}
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);