diff options
author | Ben Gruver <bgruv@google.com> | 2015-10-01 08:34:21 -0700 |
---|---|---|
committer | Ben Gruver <bgruv@google.com> | 2015-10-01 08:34:21 -0700 |
commit | ea3fdd7e860db85a062bbadc90f3a5a7555d0d25 (patch) | |
tree | 4aae5978087484137ef0a55da1c5d38059c8d102 /smali | |
parent | 546fdfe3d10ed255daf016d9707c12ac659dd50e (diff) | |
parent | a9dcd62b92ceac9cadb5a3b828852f13349ae78e (diff) | |
download | smali-ea3fdd7e860db85a062bbadc90f3a5a7555d0d25.tar.gz |
Merge branch 'master' into smalidea
Diffstat (limited to 'smali')
-rw-r--r-- | smali/src/main/antlr/smaliParser.g | 2 | ||||
-rw-r--r-- | smali/src/main/antlr/smaliTreeWalker.g | 2 | ||||
-rw-r--r-- | smali/src/main/java/org/jf/smali/SmaliTestUtils.java | 5 | ||||
-rw-r--r-- | smali/src/main/java/org/jf/smali/main.java | 90 | ||||
-rw-r--r-- | smali/src/main/jflex/smaliLexer.jflex | 6 | ||||
-rw-r--r-- | smali/src/test/resources/LexerTest/InstructionTest.smali | 5 | ||||
-rw-r--r-- | smali/src/test/resources/LexerTest/InstructionTest.tokens | 5 |
7 files changed, 106 insertions, 9 deletions
diff --git a/smali/src/main/antlr/smaliParser.g b/smali/src/main/antlr/smaliParser.g index 9fcf2f1d..0ce825c1 100644 --- a/smali/src/main/antlr/smaliParser.g +++ b/smali/src/main/antlr/smaliParser.g @@ -257,7 +257,7 @@ import org.jf.dexlib2.Opcodes; private boolean verboseErrors = false; private boolean allowOdex = false; private int apiLevel = 15; - private Opcodes opcodes = new Opcodes(apiLevel, false); + private Opcodes opcodes = Opcodes.forApi(apiLevel); public void setVerboseErrors(boolean verboseErrors) { this.verboseErrors = verboseErrors; diff --git a/smali/src/main/antlr/smaliTreeWalker.g b/smali/src/main/antlr/smaliTreeWalker.g index 0d2623b0..c3a50994 100644 --- a/smali/src/main/antlr/smaliTreeWalker.g +++ b/smali/src/main/antlr/smaliTreeWalker.g @@ -77,7 +77,7 @@ import java.util.*; public String classType; private boolean verboseErrors = false; private int apiLevel = 15; - private Opcodes opcodes = new Opcodes(apiLevel, false); + private Opcodes opcodes = Opcodes.forApi(apiLevel); private DexBuilder dexBuilder; public void setDexBuilder(DexBuilder dexBuilder) { diff --git a/smali/src/main/java/org/jf/smali/SmaliTestUtils.java b/smali/src/main/java/org/jf/smali/SmaliTestUtils.java index 26de0089..bef07414 100644 --- a/smali/src/main/java/org/jf/smali/SmaliTestUtils.java +++ b/smali/src/main/java/org/jf/smali/SmaliTestUtils.java @@ -57,7 +57,7 @@ public class SmaliTestUtils { throws RecognitionException, IOException { CommonTokenStream tokens; LexerErrorInterface lexer; - DexBuilder dexBuilder = DexBuilder.makeDexBuilder(apiLevel); + DexBuilder dexBuilder = DexBuilder.makeDexBuilder(Opcodes.forApi(apiLevel, experimental)); Reader reader = new StringReader(smaliText); @@ -94,8 +94,7 @@ public class SmaliTestUtils { dexBuilder.writeTo(dataStore); - DexBackedDexFile dexFile = new DexBackedDexFile( - new Opcodes(apiLevel, experimental), dataStore.getData()); + DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.forApi(apiLevel, experimental), dataStore.getData()); return Iterables.getFirst(dexFile.getClasses(), null); } diff --git a/smali/src/main/java/org/jf/smali/main.java b/smali/src/main/java/org/jf/smali/main.java index 31f65a88..b36b088d 100644 --- a/smali/src/main/java/org/jf/smali/main.java +++ b/smali/src/main/java/org/jf/smali/main.java @@ -28,14 +28,16 @@ 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; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTreeNodeStream; -import org.antlr.runtime.tree.TreeNodeStream; import org.apache.commons.cli.*; +import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.writer.builder.DexBuilder; import org.jf.dexlib2.writer.io.FileDataStore; import org.jf.util.ConsoleUtil; @@ -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; @@ -195,7 +218,8 @@ public class main { boolean errors = false; - final DexBuilder dexBuilder = DexBuilder.makeDexBuilder(apiLevel); + final DexBuilder dexBuilder = DexBuilder.makeDexBuilder(Opcodes.forApi(apiLevel, experimental)); + ExecutorService executor = Executors.newFixedThreadPool(jobs); List<Future<Boolean>> tasks = Lists.newArrayList(); @@ -232,6 +256,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 +289,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 +440,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 +488,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); diff --git a/smali/src/main/jflex/smaliLexer.jflex b/smali/src/main/jflex/smaliLexer.jflex index d7fd6cab..2f57a438 100644 --- a/smali/src/main/jflex/smaliLexer.jflex +++ b/smali/src/main/jflex/smaliLexer.jflex @@ -421,7 +421,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT10x); } - "return-void-barrier" { + "return-void-barrier" | "return-void-no-barrier" { return newToken(INSTRUCTION_FORMAT10x_ODEX); } @@ -522,7 +522,9 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | "liberate-variable" { return newToken(INSTRUCTION_FORMAT22c_STRING); } - "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" { + + "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" | + "iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" { return newToken(INSTRUCTION_FORMAT22cs_FIELD); } diff --git a/smali/src/test/resources/LexerTest/InstructionTest.smali b/smali/src/test/resources/LexerTest/InstructionTest.smali index f6dcbb1e..174cff8c 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.smali +++ b/smali/src/test/resources/LexerTest/InstructionTest.smali @@ -2,6 +2,7 @@ goto return-void nop return-void-barrier +return-void-no-barrier const/4 move-result move-result-wide @@ -132,6 +133,10 @@ iget-object-quick iput-quick iput-wide-quick iput-object-quick +iput-boolean-quick +iput-byte-quick +iput-char-quick +iput-short-quick rsub-int add-int/lit16 mul-int/lit16 diff --git a/smali/src/test/resources/LexerTest/InstructionTest.tokens b/smali/src/test/resources/LexerTest/InstructionTest.tokens index fb5503b5..fa959bad 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -2,6 +2,7 @@ INSTRUCTION_FORMAT10t("goto") INSTRUCTION_FORMAT10x("return-void") INSTRUCTION_FORMAT10x("nop") INSTRUCTION_FORMAT10x_ODEX("return-void-barrier") +INSTRUCTION_FORMAT10x_ODEX("return-void-no-barrier") INSTRUCTION_FORMAT11n("const/4") INSTRUCTION_FORMAT11x("move-result") INSTRUCTION_FORMAT11x("move-result-wide") @@ -132,6 +133,10 @@ INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick") INSTRUCTION_FORMAT22cs_FIELD("iput-quick") INSTRUCTION_FORMAT22cs_FIELD("iput-wide-quick") INSTRUCTION_FORMAT22cs_FIELD("iput-object-quick") +INSTRUCTION_FORMAT22cs_FIELD("iput-boolean-quick") +INSTRUCTION_FORMAT22cs_FIELD("iput-byte-quick") +INSTRUCTION_FORMAT22cs_FIELD("iput-char-quick") +INSTRUCTION_FORMAT22cs_FIELD("iput-short-quick") INSTRUCTION_FORMAT22s_OR_ID("rsub-int") INSTRUCTION_FORMAT22s("add-int/lit16") INSTRUCTION_FORMAT22s("mul-int/lit16") |