aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrion Hodson <oth@google.com>2017-09-19 19:12:13 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-09-19 19:12:13 +0000
commit3624a7cfdc4d3f2e78b57d7e9d130b6510f9fa0c (patch)
tree66b29d3f596e29a63efc80e11081809cc2966516
parent49f383c1facb465b1daa7c4e5e73397291532bd8 (diff)
parentd2e572e4432df7577fdb45705cb9ec9cc9009ecb (diff)
downloadsmali-3624a7cfdc4d3f2e78b57d7e9d130b6510f9fa0c.tar.gz
Merge "Merge remote-tracking branch 'aosp/upstream-master' into oth-merge-smali-upstream" am: a0f3b5890f am: be0264527b am: ac9019c663
am: d2e572e443 Change-Id: I6ea9f77c153228dc4888ea1d2c80b2695b822319
-rw-r--r--NOTICE4
-rw-r--r--baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java8
-rw-r--r--build.gradle6
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java68
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction22cs.java65
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35mi.java80
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35ms.java79
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rmi.java65
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rms.java66
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java104
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java63
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java42
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java33
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java31
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java11
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java16
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java15
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java23
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java13
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java21
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java6
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java4
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java4
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java24
-rw-r--r--dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java57
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java10
-rw-r--r--dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java9
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin52928 -> 54783 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties4
-rwxr-xr-xgradlew19
30 files changed, 934 insertions, 16 deletions
diff --git a/NOTICE b/NOTICE
index e29e98b8..7c80c51c 100644
--- a/NOTICE
+++ b/NOTICE
@@ -30,8 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Unless otherwise stated in the code/commit message, any changes with the
-committer of bgruv@google.com is copyrighted by Google Inc. and released
-under the following license:
+committer of bgruv@google.com or wkal@google.com is copyrighted by
+Google Inc. and released under the following license:
*******************************************************************************
Copyright 2011, Google Inc.
diff --git a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java
index 2e3eb79e..eb670df4 100644
--- a/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java
+++ b/baksmali/src/main/java/org/jf/baksmali/DisassembleCommand.java
@@ -132,6 +132,10 @@ public class DisassembleCommand extends DexInputCommand {
"fields from the current class.")
private boolean implicitReferences = false;
+ @Parameter(names = "--allow-odex-opcodes",
+ description = "Allows odex opcodes to be disassembled, even if the result won't be able to be reassembled.")
+ private boolean allowOdex = false;
+
@Parameter(names = "--classes",
description = "A comma separated list of classes. Only disassemble these classes")
@ExtendedParameter(argumentNames = "classes")
@@ -282,6 +286,10 @@ public class DisassembleCommand extends DexInputCommand {
dexFile.getClasses());
}
+ if (allowOdex) {
+ options.allowOdex = true;
+ }
+
return options;
}
}
diff --git a/build.gradle b/build.gradle
index 9e8205d4..08da9c85 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,7 +31,7 @@
apply plugin: 'idea'
-version = '2.2.0'
+version = '2.2.1'
def jcommanderVersion = ''
if (!('release' in gradle.startParameter.taskNames)) {
@@ -204,6 +204,6 @@ buildscript {
}
task wrapper(type: Wrapper) {
- gradleVersion = '3.1'
+ gradleVersion = '3.5'
distributionType = Wrapper.DistributionType.ALL
-} \ No newline at end of file
+}
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 148bafd1..a77ae253 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java
@@ -601,6 +601,9 @@ public class MutableMethodImplementation implements MethodImplementation {
case Format22c:
setInstruction(location, newBuilderInstruction22c((Instruction22c) instruction));
return;
+ case Format22cs:
+ setInstruction(location, newBuilderInstruction22cs((Instruction22cs) instruction));
+ return;
case Format22s:
setInstruction(location, newBuilderInstruction22s((Instruction22s) instruction));
return;
@@ -636,9 +639,21 @@ public class MutableMethodImplementation implements MethodImplementation {
case Format35c:
setInstruction(location, newBuilderInstruction35c((Instruction35c) instruction));
return;
+ case Format35mi:
+ setInstruction(location, newBuilderInstruction35mi((Instruction35mi) instruction));
+ return;
+ case Format35ms:
+ setInstruction(location, newBuilderInstruction35ms((Instruction35ms) instruction));
+ return;
case Format3rc:
setInstruction(location, newBuilderInstruction3rc((Instruction3rc)instruction));
return;
+ case Format3rmi:
+ setInstruction(location, newBuilderInstruction3rmi((Instruction3rmi)instruction));
+ return;
+ case Format3rms:
+ setInstruction(location, newBuilderInstruction3rms((Instruction3rms)instruction));
+ return;
case Format51l:
setInstruction(location, newBuilderInstruction51l((Instruction51l)instruction));
return;
@@ -771,6 +786,15 @@ public class MutableMethodImplementation implements MethodImplementation {
}
@Nonnull
+ private BuilderInstruction22cs newBuilderInstruction22cs(@Nonnull Instruction22cs instruction) {
+ return new BuilderInstruction22cs(
+ instruction.getOpcode(),
+ instruction.getRegisterA(),
+ instruction.getRegisterB(),
+ instruction.getFieldOffset());
+ }
+
+ @Nonnull
private BuilderInstruction22s newBuilderInstruction22s(@Nonnull Instruction22s instruction) {
return new BuilderInstruction22s(
instruction.getOpcode(),
@@ -869,6 +893,32 @@ public class MutableMethodImplementation implements MethodImplementation {
}
@Nonnull
+ private BuilderInstruction35mi newBuilderInstruction35mi(@Nonnull Instruction35mi instruction) {
+ return new BuilderInstruction35mi(
+ instruction.getOpcode(),
+ instruction.getRegisterCount(),
+ instruction.getRegisterC(),
+ instruction.getRegisterD(),
+ instruction.getRegisterE(),
+ instruction.getRegisterF(),
+ instruction.getRegisterG(),
+ instruction.getInlineIndex());
+ }
+
+ @Nonnull
+ private BuilderInstruction35ms newBuilderInstruction35ms(@Nonnull Instruction35ms instruction) {
+ return new BuilderInstruction35ms(
+ instruction.getOpcode(),
+ instruction.getRegisterCount(),
+ instruction.getRegisterC(),
+ instruction.getRegisterD(),
+ instruction.getRegisterE(),
+ instruction.getRegisterF(),
+ instruction.getRegisterG(),
+ instruction.getVtableIndex());
+ }
+
+ @Nonnull
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
return new BuilderInstruction3rc(
instruction.getOpcode(),
@@ -878,6 +928,24 @@ public class MutableMethodImplementation implements MethodImplementation {
}
@Nonnull
+ private BuilderInstruction3rmi newBuilderInstruction3rmi(@Nonnull Instruction3rmi instruction) {
+ return new BuilderInstruction3rmi(
+ instruction.getOpcode(),
+ instruction.getStartRegister(),
+ instruction.getRegisterCount(),
+ instruction.getInlineIndex());
+ }
+
+ @Nonnull
+ private BuilderInstruction3rms newBuilderInstruction3rms(@Nonnull Instruction3rms instruction) {
+ return new BuilderInstruction3rms(
+ instruction.getOpcode(),
+ instruction.getStartRegister(),
+ instruction.getRegisterCount(),
+ instruction.getVtableIndex());
+ }
+
+ @Nonnull
private BuilderInstruction51l newBuilderInstruction51l(@Nonnull Instruction51l instruction) {
return new BuilderInstruction51l(
instruction.getOpcode(),
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction22cs.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction22cs.java
new file mode 100644
index 00000000..e43f39da
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction22cs.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012, 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.Instruction22c;
+import org.jf.dexlib2.iface.instruction.formats.Instruction22cs;
+import org.jf.dexlib2.iface.reference.Reference;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction22cs extends BuilderInstruction implements Instruction22cs {
+ public static final Format FORMAT = Format.Format22cs;
+
+ protected final int registerA;
+ protected final int registerB;
+ protected final int fieldOffset;
+
+ public BuilderInstruction22cs(@Nonnull Opcode opcode,
+ int registerA,
+ int registerB,
+ int fieldOffset) {
+ super(opcode);
+ this.registerA = Preconditions.checkNibbleRegister(registerA);
+ this.registerB = Preconditions.checkNibbleRegister(registerB);
+ this.fieldOffset = fieldOffset;
+ }
+
+ @Override public int getRegisterA() { return registerA; }
+ @Override public int getRegisterB() { return registerB; }
+ @Override public int getFieldOffset() { return fieldOffset; }
+ @Override public Format getFormat() { return FORMAT; }
+} \ No newline at end of file
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35mi.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35mi.java
new file mode 100644
index 00000000..43aed787
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35mi.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, 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.Instruction35mi;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction35mi extends BuilderInstruction implements Instruction35mi {
+ public static final Format FORMAT = Format.Format35mi;
+
+ protected final int registerCount;
+ protected final int registerC;
+ protected final int registerD;
+ protected final int registerE;
+ protected final int registerF;
+ protected final int registerG;
+ protected final int inlineIndex;
+
+ public BuilderInstruction35mi(@Nonnull Opcode opcode,
+ int registerCount,
+ int registerC,
+ int registerD,
+ int registerE,
+ int registerF,
+ int registerG,
+ int inlineIndex) {
+ super(opcode);
+ this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
+ this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
+ this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
+ this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
+ this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0;
+ this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0;
+ this.inlineIndex = inlineIndex;
+ }
+
+ @Override public int getRegisterCount() { return registerCount; }
+ @Override public int getRegisterC() { return registerC; }
+ @Override public int getRegisterD() { return registerD; }
+ @Override public int getRegisterE() { return registerE; }
+ @Override public int getRegisterF() { return registerF; }
+ @Override public int getRegisterG() { return registerG; }
+ @Override public int getInlineIndex() { return inlineIndex; }
+ @Override public Format getFormat() { return FORMAT; }
+
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35ms.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35ms.java
new file mode 100644
index 00000000..824dbd8e
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35ms.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012, 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.Instruction35ms;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction35ms extends BuilderInstruction implements Instruction35ms {
+ public static final Format FORMAT = Format.Format35ms;
+
+ protected final int registerCount;
+ protected final int registerC;
+ protected final int registerD;
+ protected final int registerE;
+ protected final int registerF;
+ protected final int registerG;
+ protected final int vtableIndex;
+
+ public BuilderInstruction35ms(@Nonnull Opcode opcode,
+ int registerCount,
+ int registerC,
+ int registerD,
+ int registerE,
+ int registerF,
+ int registerG,
+ int vtableIndex) {
+ super(opcode);
+ this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
+ this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
+ this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
+ this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
+ this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0;
+ this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0;
+ this.vtableIndex = vtableIndex;
+ }
+
+ @Override public int getRegisterCount() { return registerCount; }
+ @Override public int getRegisterC() { return registerC; }
+ @Override public int getRegisterD() { return registerD; }
+ @Override public int getRegisterE() { return registerE; }
+ @Override public int getRegisterF() { return registerF; }
+ @Override public int getRegisterG() { return registerG; }
+ @Override public int getVtableIndex() { return vtableIndex; }
+ @Override public Format getFormat() { return FORMAT; }
+}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rmi.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rmi.java
new file mode 100644
index 00000000..1df7b308
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rmi.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012, 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.Instruction3rmi;
+import org.jf.dexlib2.iface.instruction.formats.Instruction3rms;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction3rmi extends BuilderInstruction implements Instruction3rmi {
+ public static final Format FORMAT = Format.Format3rmi;
+
+ protected final int startRegister;
+ protected final int registerCount;
+ protected final int inlineIndex;
+
+ public BuilderInstruction3rmi(@Nonnull Opcode opcode,
+ int startRegister,
+ int registerCount,
+ int inlineIndex) {
+ super(opcode);
+ this.startRegister = Preconditions.checkShortRegister(startRegister);
+ this.registerCount = Preconditions.checkRegisterRangeCount(registerCount);
+ this.inlineIndex = inlineIndex;
+ }
+
+ @Override public int getStartRegister() { return startRegister; }
+ @Override public int getRegisterCount() { return registerCount; }
+ @Override public int getInlineIndex() { return inlineIndex; }
+ @Override public Format getFormat() { return FORMAT; }
+}
+
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rms.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rms.java
new file mode 100644
index 00000000..bd73901f
--- /dev/null
+++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction3rms.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012, 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.Instruction3rc;
+import org.jf.dexlib2.iface.instruction.formats.Instruction3rms;
+import org.jf.dexlib2.iface.reference.Reference;
+import org.jf.dexlib2.util.Preconditions;
+
+import javax.annotation.Nonnull;
+
+public class BuilderInstruction3rms extends BuilderInstruction implements Instruction3rms {
+ public static final Format FORMAT = Format.Format3rms;
+
+ protected final int startRegister;
+ protected final int registerCount;
+ protected final int vtableIndex;
+
+ public BuilderInstruction3rms(@Nonnull Opcode opcode,
+ int startRegister,
+ int registerCount,
+ int vtableIndex) {
+ super(opcode);
+ this.startRegister = Preconditions.checkShortRegister(startRegister);
+ this.registerCount = Preconditions.checkRegisterRangeCount(registerCount);
+ this.vtableIndex = vtableIndex;
+ }
+
+ @Override public int getStartRegister() { return startRegister; }
+ @Override public int getRegisterCount() { return registerCount; }
+ @Override public int getVtableIndex() { return vtableIndex; }
+ @Override public Format getFormat() { return FORMAT; }
+}
+
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java
index 13c0a7b0..e6880de2 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java
@@ -88,10 +88,41 @@ public class BaseDexReader<T extends BaseDexBuffer> {
return result;
}
+ public int peekSleb128Size() {
+ int end = dexBuf.baseOffset + offset;
+ int currentByteValue;
+ int result;
+ byte[] buf = dexBuf.buf;
+
+ result = buf[end++] & 0xff;
+ if (result > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ throw new ExceptionWithContext(
+ "Invalid sleb128 integer encountered at offset 0x%x", offset);
+ }
+ }
+ }
+ }
+ }
+
+ return end - (dexBuf.baseOffset + offset);
+ }
+
public int readSmallUleb128() {
return readUleb128(false);
}
+ public int peekSmallUleb128Size() {
+ return peekUleb128Size(false);
+ }
+
private int readUleb128(boolean allowLarge) {
int end = dexBuf.baseOffset + offset;
int currentByteValue;
@@ -133,6 +164,43 @@ public class BaseDexReader<T extends BaseDexBuffer> {
return result;
}
+ private int peekUleb128Size(boolean allowLarge) {
+ int end = dexBuf.baseOffset + offset;
+ int currentByteValue;
+ int result;
+ byte[] buf = dexBuf.buf;
+
+ result = buf[end++] & 0xff;
+ if (result > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++];
+
+ // MSB shouldn't be set on last byte
+ if (currentByteValue < 0) {
+ throw new ExceptionWithContext(
+ "Invalid uleb128 integer encountered at offset 0x%x", offset);
+ } else if ((currentByteValue & 0xf) > 0x07) {
+ if (!allowLarge) {
+ // for non-large uleb128s, we assume most significant bit of the result will not be
+ // set, so that it can fit into a signed integer without wrapping
+ throw new ExceptionWithContext(
+ "Encountered valid uleb128 that is out of range at offset 0x%x", offset);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return end - (dexBuf.baseOffset + offset);
+ }
+
+
/**
* Reads a "large" uleb128. That is, one that may legitimately be greater than a signed int.
*
@@ -183,6 +251,35 @@ public class BaseDexReader<T extends BaseDexBuffer> {
return result;
}
+ public int peekBigUleb128Size() {
+ int end = dexBuf.baseOffset + offset;
+ int currentByteValue;
+ int result;
+ byte[] buf = dexBuf.buf;
+
+ result = buf[end++] & 0xff;
+ if (result > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++] & 0xff;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = buf[end++];
+
+ // MSB shouldn't be set on last byte
+ if (currentByteValue < 0) {
+ throw new ExceptionWithContext(
+ "Invalid uleb128 integer encountered at offset 0x%x", offset);
+ }
+ }
+ }
+ }
+ }
+
+ return end - (dexBuf.baseOffset + offset);
+ }
+
public void skipUleb128() {
int end = dexBuf.baseOffset + offset;
byte currentByteValue;
@@ -516,4 +613,11 @@ public class BaseDexReader<T extends BaseDexBuffer> {
offset += ret[0];
return value;
}
+
+ public int peekStringLength(int utf16Length) {
+ int[] ret = new int[1];
+ Utf8Utils.utf8BytesWithUtf16LengthToString(
+ dexBuf.buf, dexBuf.baseOffset + offset, utf16Length, ret);
+ return ret[0];
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
index 88f1dce9..9159fc6b 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java
@@ -36,6 +36,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.jf.dexlib2.base.reference.BaseTypeReference;
import org.jf.dexlib2.dexbacked.raw.ClassDefItem;
+import org.jf.dexlib2.dexbacked.raw.TypeIdItem;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.FixedSizeSet;
import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator;
@@ -434,4 +435,66 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
virtualMethodsOffset = reader.getOffset();
return virtualMethodsOffset;
}
+
+ /**
+ * Calculate and return the private size of a class definition.
+ *
+ * Calculated as: class_def_item size + type_id size + interfaces type_list +
+ * annotations_directory_item overhead + class_data_item + static values overhead +
+ * methods size + fields size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = 8 * 4; //class_def_item has 8 uint fields in dex files
+ size += TypeIdItem.ITEM_SIZE; //type_ids size
+
+ //add interface list size if any
+ int interfacesLength = getInterfaces().size();
+ if (interfacesLength > 0) {
+ //add size of the type_list
+ size += 4; //uint for size
+ size += interfacesLength * 2; //ushort per type_item
+ }
+
+ //annotations directory size if it exists
+ AnnotationsDirectory directory = getAnnotationsDirectory();
+ if (!AnnotationsDirectory.EMPTY.equals(directory)) {
+ size += 4 * 4; //4 uints in annotations_directory_item
+ Set<? extends DexBackedAnnotation> classAnnotations = directory.getClassAnnotations();
+ if (!classAnnotations.isEmpty()) {
+ size += 4; //uint for size
+ size += classAnnotations.size() * 4; //uint per annotation_off
+ //TODO: should we add annotation_item size? what if it's shared?
+ }
+ }
+
+ //static values and/or metadata
+ int staticInitialValuesOffset =
+ dexFile.readSmallUint(classDefOffset + ClassDefItem.STATIC_VALUES_OFFSET);
+ if (staticInitialValuesOffset != 0) {
+ DexReader reader = dexFile.readerAt(staticInitialValuesOffset);
+ size += reader.peekSmallUleb128Size(); //encoded_array size field
+ }
+
+ //class_data_item
+ int classDataOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_DATA_OFFSET);
+ if (classDataOffset > 0) {
+ DexReader reader = dexFile.readerAt(classDataOffset);
+ reader.readSmallUleb128(); //staticFieldCount
+ reader.readSmallUleb128(); //instanceFieldCount
+ reader.readSmallUleb128(); //directMethodCount
+ reader.readSmallUleb128(); //virtualMethodCount
+ size += reader.getOffset() - classDataOffset;
+ }
+
+ for (DexBackedField dexBackedField : getFields()) {
+ size += dexBackedField.getSize();
+ }
+
+ for (DexBackedMethod dexBackedMethod : getMethods()) {
+ size += dexBackedMethod.getSize();
+ }
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java
index 5eff67a1..653cdbd3 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java
@@ -33,8 +33,10 @@ package org.jf.dexlib2.dexbacked;
import org.jf.dexlib2.base.reference.BaseFieldReference;
import org.jf.dexlib2.dexbacked.raw.FieldIdItem;
+import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator;
+import org.jf.dexlib2.dexbacked.value.DexBackedEncodedValue;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.value.EncodedValue;
@@ -52,6 +54,8 @@ public class DexBackedField extends BaseFieldReference implements Field {
public final int annotationSetOffset;
public final int fieldIndex;
+ private final int startOffset;
+ private final int initialValueOffset;
private int fieldIdItemOffset;
@@ -65,11 +69,13 @@ public class DexBackedField extends BaseFieldReference implements Field {
// large values may be used for the index delta, which cause the cumulative index to overflow upon
// addition, effectively allowing out of order entries.
+ startOffset = reader.getOffset();
int fieldIndexDiff = reader.readLargeUleb128();
this.fieldIndex = fieldIndexDiff + previousFieldIndex;
this.accessFlags = reader.readSmallUleb128();
this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
+ initialValueOffset = staticInitialValueIterator.getReaderOffset();
this.initialValue = staticInitialValueIterator.getNextOrNull();
}
@@ -82,11 +88,13 @@ public class DexBackedField extends BaseFieldReference implements Field {
// large values may be used for the index delta, which cause the cumulative index to overflow upon
// addition, effectively allowing out of order entries.
+ startOffset = reader.getOffset();
int fieldIndexDiff = reader.readLargeUleb128();
this.fieldIndex = fieldIndexDiff + previousFieldIndex;
this.accessFlags = reader.readSmallUleb128();
this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
+ initialValueOffset = 0;
this.initialValue = null;
}
@@ -131,4 +139,38 @@ public class DexBackedField extends BaseFieldReference implements Field {
}
return fieldIdItemOffset;
}
+
+ /**
+ * Calculate and return the private size of a field definition.
+ *
+ * Calculated as: field_idx_diff + access_flags + annotations overhead +
+ * initial value size + field reference size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = 0;
+ DexReader reader = dexFile.readerAt(startOffset);
+ reader.readLargeUleb128(); //field_idx_diff
+ reader.readSmallUleb128(); //access_flags
+ size += reader.getOffset() - startOffset;
+
+ Set<? extends DexBackedAnnotation> annotations = getAnnotations();
+ if (!annotations.isEmpty()) {
+ size += 2 * 4; //2 * uint overhead from field_annotation
+ }
+
+ if (initialValueOffset > 0) {
+ reader.setOffset(initialValueOffset);
+ if (initialValue != null) {
+ DexBackedEncodedValue.skipFrom(reader);
+ size += reader.getOffset() - initialValueOffset;
+ }
+ }
+
+ DexBackedFieldReference fieldRef = new DexBackedFieldReference(dexFile, fieldIndex);
+ size += fieldRef.getSize();
+
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
index eccb9218..821d2232 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethod.java
@@ -37,11 +37,13 @@ import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.dexbacked.raw.MethodIdItem;
import org.jf.dexlib2.dexbacked.raw.ProtoIdItem;
import org.jf.dexlib2.dexbacked.raw.TypeListItem;
+import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.ParameterIterator;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.Method;
+import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.util.AbstractForwardSequentialList;
@@ -62,6 +64,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
private final int methodAnnotationSetOffset;
public final int methodIndex;
+ private final int startOffset;
private int methodIdItemOffset;
private int protoIdItemOffset;
@@ -72,6 +75,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
int previousMethodIndex) {
this.dexFile = reader.dexBuf;
this.classDef = classDef;
+ startOffset = reader.getOffset();
// large values may be used for the index delta, which cause the cumulative index to overflow upon
// addition, effectively allowing out of order entries.
@@ -91,6 +95,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
@Nonnull AnnotationsDirectory.AnnotationIterator paramaterAnnotationIterator) {
this.dexFile = reader.dexBuf;
this.classDef = classDef;
+ startOffset = reader.getOffset();
// large values may be used for the index delta, which cause the cumulative index to overflow upon
// addition, effectively allowing out of order entries.
@@ -224,4 +229,32 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
reader.skipUleb128();
}
}
+
+ /**
+ * Calculate and return the private size of a method definition.
+ *
+ * Calculated as: method_idx_diff + access_flags + code_off +
+ * implementation size + reference size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = 0;
+
+ DexReader reader = dexFile.readerAt(startOffset);
+ reader.readLargeUleb128(); //method_idx_diff
+ reader.readSmallUleb128(); //access_flags
+ reader.readSmallUleb128(); //code_off
+ size += reader.getOffset() - startOffset;
+
+ DexBackedMethodImplementation impl = getImplementation();
+ if (impl != null) {
+ size += impl.getSize();
+ }
+
+ DexBackedMethodReference methodRef = new DexBackedMethodReference(dexFile, methodIndex);
+ size += methodRef.getSize();
+
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
index a82032a1..cfe16aa6 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedMethodImplementation.java
@@ -36,6 +36,7 @@ import org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction;
import org.jf.dexlib2.dexbacked.raw.CodeItem;
import org.jf.dexlib2.dexbacked.util.DebugInfo;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
+import org.jf.dexlib2.dexbacked.util.VariableSizeListIterator;
import org.jf.dexlib2.dexbacked.util.VariableSizeLookaheadIterator;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.debug.DebugItem;
@@ -148,4 +149,34 @@ public class DexBackedMethodImplementation implements MethodImplementation {
public Iterator<String> getParameterNames(@Nullable DexReader dexReader) {
return getDebugInfo().getParameterNames(dexReader);
}
+
+ /**
+ * Calculate and return the private size of a method implementation.
+ *
+ * Calculated as: debug info size + instructions size + try-catch size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int debugSize = getDebugInfo().getSize();
+
+ //set last offset just before bytecode instructions (after insns_size)
+ int lastOffset = codeOffset + CodeItem.INSTRUCTION_START_OFFSET;
+
+ //set code_item ending offset to the end of instructions list (insns_size * ushort)
+ lastOffset += dexFile.readSmallUint(codeOffset + CodeItem.INSTRUCTION_COUNT_OFFSET) * 2;
+
+ //read any exception handlers and move code_item offset to the end
+ for (DexBackedTryBlock tryBlock: getTryBlocks()) {
+ Iterator<? extends DexBackedExceptionHandler> tryHandlerIter =
+ tryBlock.getExceptionHandlers().iterator();
+ while (tryHandlerIter.hasNext()) {
+ tryHandlerIter.next();
+ }
+ lastOffset = ((VariableSizeListIterator)tryHandlerIter).getReaderOffset();
+ }
+
+ //method impl size = debug block size + code_item size
+ return debugSize + (lastOffset - codeOffset);
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java
index c3655d54..a00c987a 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java
@@ -63,4 +63,15 @@ public class DexBackedFieldReference extends BaseFieldReference {
public String getType() {
return dexFile.getType(dexFile.readUshort(fieldIdItemOffset + FieldIdItem.TYPE_OFFSET));
}
+
+ /**
+ * Calculate and return the private size of a field reference.
+ *
+ * Calculated as: class_idx + type_idx + name_idx
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ return FieldIdItem.ITEM_SIZE;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java
index 12875b7b..9d9c6b18 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java
@@ -74,4 +74,20 @@ public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
public String getReturnType() {
return dexFile.getType(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET));
}
+
+ /**
+ * Calculate and return the private size of a method proto.
+ *
+ * Calculated as: shorty_idx + return_type_idx + parameters_off + type_list size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = ProtoIdItem.ITEM_SIZE; //3 * uint
+ List<String> parameters = getParameterTypes();
+ if (!parameters.isEmpty()) {
+ size += 4 + parameters.size() * 2; //uint + size * ushort for type_idxs
+ }
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java
index 6a85e8b9..f2b0b597 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java
@@ -98,4 +98,19 @@ public class DexBackedMethodReference extends BaseMethodReference {
}
return protoIdItemOffset;
}
+
+ /**
+ * Calculate and return the private size of a method reference.
+ *
+ * Calculated as: class_idx + proto_idx + name_idx + prototype size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = MethodIdItem.ITEM_SIZE; //ushort + ushort + uint for indices
+ DexBackedMethodProtoReference protoRef = new DexBackedMethodProtoReference(dexFile,
+ dexFile.readUshort(methodIdItemOffset + MethodIdItem.PROTO_OFFSET));
+ size += protoRef.getSize();
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java
index 61d0c818..4eb0097d 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java
@@ -33,6 +33,8 @@ package org.jf.dexlib2.dexbacked.reference;
import org.jf.dexlib2.base.reference.BaseStringReference;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
+import org.jf.dexlib2.dexbacked.DexReader;
+import org.jf.dexlib2.dexbacked.raw.StringIdItem;
import javax.annotation.Nonnull;
@@ -50,4 +52,25 @@ public class DexBackedStringReference extends BaseStringReference {
public String getString() {
return dexFile.getString(stringIndex);
}
+
+
+ /**
+ * Calculate and return the private size of a string reference.
+ *
+ * Calculated as: string_data_off + string_data_item size
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ int size = StringIdItem.ITEM_SIZE; //uint for string_data_off
+ //add the string data length:
+ int stringOffset = dexFile.getStringIdItemOffset(stringIndex);
+ int stringDataOffset = dexFile.readSmallUint(stringOffset);
+ DexReader reader = dexFile.readerAt(stringDataOffset);
+ size += reader.peekSmallUleb128Size();
+ int utf16Length = reader.readSmallUleb128();
+ //and string data itself:
+ size += reader.peekStringLength(utf16Length);
+ return size;
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java
index 2fcff0a2..5dc52410 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java
@@ -33,6 +33,7 @@ package org.jf.dexlib2.dexbacked.reference;
import org.jf.dexlib2.base.reference.BaseTypeReference;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
+import org.jf.dexlib2.dexbacked.raw.TypeIdItem;
import javax.annotation.Nonnull;
@@ -49,4 +50,16 @@ public class DexBackedTypeReference extends BaseTypeReference {
@Nonnull public String getType() {
return dexFile.getType(typeIndex);
}
+
+
+ /**
+ * Calculate and return the private size of a type reference.
+ *
+ * Calculated as: descriptor_idx
+ *
+ * @return size in bytes
+ */
+ public int getSize() {
+ return TypeIdItem.ITEM_SIZE; //uint for descriptor_idx
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
index ef240718..d82e4d6f 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java
@@ -59,6 +59,13 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
*/
@Nonnull public abstract Iterator<String> getParameterNames(@Nullable DexReader reader);
+ /**
+ * Calculate and return the private size of debuginfo.
+ *
+ * @return size in bytes
+ */
+ public abstract int getSize();
+
public static DebugInfo newOrEmpty(@Nonnull DexBackedDexFile dexFile, int debugInfoOffset,
@Nonnull DexBackedMethodImplementation methodImpl) {
if (debugInfoOffset == 0) {
@@ -78,6 +85,11 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
@Nonnull @Override public Iterator<String> getParameterNames(@Nullable DexReader reader) {
return ImmutableSet.<String>of().iterator();
}
+
+ @Override
+ public int getSize() {
+ return 0;
+ }
}
private static class DebugInfoImpl extends DebugInfo {
@@ -279,5 +291,14 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
}
};
}
+
+ @Override
+ public int getSize() {
+ Iterator<DebugItem> iter = iterator();
+ while(iter.hasNext()) {
+ iter.next();
+ }
+ return ((VariableSizeLookaheadIterator) iter).getReaderOffset() - debugInfoOffset;
+ }
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java
index 1c452ae3..f17b938a 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java
@@ -43,10 +43,12 @@ public abstract class StaticInitialValueIterator {
public static final StaticInitialValueIterator EMPTY = new StaticInitialValueIterator() {
@Nullable @Override public EncodedValue getNextOrNull() { return null; }
@Override public void skipNext() {}
+ @Override public int getReaderOffset() { return 0; }
};
@Nullable public abstract EncodedValue getNextOrNull();
public abstract void skipNext();
+ public abstract int getReaderOffset();
@Nonnull
public static StaticInitialValueIterator newOrEmpty(@Nonnull DexBackedDexFile dexFile, int offset) {
@@ -81,5 +83,9 @@ public abstract class StaticInitialValueIterator {
DexBackedEncodedValue.skipFrom(reader);
}
}
+
+ public int getReaderOffset() {
+ return reader.getOffset();
+ }
}
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java
index 1f4259ff..bc2f5056 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java
@@ -59,4 +59,8 @@ public abstract class VariableSizeLookaheadIterator<T> extends AbstractIterator<
protected T computeNext() {
return readNextItem(reader);
}
+
+ public final int getReaderOffset() {
+ return reader.getOffset();
+ }
}
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java b/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java
index eb1f8d92..58ce2628 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java
@@ -38,5 +38,9 @@ public final class InstructionUtil {
return opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE;
}
+ public static boolean isInvokePolymorphic(Opcode opcode) {
+ return opcode == Opcode.INVOKE_POLYMORPHIC || opcode == Opcode.INVOKE_POLYMORPHIC_RANGE;
+ }
+
private InstructionUtil() {}
}
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 00cce65d..3020f326 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java
@@ -52,6 +52,7 @@ import org.jf.dexlib2.iface.debug.LineNumber;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
+import org.jf.dexlib2.iface.instruction.VariableRegisterInstruction;
import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.util.InstructionUtil;
@@ -955,7 +956,13 @@ public abstract class DexWriter<
if (instruction.getOpcode().referenceType == ReferenceType.METHOD) {
ReferenceInstruction refInsn = (ReferenceInstruction)instruction;
MethodReference methodRef = (MethodReference)refInsn.getReference();
- int paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(instruction.getOpcode()));
+ Opcode opcode = instruction.getOpcode();
+ int paramCount;
+ if (InstructionUtil.isInvokePolymorphic(opcode)) {
+ paramCount = ((VariableRegisterInstruction)instruction).getRegisterCount();
+ } else {
+ paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(opcode));
+ }
if (paramCount > outParamCount) {
outParamCount = paramCount;
}
@@ -1017,6 +1024,9 @@ public abstract class DexWriter<
case Format22c:
instructionWriter.write((Instruction22c)instruction);
break;
+ case Format22cs:
+ instructionWriter.write((Instruction22cs)instruction);
+ break;
case Format22s:
instructionWriter.write((Instruction22s)instruction);
break;
@@ -1047,9 +1057,21 @@ public abstract class DexWriter<
case Format35c:
instructionWriter.write((Instruction35c)instruction);
break;
+ case Format35mi:
+ instructionWriter.write((Instruction35mi)instruction);
+ break;
+ case Format35ms:
+ instructionWriter.write((Instruction35ms)instruction);
+ break;
case Format3rc:
instructionWriter.write((Instruction3rc)instruction);
break;
+ case Format3rmi:
+ instructionWriter.write((Instruction3rmi)instruction);
+ break;
+ case Format3rms:
+ instructionWriter.write((Instruction3rms)instruction);
+ break;
case Format45cc:
instructionWriter.write((Instruction45cc)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 1b883f1f..f6fd52fd 100644
--- a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java
+++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java
@@ -239,6 +239,16 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
}
}
+ public void write(@Nonnull Instruction22cs instruction) {
+ try {
+ writer.write(getOpcodeValue(instruction.getOpcode()));
+ writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB()));
+ writer.writeUshort(instruction.getFieldOffset());
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
public void write(@Nonnull Instruction22s instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
@@ -343,6 +353,30 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
}
}
+ public void write(@Nonnull Instruction35mi instruction) {
+ try {
+ writer.write(getOpcodeValue(instruction.getOpcode()));
+ writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
+ writer.writeUshort(instruction.getInlineIndex());
+ writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
+ writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public void write(@Nonnull Instruction35ms instruction) {
+ try {
+ writer.write(getOpcodeValue(instruction.getOpcode()));
+ writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
+ writer.writeUshort(instruction.getVtableIndex());
+ writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
+ writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
public void write(@Nonnull Instruction3rc instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
@@ -354,6 +388,29 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
}
}
+ public void write(@Nonnull Instruction3rmi instruction) {
+ try {
+ writer.write(getOpcodeValue(instruction.getOpcode()));
+ writer.write(instruction.getRegisterCount());
+ writer.writeUshort(instruction.getInlineIndex());
+ writer.writeUshort(instruction.getStartRegister());
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ public void write(@Nonnull Instruction3rms instruction) {
+ try {
+ writer.write(getOpcodeValue(instruction.getOpcode()));
+ writer.write(instruction.getRegisterCount());
+ writer.writeUshort(instruction.getVtableIndex());
+ writer.writeUshort(instruction.getStartRegister());
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
public void write(@Nonnull Instruction45cc instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java
index 79da5ecb..bcaaaeee 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java
@@ -254,12 +254,22 @@ public class BaseDexReaderLeb128Test {
reader = dexBuf.readerAt(0);
reader.skipUleb128();
Assert.assertEquals(expectedLength, reader.getOffset());
+
+ reader = dexBuf.readerAt(0);
+ Assert.assertEquals(expectedLength, reader.peekSmallUleb128Size());
}
private void performFailureTest(byte[] buf) {
BaseDexBuffer dexBuf = new BaseDexBuffer(buf);
BaseDexReader reader = dexBuf.readerAt(0);
try {
+ reader.peekSmallUleb128Size();
+ Assert.fail();
+ } catch (ExceptionWithContext ex) {
+ // expected exception
+ }
+
+ try {
reader.readSmallUleb128();
Assert.fail();
} catch (ExceptionWithContext ex) {
diff --git a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java
index cd1cc1a1..846ebb6f 100644
--- a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java
+++ b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java
@@ -257,12 +257,21 @@ public class BaseDexReaderSleb128Test {
BaseDexReader reader = dexBuf.readerAt(0);
Assert.assertEquals(expectedValue, reader.readSleb128());
Assert.assertEquals(expectedLength, reader.getOffset());
+
+ reader = dexBuf.readerAt(0);
+ Assert.assertEquals(expectedLength, reader.peekSleb128Size());
}
private void performFailureTest(byte[] buf) {
BaseDexBuffer dexBuf = new BaseDexBuffer(buf);
BaseDexReader reader = dexBuf.readerAt(0);
try {
+ reader.peekSleb128Size();
+ Assert.fail();
+ } catch (ExceptionWithContext ex) {
+ // expected exception
+ }
+ try {
reader.readSleb128();
Assert.fail();
} catch (ExceptionWithContext ex) {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 6ffa2378..241a7ad1 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8ee9c631..ea282cc8 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Sep 28 23:22:26 AEST 2016
+#Wed May 03 00:04:05 SGT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
diff --git a/gradlew b/gradlew
index 9aa616c2..4453ccea 100755
--- a/gradlew
+++ b/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
##############################################################################
##
@@ -154,16 +154,19 @@ if $cygwin ; then
esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+exec "$JAVACMD" "$@"