diff options
author | Orion Hodson <oth@google.com> | 2017-09-19 19:04:25 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-09-19 19:04:25 +0000 |
commit | d2e572e4432df7577fdb45705cb9ec9cc9009ecb (patch) | |
tree | 66b29d3f596e29a63efc80e11081809cc2966516 | |
parent | 49f383c1facb465b1daa7c4e5e73397291532bd8 (diff) | |
parent | ac9019c663d2d41221bd7205e4923b8a80664f73 (diff) | |
download | smali-d2e572e4432df7577fdb45705cb9ec9cc9009ecb.tar.gz |
Merge "Merge remote-tracking branch 'aosp/upstream-master' into oth-merge-smali-upstream" am: a0f3b5890f am: be0264527b
am: ac9019c663
Change-Id: I5c8a97e24dd7ad45f437f900493b87cd213eb3d0
30 files changed, 934 insertions, 16 deletions
@@ -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 Binary files differindex 6ffa2378..241a7ad1 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar 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 @@ -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" "$@" |