Add initial support for vdex files

This is the bare minimum to get deodexing to work with vdex files.
This commit is contained in:
Ben Gruver 2017-03-25 16:25:49 -07:00
parent bda4477bae
commit 48cde6219d
4 changed files with 120 additions and 12 deletions

View File

@ -46,3 +46,45 @@ d1537b569b6cd18297c5e02d13cdd588c4366c51 - 77
4359e61927866c254bc2d701e3ea4c48de10b79c - 84
d549c28cfbddba945cb88857bcca3dce1414fb29 - 85
952dbb19cd094b8bfb01dbb33e0878db429e499a - 86
239d6eaff0cbb5c4c0139f7053a012758799f186 - 87 - introduction of vdex files
77d9dd75d5d4a22ad1235f9a08d2cfbf2f0ae6fa - 89
af1e2990cd1406a0fb7cba1d2e208208e950e413 - 90
9fd8c60cdff7b28a89bb97fd90ae9d0f37cf8f8b - 91
6beced4c017826f7c449f12fac7fa42403657f2b - 92
58c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77 - 93
5923b5238091d9cd65f988fc059deb4fbb2e7f08 - 94
2b615ba29c4dfcf54aaf44955f2eac60f5080b2e - 95
f7aaacd97881c6924b8212c7f8fe4a4c8721ef53 - 94 (revert of 2b615ba)
0d3998b5ff619364acf47bec0b541e7a49bd6fe7 - 95 (re-commit of 2b615ba)
ac141397dc29189ad2b2df41f8d4312246beec60 - 96
1998cd02603197f2acdc0734397a6d48b2f59b80 - 97
e71b35446985835363a4508646cf7b1121bd95a3 - 98
39cee66a8ddf0254626c9591662cf87e4a1cedc4 - 99
cc99df230feb46ba717252f002d0cc2da6828421 - 100
fee255039e30c1c3dfc70c426c3d176221c3cdf9 - 99 (revert of cc99df23)
e761bccf9f0d884cc4d4ec104568cef968296492 - 100 (re-commit of cc99df23)
8d91ac31ccb92557e434d89ffade3372466e1af5 - 101
fd3161acfbe82c54ef49958f0ccc62511f224f91 - 102
a2f526f889be06f96ea59624c9dfb1223b3839f3 - 103
b048cb74b742b03eb6dd5f1d6dd49e559f730b36 - 104
12f1b99775bbf7dd82d0a897587ab6ed0e75ee22 - 105
ec7862283dd49f5a58d0ac45960ce27c2f7671b8 - 106
45aa598cd1773f5eb1705dec13bea059238e054d - 107
d16363a93053de0f32252c7897d839a46aff14ae - 108
1a20b6801f2432a42b906f0de01e7e9586526aec - 109
575d3e60c68b5cf481b615dde4a16283507b19ed - 110
85c0f2ac03417f5125bc2ff1dab8109859c67d5c - 111
5812e20ff7cbc8efa0b8d7486ada2f58840a6ad5 - 111
b7ea3799c15b0090bb690e18ac1b5b0fddbdeee8 - 112
- version bump for missing bump in commits
- 3228908337fdfe851223f8ae374538de25cb5ad1
- 5812e20ff7cbc8efa0b8d7486ada2f58840a6ad5
d776ff08e07494327716f0d2ea1a774b2ebfbca9 - 113
bfb80d25eaeb7a604d5dd25a370e3869e96a33ab - 114
1aea3510b8dd0c512cec61c91c5ef1f1e5d53d64 - 115
6374c58f2ea403b3a05fb27376110fe4d0fc8e3f - 114 (revert of 1aea3510)
0b66d6174bf1f6023f9d36dda8538490b79c2e9f - 113 (revert of bfb80d25)
8d6768d47b66a688d35399d524ad5a5450e9d9d4 - 114 (i don't even)
f44d36c8423f81cbb5e9f55d8813e26ffa1a7f3b - 115 (115 again. heck if I know what's going on)
cbcedbf9382bc773713cd3552ed96f417bf1daeb - 116
051071718085ce807a2e7c55278a8d723e238e86 - 116

8
dexlib2/VdexVersions.txt Normal file
View File

@ -0,0 +1,8 @@
7b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2 - 0 - introduction of vdex files
5d5a36bddbc008cd52a3207aa2b31177c47f9a49 - 0 - verifier deps
4acefd33064d37b41ca55c3c9355345a20e5f9c2 - 0 - quickening info
f54e5df37cb42d9a83fc54b375da5ef335d604a9 - 1 - dex file count + dex location checksum
7498105ec7497bae2ba9f1a697da9efa0c979654 - 2 - verify profile
3eba863e41d531340392d9ec64e17963ac898d81 - 3
97fa9928c07d3e0ee631235e9619fb0f8949ed7a - 4
6e54f78c7c1e01c1a91a458c6e51cca1c7d13ad4 - 5

View File

@ -34,12 +34,15 @@ package org.jf.dexlib2;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
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;
import org.jf.dexlib2.dexbacked.OatFile.OatDexFile;
import org.jf.dexlib2.dexbacked.OatFile.VdexProvider;
import org.jf.dexlib2.dexbacked.ZipDexContainer;
import org.jf.dexlib2.dexbacked.ZipDexContainer.NotAZipFileException;
import org.jf.dexlib2.iface.DexFile;
@ -107,7 +110,7 @@ public final class DexFileFactory {
OatFile oatFile = null;
try {
oatFile = OatFile.fromInputStream(inputStream);
oatFile = OatFile.fromInputStream(inputStream, new FilenameVdexProvider(file));
} catch (NotAnOatFileException ex) {
// just eat it
}
@ -189,7 +192,7 @@ public final class DexFileFactory {
try {
OatFile oatFile = null;
try {
oatFile = OatFile.fromInputStream(inputStream);
oatFile = OatFile.fromInputStream(inputStream, new FilenameVdexProvider(file));
} catch (NotAnOatFileException ex) {
// just eat it
}
@ -258,7 +261,7 @@ public final class DexFileFactory {
OatFile oatFile = null;
try {
oatFile = OatFile.fromInputStream(inputStream);
oatFile = OatFile.fromInputStream(inputStream, new FilenameVdexProvider(file));
} catch (NotAnOatFileException ex) {
// just eat it
}
@ -458,4 +461,35 @@ public final class DexFileFactory {
return dexFile.getOpcodes();
}
}
public static class FilenameVdexProvider implements VdexProvider {
private final File vdexFile;
@Nullable
private byte[] buf = null;
private boolean loadedVdex = false;
public FilenameVdexProvider(File oatFile) {
File oatParent = oatFile.getAbsoluteFile().getParentFile();
String baseName = Files.getNameWithoutExtension(oatFile.getAbsolutePath());
vdexFile = new File(oatParent, baseName + ".vdex");
}
@Nullable @Override public byte[] getVdex() {
if (!loadedVdex) {
if (vdexFile.exists()) {
try {
buf = ByteStreams.toByteArray(new FileInputStream(vdexFile));
} catch (FileNotFoundException e) {
buf = null;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
loadedVdex = true;
}
return buf;
}
}
}

View File

@ -70,8 +70,13 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
private final boolean is64bit;
@Nonnull private final OatHeader oatHeader;
@Nonnull private final Opcodes opcodes;
@Nullable private final VdexProvider vdexProvider;
public OatFile(@Nonnull byte[] buf) {
this(buf, null);
}
public OatFile(@Nonnull byte[] buf, @Nullable VdexProvider vdexProvider) {
super(buf);
if (buf.length < MIN_ELF_HEADER_SIZE) {
@ -107,6 +112,7 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
}
this.opcodes = Opcodes.forArtVersion(oatHeader.getVersion());
this.vdexProvider = vdexProvider;
}
private static void verifyMagic(byte[] buf) {
@ -117,7 +123,11 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
}
}
public static OatFile fromInputStream(@Nonnull InputStream is)
public static OatFile fromInputStream(@Nonnull InputStream is) throws IOException {
return fromInputStream(is, null);
}
public static OatFile fromInputStream(@Nonnull InputStream is, @Nullable VdexProvider vdexProvider)
throws IOException {
if (!is.markSupported()) {
throw new IllegalArgumentException("InputStream must support mark");
@ -137,7 +147,7 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
is.reset();
byte[] buf = ByteStreams.toByteArray(is);
return new OatFile(buf);
return new OatFile(buf, vdexProvider);
}
public int getOatVersion() {
@ -219,8 +229,8 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
public class OatDexFile extends DexBackedDexFile implements MultiDexContainer.MultiDexFile {
@Nonnull public final String filename;
public OatDexFile(int offset, @Nonnull String filename) {
super(opcodes, OatFile.this.buf, offset);
public OatDexFile(byte[] buf, int offset, @Nonnull String filename) {
super(opcodes, buf, offset);
this.filename = filename;
}
@ -542,15 +552,18 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
private class DexEntry {
public final String entryName;
public final byte[] buf;
public final int dexOffset;
public DexEntry(String entryName, int dexOffset) {
public DexEntry(String entryName, byte[] buf, int dexOffset) {
this.entryName = entryName;
this.buf = buf;
this.dexOffset = dexOffset;
}
public OatDexFile getDexFile() {
return new OatDexFile(dexOffset, entryName);
return new OatDexFile(buf, dexOffset, entryName);
}
}
@ -572,10 +585,9 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
offset += 4; // checksum
int dexOffset = readSmallUint(offset) + oatHeader.headerOffset;
int dexOffset = readSmallUint(offset);
offset += 4;
if (getOatVersion() >= 75) {
offset += 4; // offset to class offsets table
}
@ -590,7 +602,15 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
index++;
return new DexEntry(filename, dexOffset);
byte[] buf;
if (getOatVersion() >= 87 && vdexProvider != null && vdexProvider.getVdex() != null) {
buf = vdexProvider.getVdex();
} else {
buf = OatFile.this.buf;
offset += oatHeader.headerOffset;
}
return new DexEntry(filename, buf, dexOffset);
}
@Override public void remove() {
@ -608,4 +628,8 @@ public class OatFile extends BaseDexBuffer implements MultiDexContainer<OatDexFi
public NotAnOatFileException() {}
}
public interface VdexProvider {
@Nullable
byte[] getVdex();
}
}