diff --git a/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java b/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java new file mode 100644 index 00000000..30823761 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java @@ -0,0 +1,112 @@ +/* + * Copyright 2016, 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.DexFileFactory; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.OatFile; + +import javax.annotation.Nonnull; +import java.io.File; +import java.io.IOException; + +/** + * This class implements common functionality for commands that need to load a dex file based on + * command line input + */ +public abstract class DexInputCommand implements Command { + + /** + * Parses a dex file input from the user and loads the given dex file. + * + * @param input The name of a dex, apk, odex or oat file. For apk or oat files with multiple dex files, the input + * can additionally consist of a colon followed by a specific dex entry to load. + * @param apiLevel The api level to load the dex file with + * @param experimentalOpcodes whether experimental opcodes should be allowed + * @return The loaded DexBackedDexFile + */ + @Nonnull + protected DexBackedDexFile loadDexFile(@Nonnull String input, int apiLevel, boolean experimentalOpcodes) { + File dexFileFile = new File(input); + String dexFileEntry = null; + + int previousIndex = input.length(); + while (!dexFileFile.exists()) { + int colonIndex = input.lastIndexOf(':', previousIndex - 1); + + if (colonIndex >= 0) { + dexFileFile = new File(input.substring(0, colonIndex)); + dexFileEntry = input.substring(colonIndex + 1); + previousIndex = colonIndex; + } else { + break; + } + } + + if (!dexFileFile.exists()) { + System.err.println("Can't find the file " + input); + System.exit(1); + } + + if (!dexFileFile.exists()) { + int colonIndex = input.lastIndexOf(':'); + + if (colonIndex >= 0) { + dexFileFile = new File(input.substring(0, colonIndex)); + dexFileEntry = input.substring(colonIndex + 1); + } + + if (!dexFileFile.exists()) { + System.err.println("Can't find the file " + input); + System.exit(1); + } + } + + try { + return DexFileFactory.loadDexFile(dexFileFile, dexFileEntry, apiLevel, experimentalOpcodes); + } catch (DexFileFactory.MultipleDexFilesException ex) { + System.err.println(String.format("%s is an oat file that contains multiple dex files. You must specify " + + "which one to load. E.g. To load the \"core.dex\" entry from boot.oat, you should use " + + "\"boot.oat:core.dex\"", dexFileFile)); + System.err.println("Valid entries include:"); + + for (OatFile.OatDexFile oatDexFile : ex.oatFile.getDexFiles()) { + System.err.println(oatDexFile.filename); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + // execution can never actually reach here + throw new IllegalStateException(); + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java index 26f04d6d..f0596d96 100644 --- a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java @@ -38,23 +38,20 @@ import com.beust.jcommander.validators.PositiveInteger; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.jf.dexlib2.DexFileFactory; import org.jf.dexlib2.analysis.ClassPath; import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.jf.dexlib2.dexbacked.DexBackedOdexFile; -import org.jf.dexlib2.dexbacked.OatFile; import org.jf.dexlib2.iface.DexFile; import org.jf.dexlib2.util.SyntheticAccessorResolver; import org.jf.util.jcommander.CommaColonParameterSplitter; import javax.annotation.Nonnull; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.Map; @Parameters(commandDescription = "Disassembles a dex file.") -public class DisassembleCommand implements Command { +public class DisassembleCommand extends DexInputCommand { @Nonnull private final JCommander jc; @@ -172,38 +169,16 @@ public class DisassembleCommand implements Command { return; } - String input = inputList.get(0); - File dexFileFile = new File(input); - String dexFileEntry = null; - if (!dexFileFile.exists()) { - int colonIndex = input.lastIndexOf(':'); - - if (colonIndex >= 0) { - dexFileFile = new File(input.substring(0, colonIndex)); - dexFileEntry = input.substring(colonIndex + 1); - } - - if (!dexFileFile.exists()) { - System.err.println("Can't find the file " + input); - System.exit(1); - } + if (inputList.size() > 1) { + System.err.println("Too many files specified"); + jc.usage(jc.getParsedCommand()); + return; } - //Read in and parse the dex file - DexBackedDexFile dexFile = null; - try { - dexFile = DexFileFactory.loadDexFile(dexFileFile, dexFileEntry, apiLevel, experimentalOpcodes); - } catch (DexFileFactory.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 (OatFile.OatDexFile oatDexFile : ex.oatFile.getDexFiles()) { - System.err.println(oatDexFile.filename); - } - System.exit(1); - } catch (IOException ex) { - throw new RuntimeException(ex); + String input = inputList.get(0); + DexBackedDexFile dexFile = loadDexFile(input, apiLevel, experimentalOpcodes); + if (dexFile == null) { + return; } if (dexFile.hasOdexOpcodes()) { diff --git a/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java new file mode 100644 index 00000000..90f76130 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.google.common.collect.Lists; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.util.ReferenceUtil; + +import javax.annotation.Nonnull; +import java.util.List; + +@Parameters(commandDescription = "Lists the classes in a dex file.") +public class ListClassesCommand extends DexInputCommand { + + @Nonnull private final JCommander jc; + + @Parameter(names = {"-h", "-?", "--help"}, help = true, + description = "Show usage information") + private boolean help; + + @Parameter(description = " - A dex/apk/oat/odex file. For apk or oat files that contain multiple dex " + + "files, you can specify which dex file to disassemble by appending the name of the dex file with a " + + "colon. E.g. \"something.apk:classes2.dex\"") + private List inputList = Lists.newArrayList(); + + public ListClassesCommand(@Nonnull JCommander jc) { + this.jc = jc; + } + + @Override public void run() { + if (help || inputList == null || inputList.isEmpty()) { + jc.usage(jc.getParsedCommand()); + return; + } + + if (inputList.size() > 1) { + System.err.println("Too many files specified"); + jc.usage(jc.getParsedCommand()); + return; + } + + String input = inputList.get(0); + DexBackedDexFile dexFile = loadDexFile(input, 15, false); + + for (Reference reference: dexFile.getClasses()) { + System.out.println(ReferenceUtil.getReferenceString(reference)); + } + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/ListCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListCommand.java new file mode 100644 index 00000000..427ebde2 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListCommand.java @@ -0,0 +1,72 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import javax.annotation.Nonnull; + +@Parameters(commandDescription = "Lists various objects in a dex file.") +public class ListCommand implements Command { + + @Nonnull private final JCommander jc; + @Nonnull private JCommander subJc; + + @Parameter(names = {"-h", "-?", "--help"}, help = true, + description = "Show usage information") + private boolean help; + + public ListCommand(@Nonnull JCommander jc) { + this.jc = jc; + } + + public void registerSubCommands() { + subJc = jc.getCommands().get("list"); + subJc.addCommand("strings", new ListStringsCommand(subJc), "string", "str", "s"); + subJc.addCommand("methods", new ListMethodsCommand(subJc), "method", "m"); + subJc.addCommand("fields", new ListFieldsCommand(subJc), "field", "f"); + subJc.addCommand("types", new ListTypesCommand(subJc), "type", "t"); + subJc.addCommand("classes", new ListClassesCommand(subJc), "class", "c"); + } + + @Override public void run() { + if (help || subJc.getParsedCommand() == null) { + subJc.usage(); + return; + } + + Command command = (Command)subJc.getCommands().get(subJc.getParsedCommand()).getObjects().get(0); + command.run(); + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/ListFieldsCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListFieldsCommand.java new file mode 100644 index 00000000..10924172 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListFieldsCommand.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameters; +import org.jf.dexlib2.ReferenceType; + +import javax.annotation.Nonnull; + +@Parameters(commandDescription = "Lists the fields in a dex file's field table.") +public class ListFieldsCommand extends ListReferencesCommand { + public ListFieldsCommand(@Nonnull JCommander jc) { + super(jc, ReferenceType.FIELD); + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/ListMethodsCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListMethodsCommand.java new file mode 100644 index 00000000..afb5ed65 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListMethodsCommand.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameters; +import org.jf.dexlib2.ReferenceType; + +import javax.annotation.Nonnull; + +@Parameters(commandDescription = "Lists the methods in a dex file's method table.") +public class ListMethodsCommand extends ListReferencesCommand { + public ListMethodsCommand(@Nonnull JCommander jc) { + super(jc, ReferenceType.METHOD); + } +} \ No newline at end of file diff --git a/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java new file mode 100644 index 00000000..27bab5d8 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.google.common.collect.Lists; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.util.ReferenceUtil; + +import javax.annotation.Nonnull; +import java.util.List; + +public abstract class ListReferencesCommand extends DexInputCommand { + + @Nonnull private final JCommander jc; + private final int referenceType; + + @Parameter(names = {"-h", "-?", "--help"}, help = true, + description = "Show usage information") + private boolean help; + + @Parameter(description = " - A dex/apk/oat/odex file. For apk or oat files that contain multiple dex " + + "files, you can specify which dex file to disassemble by appending the name of the dex file with a " + + "colon. E.g. \"something.apk:classes2.dex\"") + private List inputList = Lists.newArrayList(); + + public ListReferencesCommand(@Nonnull JCommander jc, int referenceType) { + this.jc = jc; + this.referenceType = referenceType; + } + + @Override public void run() { + if (help || inputList == null || inputList.isEmpty()) { + jc.usage(jc.getParsedCommand()); + return; + } + + if (inputList.size() > 1) { + System.err.println("Too many files specified"); + jc.usage(jc.getParsedCommand()); + return; + } + + String input = inputList.get(0); + DexBackedDexFile dexFile = loadDexFile(input, 15, false); + + for (Reference reference: dexFile.getReferences(referenceType)) { + System.out.println(ReferenceUtil.getReferenceString(reference)); + } + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/ListStringsCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListStringsCommand.java new file mode 100644 index 00000000..97152f31 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListStringsCommand.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameters; +import org.jf.dexlib2.ReferenceType; + +import javax.annotation.Nonnull; + +@Parameters(commandDescription = "Lists the strings in a dex file's string table.") +public class ListStringsCommand extends ListReferencesCommand { + public ListStringsCommand(@Nonnull JCommander jc) { + super(jc, ReferenceType.STRING); + } +} \ No newline at end of file diff --git a/baksmali/src/main/java/org/jf/baksmali/ListTypesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListTypesCommand.java new file mode 100644 index 00000000..cbbca32a --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/ListTypesCommand.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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 com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameters; +import org.jf.dexlib2.ReferenceType; + +import javax.annotation.Nonnull; + +@Parameters(commandDescription = "Lists the type ids in a dex file's type table.") +public class ListTypesCommand extends ListReferencesCommand { + public ListTypesCommand(@Nonnull JCommander jc) { + super(jc, ReferenceType.TYPE); + } +} diff --git a/baksmali/src/main/java/org/jf/baksmali/Main.java b/baksmali/src/main/java/org/jf/baksmali/Main.java index 39d95cac..977049d6 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Main.java +++ b/baksmali/src/main/java/org/jf/baksmali/Main.java @@ -61,6 +61,10 @@ public class Main { jc.addCommand("help", new HelpCommand(jc), "h"); jc.addCommand("hlep", new HlepCommand(jc)); + ListCommand listCommand = new ListCommand(jc); + jc.addCommand("list", listCommand, "l"); + listCommand.registerSubCommands(); + jc.parse(args); if (jc.getParsedCommand() == null || main.help) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java index 32505eec..a3f791f9 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java @@ -33,9 +33,15 @@ package org.jf.dexlib2.dexbacked; import com.google.common.io.ByteStreams; import org.jf.dexlib2.Opcodes; +import org.jf.dexlib2.ReferenceType; import org.jf.dexlib2.dexbacked.raw.*; +import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference; +import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference; +import org.jf.dexlib2.dexbacked.reference.DexBackedStringReference; +import org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference; import org.jf.dexlib2.dexbacked.util.FixedSizeSet; import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.iface.reference.Reference; import org.jf.util.ExceptionWithContext; import javax.annotation.Nonnull; @@ -43,6 +49,8 @@ import javax.annotation.Nullable; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.util.AbstractList; +import java.util.List; import java.util.Set; public class DexBackedDexFile extends BaseDexBuffer implements DexFile { @@ -265,6 +273,81 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile { return getType(typeIndex); } + public List getStrings() { + return new AbstractList() { + @Override public DexBackedStringReference get(int index) { + if (index < 0 || index >= getStringCount()) { + throw new IndexOutOfBoundsException(); + } + return new DexBackedStringReference(DexBackedDexFile.this, index); + } + + @Override public int size() { + return getStringCount(); + } + }; + } + + public List getTypes() { + return new AbstractList() { + @Override public DexBackedTypeReference get(int index) { + if (index < 0 || index >= getTypeCount()) { + throw new IndexOutOfBoundsException(); + } + return new DexBackedTypeReference(DexBackedDexFile.this, index); + } + + @Override public int size() { + return getTypeCount(); + } + }; + } + + public List getMethods() { + return new AbstractList() { + @Override public DexBackedMethodReference get(int index) { + if (index < 0 || index >= getMethodCount()) { + throw new IndexOutOfBoundsException(); + } + return new DexBackedMethodReference(DexBackedDexFile.this, index); + } + + @Override public int size() { + return getMethodCount(); + } + }; + } + + public List getFields() { + return new AbstractList() { + @Override public DexBackedFieldReference get(int index) { + if (index < 0 || index >= getFieldCount()) { + throw new IndexOutOfBoundsException(); + } + return new DexBackedFieldReference(DexBackedDexFile.this, index); + } + + @Override public int size() { + return getFieldCount(); + } + }; + } + + public List getReferences(int referenceType) { + switch (referenceType) { + case ReferenceType.STRING: + return getStrings(); + case ReferenceType.TYPE: + return getTypes(); + case ReferenceType.METHOD: + return getMethods(); + case ReferenceType.FIELD: + return getFields(); + default: + throw new IllegalArgumentException(String.format("Invalid reference type: %d", referenceType)); + } + } + @Override @Nonnull public DexReader readerAt(int offset) {