From 64785d79a3e3179784a9ec046a4c8a5994f15dfd Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Mon, 13 Jul 2015 21:48:54 -0700 Subject: Add support for using an oat file as the boot class path --- .../java/org/jf/dexlib2/analysis/ClassPath.java | 57 +++++++++++++++++----- 1 file changed, 46 insertions(+), 11 deletions(-) (limited to 'dexlib2') diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java index 4185da82..2233f599 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java @@ -34,13 +34,12 @@ package org.jf.dexlib2.analysis; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import com.google.common.collect.*; import org.jf.dexlib2.DexFileFactory; import org.jf.dexlib2.DexFileFactory.DexFileNotFound; +import org.jf.dexlib2.DexFileFactory.MultipleDexFilesException; import org.jf.dexlib2.analysis.reflection.ReflectionClassDef; +import org.jf.dexlib2.dexbacked.OatFile.OatDexFile; import org.jf.dexlib2.iface.ClassDef; import org.jf.dexlib2.iface.DexFile; import org.jf.dexlib2.immutable.ImmutableDexFile; @@ -52,6 +51,7 @@ import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -189,21 +189,46 @@ public class ClassPath { int api, boolean checkPackagePrivateAccess, boolean experimental) { ArrayList dexFiles = Lists.newArrayList(); + boolean isArt = false; + + for (String classPathEntry: classPath) { + List classPathDexFiles = + loadClassPathEntry(classPathDirs, classPathEntry, api, experimental); + if (!isArt) { + for (DexFile classPathDexFile: classPathDexFiles) { + if (classPathDexFile instanceof OatDexFile) { + isArt = true; + break; + } + } + } + dexFiles.addAll(classPathDexFiles); + } + dexFiles.add(dexFile); + return new ClassPath(dexFiles, checkPackagePrivateAccess); + } + + @Nonnull + public static ClassPath fromClassPath(Iterable classPathDirs, Iterable classPath, DexFile dexFile, + int api, boolean checkPackagePrivateAccess, boolean experimental, + boolean isArt) { + ArrayList dexFiles = Lists.newArrayList(); + for (String classPathEntry: classPath) { try { - dexFiles.add(loadClassPathEntry(classPathDirs, classPathEntry, api, experimental)); + dexFiles.addAll(loadClassPathEntry(classPathDirs, classPathEntry, api, experimental)); } catch (ExceptionWithContext e){} } dexFiles.add(dexFile); - return new ClassPath(dexFiles, checkPackagePrivateAccess); + return new ClassPath(dexFiles, checkPackagePrivateAccess, isArt); } private static final Pattern dalvikCacheOdexPattern = Pattern.compile("@([^@]+)@classes.dex$"); @Nonnull - private static DexFile loadClassPathEntry(@Nonnull Iterable classPathDirs, - @Nonnull String bootClassPathEntry, int api, - boolean experimental) { + private static List loadClassPathEntry(@Nonnull Iterable classPathDirs, + @Nonnull String bootClassPathEntry, int api, + boolean experimental) { File rawEntry = new File(bootClassPathEntry); // strip off the path - we only care about the filename String entryName = rawEntry.getName(); @@ -229,7 +254,15 @@ public class ClassPath { } for (String classPathDir: classPathDirs) { - for (String ext: new String[]{"", ".odex", ".jar", ".apk", ".zip"}) { + String[] extensions; + + if (entryName.endsWith(".oat")) { + extensions = new String[] { ".oat" }; + } else { + extensions = new String[] { "", ".odex", ".jar", ".apk", ".zip" }; + } + + for (String ext: extensions) { File file = new File(classPathDir, baseEntryName + ext); if (file.exists() && file.isFile()) { @@ -238,9 +271,11 @@ public class ClassPath { "warning: cannot open %s for reading. Will continue looking.", file.getPath())); } else { try { - return DexFileFactory.loadDexFile(file, api, experimental); + return ImmutableList.of(DexFileFactory.loadDexFile(file, api, experimental)); } catch (DexFileNotFound ex) { // ignore and continue + } catch (MultipleDexFilesException ex) { + return ex.oatFile.getDexFiles(); } catch (Exception ex) { throw ExceptionWithContext.withContext(ex, "Error while reading boot class path entry \"%s\"", bootClassPathEntry); -- cgit v1.2.3