aboutsummaryrefslogtreecommitdiff
path: root/dexlib2/src
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2015-02-18 17:38:30 -0800
committerIgor Murashkin <iam@google.com>2015-03-16 11:40:58 -0700
commit144951a9e9e6c87866245f2bdeebf0ebedaa0e38 (patch)
treebdbc5c4f2ad3ea320798ade74888490123c30ad5 /dexlib2/src
parentf70084bdfeba10dfb68c2c63eb1bedd4e42b4b0f (diff)
downloadsmali-144951a9e9e6c87866245f2bdeebf0ebedaa0e38.tar.gz
Add lambda experimental dalvik opcodes
* Add new -X/--experimental flag to [dis]assemble opcodes not in art yet * Add new opcodes liberate-variable, box-lambda, unbox-lambda, capture-variable, create-lambda, invoke-lambda * Add support for encoding 25x instructions * Adds LambdaTest to check new opcodes assemble/disassemble properly TODO: invoke-lambda-range Change-Id: I5c8bcbfa8b6cb9a13ef2017fce2d1b7fda6e11c3
Diffstat (limited to 'dexlib2/src')
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java18
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/Format.java1
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/Opcode.java32
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java5
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java13
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java14
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java14
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java78
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java82
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java2
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java83
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java27
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java47
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java37
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java2
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java97
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java9
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java3
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java13
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/AccessorTest.java2
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java6
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/writer/DexWriterTest.java2
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/writer/JumboStringConversionTest.java4
23 files changed, 528 insertions, 63 deletions
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
index d08da036..85f8a426 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java
@@ -45,22 +45,26 @@ import java.util.zip.ZipFile;
public final class DexFileFactory {
@Nonnull
- public static DexBackedDexFile loadDexFile(String path, int api) throws IOException {
- return loadDexFile(new File(path), "classes.dex", new Opcodes(api));
+ public static DexBackedDexFile loadDexFile(String path, int api, boolean experimental)
+ throws IOException {
+ return loadDexFile(new File(path), "classes.dex", new Opcodes(api, experimental));
}
@Nonnull
- public static DexBackedDexFile loadDexFile(File dexFile, int api) throws IOException {
- return loadDexFile(dexFile, "classes.dex", new Opcodes(api));
+ public static DexBackedDexFile loadDexFile(File dexFile, int api, boolean experimental)
+ throws IOException {
+ return loadDexFile(dexFile, "classes.dex", new Opcodes(api, experimental));
}
@Nonnull
- public static DexBackedDexFile loadDexFile(File dexFile, String dexEntry, int api) throws IOException {
- return loadDexFile(dexFile, dexEntry, new Opcodes(api));
+ public static DexBackedDexFile loadDexFile(File dexFile, String dexEntry, int api,
+ boolean experimental) throws IOException {
+ return loadDexFile(dexFile, dexEntry, new Opcodes(api, experimental));
}
@Nonnull
- public static DexBackedDexFile loadDexFile(File dexFile, String dexEntry, @Nonnull Opcodes opcodes) throws IOException {
+ public static DexBackedDexFile loadDexFile(File dexFile, String dexEntry,
+ @Nonnull Opcodes opcodes) throws IOException {
ZipFile zipFile = null;
boolean isZipFile = false;
try {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Format.java b/dexlib2/src/main/java/org/jf/dexlib2/Format.java
index d91b7432..ee34aa50 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/Format.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/Format.java
@@ -51,6 +51,7 @@ public enum Format {
Format22t(4),
Format22x(4),
Format23x(4),
+ Format25x(4),
Format30t(6),
Format31c(6),
Format31i(6),
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java
index d0adee8c..3b082ee8 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java
@@ -269,13 +269,13 @@ public enum Opcode
INVOKE_OBJECT_INIT_RANGE((short)0xf0, "invoke-object-init/range", minApi(14), ReferenceType.METHOD, Format.Format3rc, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE),
RETURN_VOID_BARRIER((short)0xf1, "return-void-barrier", minApi(11), ReferenceType.NONE, Format.Format10x, Opcode.ODEX_ONLY),
IGET_QUICK((short)0xf2, "iget-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
- IGET_WIDE_QUICK((short)0xf3, "iget-wide-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
- IGET_OBJECT_QUICK((short)0xf4, "iget-object-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
- IPUT_QUICK((short)0xf5, "iput-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
- IPUT_WIDE_QUICK((short)0xf6, "iput-wide-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
- IPUT_OBJECT_QUICK((short)0xf7, "iput-object-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
- INVOKE_VIRTUAL_QUICK((short)0xf8, "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
- INVOKE_VIRTUAL_QUICK_RANGE((short)0xf9, "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
+ IGET_WIDE_QUICK((short)0xf3, "iget-wide-quick", maxApi(22), ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
+ IGET_OBJECT_QUICK((short)0xf4, "iget-object-quick", maxApi(22), ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
+ IPUT_QUICK((short)0xf5, "iput-quick", maxApi(22), ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
+ IPUT_WIDE_QUICK((short)0xf6, "iput-wide-quick", maxApi(22), ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
+ IPUT_OBJECT_QUICK((short)0xf7, "iput-object-quick", maxApi(22), ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
+ INVOKE_VIRTUAL_QUICK((short)0xf8, "invoke-virtual-quick", maxApi(22), ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
+ INVOKE_VIRTUAL_QUICK_RANGE((short)0xf9, "invoke-virtual-quick/range", maxApi(22), ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_SUPER_QUICK((short)0xfa, "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_SUPER_QUICK_RANGE((short)0xfb, "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
@@ -285,7 +285,17 @@ public enum Opcode
PACKED_SWITCH_PAYLOAD((short)0x100, "packed-switch-payload", ReferenceType.NONE, Format.PackedSwitchPayload, 0),
SPARSE_SWITCH_PAYLOAD((short)0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0),
- ARRAY_PAYLOAD((short)0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0);
+ ARRAY_PAYLOAD((short)0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0),
+
+ // Reuse the deprecated f3-ff opcodes in Art:
+ INVOKE_LAMBDA((short)0xf3, "invoke-lambda", minApi(23), ReferenceType.NONE, Format.Format25x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.EXPERIMENTAL),
+ // TODO: What about JUMBO support if the string ID is too large?
+ CAPTURE_VARIABLE((short)0xf5, "capture-variable", minApi(23), ReferenceType.STRING, Format.Format21c, Opcode.EXPERIMENTAL),
+ CREATE_LAMBDA((short)0xf6, "create-lambda", minApi(23), ReferenceType.METHOD, Format.Format21c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
+ // TODO: do we need a capture/liberate wide?
+ LIBERATE_VARIABLE((short)0xf7, "liberate-variable", minApi(23), ReferenceType.STRING, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
+ BOX_LAMBDA((short)0xf8, "box-lambda", minApi(23), ReferenceType.NONE, Format.Format22x, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
+ UNBOX_LAMBDA((short)0xf9, "unbox-lambda", minApi(23), ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL);
//if the instruction can throw an exception
public static final int CAN_THROW = 0x1;
@@ -309,6 +319,8 @@ public enum Opcode
public static final int JUMBO_OPCODE = 0x200;
//if the instruction can initialize an uninitialized object reference
public static final int CAN_INITIALIZE_REFERENCE = 0x400;
+ //if the instruction is experimental (not potentially supported by Android runtime yet)
+ public static final int EXPERIMENTAL = 0x800;
private static final int ALL_APIS = 0xFFFF0000;
@@ -417,4 +429,8 @@ public enum Opcode
public final boolean canInitializeReference() {
return (flags & CAN_INITIALIZE_REFERENCE) != 0;
}
+
+ public final boolean isExperimental() {
+ return (flags & EXPERIMENTAL) != 0;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
index d6e5532e..dd876813 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java
@@ -40,13 +40,14 @@ public class Opcodes {
private final Opcode[] opcodesByValue;
private final HashMap<String, Opcode> opcodesByName;
- public Opcodes(int api) {
+ public Opcodes(int api, boolean experimental) {
opcodesByValue = new Opcode[256];
opcodesByName = Maps.newHashMap();
for (Opcode opcode: Opcode.values()) {
if (!opcode.format.isPayloadFormat) {
- if (api <= opcode.getMaxApi() && api >= opcode.getMinApi()) {
+ if (api <= opcode.getMaxApi() && api >= opcode.getMinApi() &&
+ (experimental || !opcode.isExperimental())) {
opcodesByValue[opcode.value] = opcode;
opcodesByName.put(opcode.name.toLowerCase(), opcode);
}
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 7efeb408..bd9cfb1b 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java
@@ -164,18 +164,18 @@ public class ClassPath {
@Nonnull
public static ClassPath fromClassPath(Iterable<String> classPathDirs, Iterable<String> classPath, DexFile dexFile,
- int api) {
- return fromClassPath(classPathDirs, classPath, dexFile, api, api == 17);
+ int api, boolean experimental) {
+ return fromClassPath(classPathDirs, classPath, dexFile, api, api == 17, experimental);
}
@Nonnull
public static ClassPath fromClassPath(Iterable<String> classPathDirs, Iterable<String> classPath, DexFile dexFile,
- int api, boolean checkPackagePrivateAccess) {
+ int api, boolean checkPackagePrivateAccess, boolean experimental) {
ArrayList<DexFile> dexFiles = Lists.newArrayList();
for (String classPathEntry: classPath) {
try {
- dexFiles.add(loadClassPathEntry(classPathDirs, classPathEntry, api));
+ dexFiles.add(loadClassPathEntry(classPathDirs, classPathEntry, api, experimental));
} catch (ExceptionWithContext e){}
}
dexFiles.add(dexFile);
@@ -186,7 +186,8 @@ public class ClassPath {
@Nonnull
private static DexFile loadClassPathEntry(@Nonnull Iterable<String> classPathDirs,
- @Nonnull String bootClassPathEntry, int api) {
+ @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();
@@ -221,7 +222,7 @@ public class ClassPath {
"warning: cannot open %s for reading. Will continue looking.", file.getPath()));
} else {
try {
- return DexFileFactory.loadDexFile(file, api);
+ return DexFileFactory.loadDexFile(file, api, experimental);
} catch (DexFileFactory.NoClassesDexException ex) {
// ignore and continue
} catch (Exception ex) {
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java
index d57ce961..2bb3e492 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java
@@ -73,6 +73,7 @@ public class DumpFields {
ArrayList<String> bootClassPathDirs = Lists.newArrayList();
String outFile = "fields.txt";
int apiLevel = 15;
+ boolean experimental = false;
for (int i=0; i<parsedOptions.length; i++) {
Option option = parsedOptions[i];
@@ -88,6 +89,9 @@ public class DumpFields {
case 'a':
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
break;
+ case 'X':
+ experimental = true;
+ break;
default:
assert false;
}
@@ -107,9 +111,9 @@ public class DumpFields {
}
try {
- DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel);
+ DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel, experimental);
Iterable<String> bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar");
- ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel);
+ ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel, experimental);
FileOutputStream outStream = new FileOutputStream(outFile);
for (ClassDef classDef: dexFile.getClasses()) {
@@ -163,8 +167,14 @@ public class DumpFields {
.withArgName("API_LEVEL")
.create("a");
+ Option experimentalOption = OptionBuilder.withLongOpt("experimental")
+ .withDescription("Enable dumping experimental opcodes, that aren't necessarily " +
+ "supported by the android runtime yet.")
+ .create("X");
+
options.addOption(classPathDirOption);
options.addOption(outputFileOption);
options.addOption(apiLevelOption);
+ options.addOption(experimentalOption);
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java
index 0d7656c3..193c0d39 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java
@@ -71,6 +71,7 @@ public class DumpVtables {
ArrayList<String> bootClassPathDirs = Lists.newArrayList();
String outFile = "vtables.txt";
int apiLevel = 15;
+ boolean experimental = false;
for (int i=0; i<parsedOptions.length; i++) {
Option option = parsedOptions[i];
@@ -86,6 +87,9 @@ public class DumpVtables {
case 'a':
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
break;
+ case 'X':
+ experimental = true;
+ break;
default:
assert false;
}
@@ -105,9 +109,9 @@ public class DumpVtables {
}
try {
- DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel);
+ DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel, experimental);
Iterable<String> bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar");
- ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel);
+ ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel, experimental);
FileOutputStream outStream = new FileOutputStream(outFile);
for (ClassDef classDef: dexFile.getClasses()) {
@@ -167,8 +171,14 @@ public class DumpVtables {
.withArgName("API_LEVEL")
.create("a");
+ Option experimentalOption = OptionBuilder.withLongOpt("experimental")
+ .withDescription("Enable dumping experimental opcodes, that aren't necessarily " +
+ "supported by the android runtime yet.")
+ .create("X");
+
options.addOption(classPathDirOption);
options.addOption(outputFileOption);
options.addOption(apiLevelOption);
+ options.addOption(experimentalOption);
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java
index f734e018..84981221 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java
@@ -511,82 +511,90 @@ public class MutableMethodImplementation implements MethodImplementation {
@Nonnull Instruction instruction) {
switch (instruction.getOpcode().format) {
case Format10t:
- setInstruction(location, newBuilderInstruction10t(location.codeAddress, codeAddressToIndex,
- (Instruction10t)instruction));
+ setInstruction(location, newBuilderInstruction10t(location.codeAddress,
+ codeAddressToIndex,
+ (Instruction10t) instruction));
return;
case Format10x:
- setInstruction(location, newBuilderInstruction10x((Instruction10x)instruction));
+ setInstruction(location, newBuilderInstruction10x((Instruction10x) instruction));
return;
case Format11n:
- setInstruction(location, newBuilderInstruction11n((Instruction11n)instruction));
+ setInstruction(location, newBuilderInstruction11n((Instruction11n) instruction));
return;
case Format11x:
- setInstruction(location, newBuilderInstruction11x((Instruction11x)instruction));
+ setInstruction(location, newBuilderInstruction11x((Instruction11x) instruction));
return;
case Format12x:
- setInstruction(location, newBuilderInstruction12x((Instruction12x)instruction));
+ setInstruction(location, newBuilderInstruction12x((Instruction12x) instruction));
return;
case Format20bc:
- setInstruction(location, newBuilderInstruction20bc((Instruction20bc)instruction));
+ setInstruction(location, newBuilderInstruction20bc((Instruction20bc) instruction));
return;
case Format20t:
- setInstruction(location, newBuilderInstruction20t(location.codeAddress, codeAddressToIndex,
- (Instruction20t)instruction));
+ setInstruction(location, newBuilderInstruction20t(location.codeAddress,
+ codeAddressToIndex,
+ (Instruction20t) instruction));
return;
case Format21c:
- setInstruction(location, newBuilderInstruction21c((Instruction21c)instruction));
+ setInstruction(location, newBuilderInstruction21c((Instruction21c) instruction));
return;
case Format21ih:
- setInstruction(location, newBuilderInstruction21ih((Instruction21ih)instruction));
+ setInstruction(location, newBuilderInstruction21ih((Instruction21ih) instruction));
return;
case Format21lh:
- setInstruction(location, newBuilderInstruction21lh((Instruction21lh)instruction));
+ setInstruction(location, newBuilderInstruction21lh((Instruction21lh) instruction));
return;
case Format21s:
- setInstruction(location, newBuilderInstruction21s((Instruction21s)instruction));
+ setInstruction(location, newBuilderInstruction21s((Instruction21s) instruction));
return;
case Format21t:
- setInstruction(location, newBuilderInstruction21t(location.codeAddress, codeAddressToIndex,
- (Instruction21t)instruction));
+ setInstruction(location, newBuilderInstruction21t(location.codeAddress,
+ codeAddressToIndex,
+ (Instruction21t) instruction));
return;
case Format22b:
- setInstruction(location, newBuilderInstruction22b((Instruction22b)instruction));
+ setInstruction(location, newBuilderInstruction22b((Instruction22b) instruction));
return;
case Format22c:
- setInstruction(location, newBuilderInstruction22c((Instruction22c)instruction));
+ setInstruction(location, newBuilderInstruction22c((Instruction22c) instruction));
return;
case Format22s:
- setInstruction(location, newBuilderInstruction22s((Instruction22s)instruction));
+ setInstruction(location, newBuilderInstruction22s((Instruction22s) instruction));
return;
case Format22t:
- setInstruction(location, newBuilderInstruction22t(location.codeAddress, codeAddressToIndex,
- (Instruction22t)instruction));
+ setInstruction(location, newBuilderInstruction22t(location.codeAddress,
+ codeAddressToIndex,
+ (Instruction22t) instruction));
return;
case Format22x:
- setInstruction(location, newBuilderInstruction22x((Instruction22x)instruction));
+ setInstruction(location, newBuilderInstruction22x((Instruction22x) instruction));
return;
case Format23x:
- setInstruction(location, newBuilderInstruction23x((Instruction23x)instruction));
+ setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction));
+ return;
+ case Format25x:
+ setInstruction(location, newBuilderInstruction25x((Instruction25x) instruction));
return;
case Format30t:
- setInstruction(location, newBuilderInstruction30t(location.codeAddress, codeAddressToIndex,
- (Instruction30t)instruction));
+ setInstruction(location, newBuilderInstruction30t(location.codeAddress,
+ codeAddressToIndex,
+ (Instruction30t) instruction));
return;
case Format31c:
- setInstruction(location, newBuilderInstruction31c((Instruction31c)instruction));
+ setInstruction(location, newBuilderInstruction31c((Instruction31c) instruction));
return;
case Format31i:
- setInstruction(location, newBuilderInstruction31i((Instruction31i)instruction));
+ setInstruction(location, newBuilderInstruction31i((Instruction31i) instruction));
return;
case Format31t:
setInstruction(location, newBuilderInstruction31t(location, codeAddressToIndex,
- (Instruction31t)instruction));
+ (Instruction31t) instruction));
return;
case Format32x:
- setInstruction(location, newBuilderInstruction32x((Instruction32x)instruction));
+ setInstruction(location, newBuilderInstruction32x((Instruction32x) instruction));
return;
case Format35c:
- setInstruction(location, newBuilderInstruction35c((Instruction35c)instruction));
+ setInstruction(location, newBuilderInstruction35c((Instruction35c) instruction));
return;
case Format3rc:
setInstruction(location, newBuilderInstruction3rc((Instruction3rc)instruction));
@@ -821,6 +829,18 @@ public class MutableMethodImplementation implements MethodImplementation {
}
@Nonnull
+ private BuilderInstruction25x newBuilderInstruction25x(@Nonnull Instruction25x instruction) {
+ return new BuilderInstruction25x(
+ instruction.getOpcode(),
+ instruction.getParameterRegisterCount(),
+ instruction.getRegisterFixedC(),
+ instruction.getRegisterParameterD(),
+ instruction.getRegisterParameterE(),
+ instruction.getRegisterParameterF(),
+ instruction.getRegisterParameterG());
+ }
+
+ @Nonnull
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
return new BuilderInstruction3rc(
instruction.getOpcode(),
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java
new file mode 100644
index 00000000..3783d2b6
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2015, 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.dexlib2.builder.instruction;
+
+import org.jf.dexlib2.Format;
+import org.jf.dexlib2.Opcode;
+import org.jf.dexlib2.builder.BuilderInstruction;
+import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction25x extends BuilderInstruction implements Instruction25x {
+ public static final Format FORMAT = Format.Format25x;
+
+ protected final int parameterRegisterCount;
+ protected final int registerClosure;
+ protected final int registerD;
+ protected final int registerE;
+ protected final int registerF;
+ protected final int registerG;
+
+ public BuilderInstruction25x(@Nonnull Opcode opcode,
+ int parameterRegisterCount,
+ int registerClosure,
+ int registerD,
+ int registerE,
+ int registerF,
+ int registerG) {
+ super(opcode);
+ this.parameterRegisterCount =
+ Preconditions.check25xParameterRegisterCount(parameterRegisterCount);
+ this.registerClosure = Preconditions.checkNibbleRegister(registerClosure); //at least 1 reg
+ this.registerD = (parameterRegisterCount>0) ?
+ Preconditions.checkNibbleRegister(registerD) : 0;
+ this.registerE = (parameterRegisterCount>1) ?
+ Preconditions.checkNibbleRegister(registerE) : 0;
+ this.registerF = (parameterRegisterCount>2) ?
+ Preconditions.checkNibbleRegister(registerF) : 0;
+ this.registerG = (parameterRegisterCount>3) ?
+ Preconditions.checkNibbleRegister(registerG) : 0;
+ }
+
+ @Override public int getRegisterCount() { return parameterRegisterCount + 1; }
+ @Override public int getParameterRegisterCount() { return parameterRegisterCount; }
+ @Override public int getRegisterFixedC() { return registerClosure; }
+ @Override public int getRegisterParameterD() { return registerD; }
+ @Override public int getRegisterParameterE() { return registerE; }
+ @Override public int getRegisterParameterF() { return registerF; }
+ @Override public int getRegisterParameterG() { return registerG; }
+
+ @Override public Format getFormat() { return FORMAT; }
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java
index a4c29990..ac82f4b4 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java
@@ -115,6 +115,8 @@ public abstract class DexBackedInstruction implements Instruction {
return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
case Format23x:
return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
+ case Format25x:
+ return new DexBackedInstruction25x(dexFile, opcode, instructionStartOffset);
case Format30t:
return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
case Format31c:
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java
new file mode 100644
index 00000000..80fb8767
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015, 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.dexlib2.dexbacked.instruction;
+
+import org.jf.dexlib2.Opcode;
+import org.jf.dexlib2.dexbacked.DexBackedDexFile;
+import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
+import org.jf.util.NibbleUtils;
+
+import javax.annotation.Nonnull;
+
+public class DexBackedInstruction25x extends DexBackedInstruction implements Instruction25x {
+ public DexBackedInstruction25x(@Nonnull DexBackedDexFile dexFile,
+ @Nonnull Opcode opcode,
+ int instructionStart) {
+ super(dexFile, opcode, instructionStart);
+ }
+
+ @Override
+ public int getRegisterCount() {
+ return getParameterRegisterCount() + 1;
+ }
+
+ @Override
+ public int getParameterRegisterCount() {
+ return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
+ }
+
+ @Override
+ public int getRegisterFixedC() {
+ return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
+ }
+
+ @Override
+ public int getRegisterParameterD() {
+ return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
+ }
+
+ @Override
+ public int getRegisterParameterE() {
+ return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
+ }
+
+ @Override
+ public int getRegisterParameterF() {
+ return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
+ }
+
+ @Override
+ public int getRegisterParameterG() {
+ return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
+ }
+
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
index c3946976..9c79e270 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java
@@ -129,6 +129,9 @@ public class CodeItem {
case Format10x:
annotateInstruction10x(out, instruction);
break;
+ case Format25x:
+ annotateInstruction25x(out, (Instruction25x) instruction);
+ break;
case Format35c:
annotateInstruction35c(out, (Instruction35c)instruction);
break;
@@ -282,6 +285,30 @@ public class CodeItem {
instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
}
+ private void annotateInstruction25x(@Nonnull AnnotatedBytes out,
+ @Nonnull Instruction25x instruction) {
+ List<String> args = Lists.newArrayList();
+
+ int registerCount = instruction.getRegisterCount(); //at least 1.
+ if (registerCount == 2) {
+ args.add(formatRegister(instruction.getRegisterParameterD()));
+ } else if (registerCount == 3) {
+ args.add(formatRegister(instruction.getRegisterParameterD()));
+ args.add(formatRegister(instruction.getRegisterParameterE()));
+ } else if (registerCount == 4) {
+ args.add(formatRegister(instruction.getRegisterParameterD()));
+ args.add(formatRegister(instruction.getRegisterParameterE()));
+ args.add(formatRegister(instruction.getRegisterParameterF()));
+ } else if (registerCount == 5) {
+ args.add(formatRegister(instruction.getRegisterParameterD()));
+ args.add(formatRegister(instruction.getRegisterParameterE()));
+ args.add(formatRegister(instruction.getRegisterParameterF()));
+ args.add(formatRegister(instruction.getRegisterParameterG()));
+ }
+ out.annotate(6, String.format("%s %s, {%s}",
+ instruction.getOpcode().name, instruction.getRegisterFixedC(), Joiner.on(", ").join(args)));
+ }
+
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
int startRegister = instruction.getStartRegister();
int endRegister = startRegister + instruction.getRegisterCount() - 1;
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java
new file mode 100644
index 00000000..c03bff77
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015, 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.dexlib2.iface.instruction;
+
+public interface OneFixedFourParameterRegisterInstruction extends VariableRegisterInstruction {
+ int getRegisterFixedC();
+ int getRegisterParameterD();
+ int getRegisterParameterE();
+ int getRegisterParameterF();
+ int getRegisterParameterG();
+
+ /** Returns the count of just the parameter register counts; in range of [0, 4] */
+ int getParameterRegisterCount();
+
+ /** Includes the total sum of both fixed and parameter register counts; at least 1 */
+ @Override
+ int getRegisterCount();
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java
new file mode 100644
index 00000000..51df2dee
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015, 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.dexlib2.iface.instruction.formats;
+
+import org.jf.dexlib2.iface.instruction.OneFixedFourParameterRegisterInstruction;
+
+public interface Instruction25x extends OneFixedFourParameterRegisterInstruction {
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java
index 432f1930..ed50ef5b 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java
@@ -97,6 +97,8 @@ public abstract class ImmutableInstruction implements Instruction {
return ImmutableInstruction22x.of((Instruction22x)instruction);
case Format23x:
return ImmutableInstruction23x.of((Instruction23x)instruction);
+ case Format25x:
+ return ImmutableInstruction25x.of((Instruction25x) instruction);
case Format30t:
return ImmutableInstruction30t.of((Instruction30t)instruction);
case Format31c:
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java
new file mode 100644
index 00000000..2f31eaea
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015, 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.dexlib2.immutable.instruction;
+
+import org.jf.dexlib2.Format;
+import org.jf.dexlib2.Opcode;
+import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class ImmutableInstruction25x extends ImmutableInstruction implements Instruction25x {
+ public static final Format FORMAT = Format.Format25x;
+
+ protected final int parameterRegisterCount;
+ protected final int registerClosure;
+ protected final int registerD;
+ protected final int registerE;
+ protected final int registerF;
+ protected final int registerG;
+
+ public ImmutableInstruction25x(@Nonnull Opcode opcode,
+ int parameterRegisterCount,
+ int registerClosure,
+ int registerD,
+ int registerE,
+ int registerF,
+ int registerG) {
+ super(opcode);
+ this.parameterRegisterCount =
+ Preconditions.check25xParameterRegisterCount(parameterRegisterCount);
+ this.registerClosure = Preconditions.checkNibbleRegister(registerClosure);
+ this.registerD = (parameterRegisterCount>0) ?
+ Preconditions.checkNibbleRegister(registerD) : 0;
+ this.registerE = (parameterRegisterCount>1) ?
+ Preconditions.checkNibbleRegister(registerE) : 0;
+ this.registerF = (parameterRegisterCount>2) ?
+ Preconditions.checkNibbleRegister(registerF) : 0;
+ this.registerG = (parameterRegisterCount>3) ?
+ Preconditions.checkNibbleRegister(registerG) : 0;
+ }
+
+ public static ImmutableInstruction25x of(Instruction25x instruction) {
+ if (instruction instanceof ImmutableInstruction25x) {
+ return (ImmutableInstruction25x)instruction;
+ }
+ return new ImmutableInstruction25x(
+ instruction.getOpcode(),
+ instruction.getRegisterCount(),
+ instruction.getRegisterFixedC(),
+ instruction.getRegisterParameterD(),
+ instruction.getRegisterParameterE(),
+ instruction.getRegisterParameterF(),
+ instruction.getRegisterParameterG());
+ }
+
+
+ @Override public int getParameterRegisterCount() { return parameterRegisterCount; }
+ @Override public int getRegisterCount() { return parameterRegisterCount + 1; }
+
+ @Override public int getRegisterFixedC() { return registerClosure; }
+ @Override public int getRegisterParameterD() { return registerD; }
+ @Override public int getRegisterParameterE() { return registerE; }
+ @Override public int getRegisterParameterF() { return registerF; }
+ @Override public int getRegisterParameterG() { return registerG; }
+
+ @Override public Format getFormat() { return FORMAT; }
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java
index ab86b652..51c083ca 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java
@@ -133,6 +133,15 @@ public class Preconditions {
return registerCount;
}
+ public static int check25xParameterRegisterCount(int registerCount) {
+ if (registerCount < 0 || registerCount > 4) {
+ throw new IllegalArgumentException(
+ String.format("Invalid parameter register count: %d. " +
+ "Must be between 0 and 4, inclusive.", registerCount));
+ }
+ return registerCount;
+ }
+
public static int checkRegisterRangeCount(int registerCount) {
if ((registerCount & 0xFFFFFF00) != 0) {
throw new IllegalArgumentException(
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
index 268df9b1..dd6ec9f1 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
@@ -976,6 +976,9 @@ public abstract class DexWriter<
case Format23x:
instructionWriter.write((Instruction23x)instruction);
break;
+ case Format25x:
+ instructionWriter.write((Instruction25x)instruction);
+ break;
case Format30t:
instructionWriter.write((Instruction30t)instruction);
break;
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java
index 17d31337..23a77759 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java
@@ -317,6 +317,19 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
}
}
+ public void write(@Nonnull Instruction25x instruction) {
+ try {
+ writer.write(instruction.getOpcode().value);
+ writer.write(packNibbles(
+ instruction.getRegisterParameterG(), instruction.getParameterRegisterCount()));
+ writer.write(packNibbles(
+ instruction.getRegisterFixedC(), instruction.getRegisterParameterD()));
+ writer.write(packNibbles(
+ instruction.getRegisterParameterE(), instruction.getRegisterParameterF()));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
public void write(@Nonnull Instruction3rc instruction) {
try {
writer.write(instruction.getOpcode().value);
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/AccessorTest.java b/dexlib2/src/test/java/org/jf/dexlib2/AccessorTest.java
index 13e7b30f..924d3fd3 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/AccessorTest.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/AccessorTest.java
@@ -79,7 +79,7 @@ public class AccessorTest {
public void testAccessors() throws IOException {
URL url = AccessorTest.class.getClassLoader().getResource("accessorTest.dex");
Assert.assertNotNull(url);
- DexFile f = DexFileFactory.loadDexFile(url.getFile(), 15);
+ DexFile f = DexFileFactory.loadDexFile(url.getFile(), 15, false);
SyntheticAccessorResolver sar = new SyntheticAccessorResolver(f.getClasses());
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java b/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java
index 686b2101..65a82f05 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java
@@ -69,7 +69,7 @@ public class CustomMethodInlineTableTest {
DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef));
ClassPath classPath = ClassPath.fromClassPath(ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile,
- 15);
+ 15, false);
InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver);
@@ -96,7 +96,7 @@ public class CustomMethodInlineTableTest {
DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef));
ClassPath classPath = ClassPath.fromClassPath(ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile,
- 15);
+ 15, false);
InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver);
@@ -123,7 +123,7 @@ public class CustomMethodInlineTableTest {
DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef));
ClassPath classPath = ClassPath.fromClassPath(ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile,
- 15);
+ 15, false);
InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver);
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/writer/DexWriterTest.java b/dexlib2/src/test/java/org/jf/dexlib2/writer/DexWriterTest.java
index b2cc52db..66abe06a 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/writer/DexWriterTest.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/writer/DexWriterTest.java
@@ -75,7 +75,7 @@ public class DexWriterTest {
throw new RuntimeException(ex);
}
- DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15), dataStore.getData());
+ DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15, false), dataStore.getData());
ClassDef dbClassDef = Iterables.getFirst(dexFile.getClasses(), null);
Assert.assertNotNull(dbClassDef);
Annotation dbAnnotation = Iterables.getFirst(dbClassDef.getAnnotations(), null);
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/writer/JumboStringConversionTest.java b/dexlib2/src/test/java/org/jf/dexlib2/writer/JumboStringConversionTest.java
index 38015e74..7e504a17 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/writer/JumboStringConversionTest.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/writer/JumboStringConversionTest.java
@@ -92,7 +92,7 @@ public class JumboStringConversionTest {
MemoryDataStore dexStore = new MemoryDataStore();
dexBuilder.writeTo(dexStore);
- DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15), dexStore.getData());
+ DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15, false), dexStore.getData());
ClassDef classDef = Iterables.getFirst(dexFile.getClasses(), null);
Assert.assertNotNull(classDef);
@@ -189,7 +189,7 @@ public class JumboStringConversionTest {
MemoryDataStore dexStore = new MemoryDataStore();
dexBuilder.writeTo(dexStore);
- DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15), dexStore.getData());
+ DexBackedDexFile dexFile = new DexBackedDexFile(new Opcodes(15, false), dexStore.getData());
ClassDef classDef = Iterables.getFirst(dexFile.getClasses(), null);
Assert.assertNotNull(classDef);