diff --git a/baksmali/src/main/java/org/jf/baksmali/ListDexCommand.java b/baksmali/src/main/java/org/jf/baksmali/ListDexCommand.java index 65aa1ec8..435d554d 100644 --- a/baksmali/src/main/java/org/jf/baksmali/ListDexCommand.java +++ b/baksmali/src/main/java/org/jf/baksmali/ListDexCommand.java @@ -35,20 +35,15 @@ 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.OatFile; -import org.jf.dexlib2.dexbacked.raw.HeaderItem; -import org.jf.dexlib2.dexbacked.raw.OdexHeaderItem; +import org.jf.dexlib2.DexFileFactory; import org.jf.util.jcommander.Command; import org.jf.util.jcommander.ExtendedParameter; import org.jf.util.jcommander.ExtendedParameters; import javax.annotation.Nonnull; -import java.io.*; -import java.util.Collections; +import java.io.File; +import java.io.IOException; import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; @Parameters(commandDescription = "Lists the dex files in an apk/oat file.") @ExtendedParameters( @@ -85,53 +80,18 @@ public class ListDexCommand extends Command { if (!file.exists()) { System.err.println(String.format("Could not find the file: %s", input)); + System.exit(-1); } + List entries; try { - ZipFile zipFile = new ZipFile(input); - - byte[] magic = new byte[8]; - - for (ZipEntry zipEntry : Collections.list(zipFile.entries())) { - try { - InputStream inputStream = zipFile.getInputStream(zipEntry); - - int totalBytesRead = 0; - while (totalBytesRead < 8) { - int bytesRead = inputStream.read(magic, totalBytesRead, 8 - totalBytesRead); - if (bytesRead == -1) { - break; - } - totalBytesRead += bytesRead; - } - - if (totalBytesRead == 8) { - if (HeaderItem.verifyMagic(magic, 0) || OdexHeaderItem.verifyMagic(magic)) { - System.out.println(zipEntry.getName()); - } - } - } catch (ZipException ex) { - // ignore and keep looking - continue; - } - } - } catch (ZipException ex) { - // ignore + entries = DexFileFactory.getAllDexEntries(file); } catch (IOException ex) { throw new RuntimeException(ex); } - try { - InputStream inputStream = new BufferedInputStream(new FileInputStream(input)); - OatFile oatFile = OatFile.fromInputStream(inputStream); - - for (OatFile.OatDexFile oatDexFile: oatFile.getDexFiles()) { - System.out.println(oatDexFile.filename); - } - } catch (OatFile.NotAnOatFileException ex) { - // just eat it - } catch (IOException ex) { - throw new RuntimeException(ex); + for (String entry: entries) { + System.out.println(entry); } } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java index 4bb9f9f6..81c73102 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java @@ -35,6 +35,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.AbstractIterator; import com.google.common.collect.Lists; import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexBackedDexFile.NotADexFile; import org.jf.dexlib2.dexbacked.DexBackedOdexFile; import org.jf.dexlib2.dexbacked.OatFile; import org.jf.dexlib2.dexbacked.OatFile.NotAnOatFileException; @@ -249,10 +250,10 @@ public final class DexFileFactory { * * @param file The file to open * @param opcodes The set of opcodes to use - * @return A DexBackedDexFile for the given file + * @return An iterable of DexBackedDexFiles * @throws IOException * @throws DexFileNotFoundException If the given file does not exist - * @throws UnsupportedFileTypeException If the given file is not a dex, odex, zip or oat file + * @throws UnsupportedFileTypeException If the given file is not a zip or oat file */ public static Iterable loadAllDexFiles( @Nonnull File file, @Nonnull final Opcodes opcodes) throws IOException { @@ -284,6 +285,8 @@ public final class DexFileFactory { } catch (IOException ex) { throw new ExceptionWithContext(ex, "Error while reading %s from %s", zipEntry.getName(), finalZipFile.getName()); + } catch (NotADexFile ex) { + // ignore and continue } } } @@ -331,7 +334,80 @@ public final class DexFileFactory { } throw new UnsupportedFileTypeException("%s is not an apk, dex, odex or oat file.", file.getPath()); + } + /** + * Gets all dex entries from an oat/zip file. + * + * For zip files, only entries that match classes[0-9]*.dex will be returned. + * + * @param file The file to get dex entries from + + * @return A list of strings contains the dex entry names + * @throws IOException + * @throws DexFileNotFoundException If the given file does not exist + * @throws UnsupportedFileTypeException If the given file is not a zip or oat file + */ + public static List getAllDexEntries(@Nonnull File file) throws IOException { + if (!file.exists()) { + throw new DexFileNotFoundException("%s does not exist", file.getName()); + } + + List entries = Lists.newArrayList(); + Opcodes opcodes = Opcodes.forApi(15); + + ZipFile zipFile = null; + try { + zipFile = new ZipFile(file); + } catch (IOException ex) { + // ignore and continue + } + + if (zipFile != null) { + Pattern dexPattern = Pattern.compile("classes[0-9]*.dex"); + Enumeration zipEntries = zipFile.entries(); + + while (zipEntries.hasMoreElements()) { + ZipEntry zipEntry = zipEntries.nextElement(); + if (dexPattern.matcher(zipEntry.getName()).matches()) { + try { + loadDexFromZip(zipFile, zipEntry, opcodes); + entries.add(zipEntry.getName()); + } catch (IOException ex) { + throw new IOException(String.format("Error while reading %s from %s", + zipEntry.getName(), zipFile.getName()), ex); + }catch (NotADexFile ex) { + // ignore and continue + } + } + } + return entries; + } + + InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); + try { + OatFile oatFile = null; + try { + oatFile = OatFile.fromInputStream(inputStream); + } catch (NotAnOatFileException ex) { + // just eat it + } + + if (oatFile != null) { + if (oatFile.isSupportedVersion() == OatFile.UNSUPPORTED) { + throw new UnsupportedOatVersionException(oatFile); + } + + for (OatDexFile oatDexFile: oatFile.getDexFiles()) { + entries.add(oatDexFile.filename); + } + return entries; + } + } finally { + inputStream.close(); + } + + throw new UnsupportedFileTypeException("%s is not an apk, oat file.", file.getPath()); } /**