From 8e1afdda32a3c6572e44ccba9150f18627bf834d Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sun, 23 Oct 2016 22:09:52 -0700 Subject: [PATCH] Clean up how api levels are handled in various places Now that dex files store an associated Opcodes instance, we don't need to pass the api level around as much. --- .../java/org/jf/baksmali/AnalysisArguments.java | 7 +------ .../main/java/org/jf/baksmali/DexInputCommand.java | 12 ++++++++---- .../java/org/jf/baksmali/DisassembleCommand.java | 3 +-- .../src/main/java/org/jf/baksmali/DumpCommand.java | 14 +++----------- .../java/org/jf/baksmali/ListClassesCommand.java | 3 +-- .../org/jf/baksmali/ListFieldOffsetsCommand.java | 5 ++--- .../org/jf/baksmali/ListReferencesCommand.java | 3 +-- .../java/org/jf/baksmali/ListVtablesCommand.java | 5 ++--- .../main/java/org/jf/dexlib2/DexFileFactory.java | 1 - .../org/jf/dexlib2/analysis/ClassPathResolver.java | 11 +++++------ 10 files changed, 24 insertions(+), 40 deletions(-) diff --git a/baksmali/src/main/java/org/jf/baksmali/AnalysisArguments.java b/baksmali/src/main/java/org/jf/baksmali/AnalysisArguments.java index fa3bb855..20bc45be 100644 --- a/baksmali/src/main/java/org/jf/baksmali/AnalysisArguments.java +++ b/baksmali/src/main/java/org/jf/baksmali/AnalysisArguments.java @@ -49,11 +49,6 @@ import java.util.List; import static org.jf.dexlib2.analysis.ClassPath.NOT_ART; public class AnalysisArguments { - @Parameter(names = {"-a", "--api"}, - description = "The numeric api level of the file being disassembled.") - @ExtendedParameter(argumentNames = "api") - public int apiLevel = 15; - @Parameter(names = {"-b", "--bootclasspath", "--bcp"}, description = "A colon separated list of the files to include in the bootclasspath when analyzing the " + "dex file. If not specified, baksmali will attempt to choose an " + @@ -131,7 +126,7 @@ public class AnalysisArguments { if (bootClassPath == null) { // TODO: we should be able to get the api from the Opcodes object associated with the dexFile.. // except that the oat version -> api mapping doesn't fully work yet - resolver = new ClassPathResolver(filteredClassPathDirectories, classPath, dexFile, apiLevel); + resolver = new ClassPathResolver(filteredClassPathDirectories, classPath, dexFile); } else if (bootClassPath.size() == 1 && bootClassPath.get(0).length() == 0) { // --bootclasspath "" is a special case, denoting that no bootclasspath should be used resolver = new ClassPathResolver( diff --git a/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java b/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java index 7117bb25..c7660cbe 100644 --- a/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/DexInputCommand.java @@ -52,6 +52,11 @@ import java.util.List; */ public abstract class DexInputCommand extends Command { + @Parameter(names = {"-a", "--api"}, + description = "The numeric api level of the file being disassembled.") + @ExtendedParameter(argumentNames = "api") + public int apiLevel = 15; + @Parameter(description = "A dex/apk/oat/odex file. For apk or oat files that contain multiple dex " + "files, you can specify the specific entry to use as if the apk/oat file was a directory. " + "e.g. \"app.apk/classes2.dex\". For more information, see \"baksmali help input\".") @@ -100,9 +105,8 @@ public abstract class DexInputCommand extends Command { * framework/arm/framework.oat/"system/framework/framework.jar:classes2.dex" * * @param input The name of a dex, apk, odex or oat file/entry. - * @param opcodes The set of opcodes to load the dex file with. */ - protected void loadDexFile(@Nonnull String input, Opcodes opcodes) { + protected void loadDexFile(@Nonnull String input) { File file = new File(input); while (file != null && !file.exists()) { @@ -131,13 +135,13 @@ public abstract class DexInputCommand extends Command { inputEntry = dexEntry; try { - dexFile = DexFileFactory.loadDexEntry(file, dexEntry, exactMatch, opcodes); + dexFile = DexFileFactory.loadDexEntry(file, dexEntry, exactMatch, Opcodes.forApi(apiLevel)); } catch (IOException ex) { throw new RuntimeException(ex); } } else { try { - dexFile = DexFileFactory.loadDexFile(file, opcodes); + dexFile = DexFileFactory.loadDexFile(file, Opcodes.forApi(apiLevel)); } catch (IOException ex) { throw new RuntimeException(ex); } diff --git a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java index 06d7c967..2e3eb79e 100644 --- a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java @@ -38,7 +38,6 @@ import com.beust.jcommander.ParametersDelegate; import com.beust.jcommander.validators.PositiveInteger; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.util.SyntheticAccessorResolver; import org.jf.util.StringWrapper; import org.jf.util.jcommander.ExtendedParameter; @@ -155,7 +154,7 @@ public class DisassembleCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); if (showDeodexWarning() && dexFile.hasOdexOpcodes()) { StringWrapper.printWrappedString(System.err, diff --git a/baksmali/src/main/java/org/jf/baksmali/DumpCommand.java b/baksmali/src/main/java/org/jf/baksmali/DumpCommand.java index 94c7bb34..433be125 100644 --- a/baksmali/src/main/java/org/jf/baksmali/DumpCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/DumpCommand.java @@ -34,12 +34,10 @@ package org.jf.baksmali; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.jf.dexlib2.dexbacked.raw.RawDexFile; import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; import org.jf.util.ConsoleUtil; -import org.jf.util.jcommander.ExtendedParameter; import org.jf.util.jcommander.ExtendedParameters; import javax.annotation.Nonnull; @@ -56,11 +54,6 @@ public class DumpCommand extends DexInputCommand { description = "Show usage information for this command.") private boolean help; - @Parameter(names = {"-a", "--api"}, - description = "The numeric api level of the file being disassembled.") - @ExtendedParameter(argumentNames = "api") - private int apiLevel = 15; - public DumpCommand(@Nonnull List commandAncestors) { super(commandAncestors); } @@ -78,10 +71,10 @@ public class DumpCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); try { - dump(dexFile, System.out, apiLevel); + dump(dexFile, System.out); } catch (IOException ex) { System.err.println("There was an error while dumping the dex file"); ex.printStackTrace(System.err); @@ -94,11 +87,10 @@ public class DumpCommand extends DexInputCommand { * @param dexFile The dex file to dump * @param output An OutputStream to write the annotated hex dump to. The caller is responsible for closing this * when needed. - * @param apiLevel The api level to use when dumping the dex file * * @throws IOException */ - public static void dump(@Nonnull DexBackedDexFile dexFile, @Nonnull OutputStream output, int apiLevel) + public static void dump(@Nonnull DexBackedDexFile dexFile, @Nonnull OutputStream output) throws IOException { Writer writer = new BufferedWriter(new OutputStreamWriter(output)); diff --git a/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java index 6c6ca64b..fb172bdd 100644 --- a/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/ListClassesCommand.java @@ -34,7 +34,6 @@ package org.jf.baksmali; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.iface.ClassDef; import org.jf.util.jcommander.ExtendedParameters; @@ -68,7 +67,7 @@ public class ListClassesCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); for (ClassDef classDef: dexFile.getClasses()) { System.out.println(classDef.getType()); diff --git a/baksmali/src/main/java/org/jf/baksmali/ListFieldOffsetsCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListFieldOffsetsCommand.java index 68e2050b..d6dd6e2b 100644 --- a/baksmali/src/main/java/org/jf/baksmali/ListFieldOffsetsCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/ListFieldOffsetsCommand.java @@ -35,7 +35,6 @@ import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.beust.jcommander.ParametersDelegate; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.analysis.ClassProto; import org.jf.dexlib2.iface.ClassDef; import org.jf.dexlib2.iface.reference.FieldReference; @@ -76,7 +75,7 @@ public class ListFieldOffsetsCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); BaksmaliOptions options = getOptions(); try { @@ -105,7 +104,7 @@ public class ListFieldOffsetsCommand extends DexInputCommand { final BaksmaliOptions options = new BaksmaliOptions(); - options.apiLevel = analysisArguments.apiLevel; + options.apiLevel = apiLevel; try { options.classPath = analysisArguments.loadClassPathForDexFile( diff --git a/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java index 3403bbf9..da9c3e31 100644 --- a/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/ListReferencesCommand.java @@ -33,7 +33,6 @@ package org.jf.baksmali; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.iface.reference.Reference; import org.jf.dexlib2.util.ReferenceUtil; @@ -66,7 +65,7 @@ public abstract class ListReferencesCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); for (Reference reference: dexFile.getReferences(referenceType)) { System.out.println(ReferenceUtil.getReferenceString(reference)); diff --git a/baksmali/src/main/java/org/jf/baksmali/ListVtablesCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListVtablesCommand.java index ed88c123..74435b3d 100644 --- a/baksmali/src/main/java/org/jf/baksmali/ListVtablesCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/ListVtablesCommand.java @@ -37,7 +37,6 @@ import com.beust.jcommander.Parameters; import com.beust.jcommander.ParametersDelegate; import org.jf.baksmali.AnalysisArguments.CheckPackagePrivateArgument; import org.jf.dexlib2.AccessFlags; -import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.analysis.ClassProto; import org.jf.dexlib2.iface.ClassDef; import org.jf.dexlib2.iface.Method; @@ -92,7 +91,7 @@ public class ListVtablesCommand extends DexInputCommand { } String input = inputList.get(0); - loadDexFile(input, Opcodes.getDefault()); + loadDexFile(input); BaksmaliOptions options = getOptions(); if (options == null) { @@ -142,7 +141,7 @@ public class ListVtablesCommand extends DexInputCommand { final BaksmaliOptions options = new BaksmaliOptions(); - options.apiLevel = analysisArguments.apiLevel; + options.apiLevel = apiLevel; try { options.classPath = analysisArguments.loadClassPathForDexFile(inputFile.getAbsoluteFile().getParentFile(), diff --git a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java index 5a700d89..bc11f120 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java @@ -81,7 +81,6 @@ public final class DexFileFactory { throw new DexFileNotFoundException("%s does not exist", file.getName()); } - try { ZipDexContainer container = new ZipDexContainer(file, opcodes); return new DexEntryFinder(file.getPath(), container).findEntry("classes.dex", true); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPathResolver.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPathResolver.java index c9f47137..da2dbea2 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPathResolver.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPathResolver.java @@ -82,7 +82,7 @@ public class ClassPathResolver { public ClassPathResolver(@Nonnull List bootClassPathDirs, @Nonnull List bootClassPathEntries, @Nonnull List extraClassPathEntries, @Nonnull DexFile dexFile) throws IOException { - this(bootClassPathDirs, bootClassPathEntries, extraClassPathEntries, dexFile, dexFile.getOpcodes().api); + this(bootClassPathDirs, bootClassPathEntries, extraClassPathEntries, dexFile, true); } /** @@ -92,7 +92,6 @@ public class ClassPathResolver { * @param extraClassPathEntries A list of additional classpath entries to load. Can be empty. All entries must be * local paths. Device paths are not supported. * @param dexFile The dex file that the classpath will be used to analyze - * @param apiLevel The api level of the device. This is used to select an appropriate set of boot classpath entries. * @throws IOException If any IOException occurs * @throws ResolveException If any classpath entries cannot be loaded for some reason * @@ -101,19 +100,19 @@ public class ClassPathResolver { * classpath entries will be loaded */ public ClassPathResolver(@Nonnull List bootClassPathDirs, @Nonnull List extraClassPathEntries, - @Nonnull DexFile dexFile, int apiLevel) + @Nonnull DexFile dexFile) throws IOException { - this(bootClassPathDirs, null, extraClassPathEntries, dexFile, apiLevel); + this(bootClassPathDirs, null, extraClassPathEntries, dexFile, true); } private ClassPathResolver(@Nonnull List bootClassPathDirs, @Nullable List bootClassPathEntries, - @Nonnull List extraClassPathEntries, @Nonnull DexFile dexFile, int apiLevel) + @Nonnull List extraClassPathEntries, @Nonnull DexFile dexFile, boolean unused) throws IOException { this.classPathDirs = bootClassPathDirs; opcodes = dexFile.getOpcodes(); if (bootClassPathEntries == null) { - bootClassPathEntries = getDefaultBootClassPath(dexFile, apiLevel); + bootClassPathEntries = getDefaultBootClassPath(dexFile, opcodes.api); } for (String entry : bootClassPathEntries) {