From db7795ffaa2d8804d84623a79d406f8c8686c1b8 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 9 Mar 2013 20:35:26 -0800 Subject: [PATCH] Add support for odex format 20bc --- .../Format/InstructionMethodItem.java | 18 ++--- .../org/jf/dexlib2/VerificationError.java | 73 +++++++++++++++++++ .../instruction/DexBackedInstruction.java | 2 + .../instruction/DexBackedInstruction20bc.java | 57 +++++++++++++++ .../jf/dexlib2/dexbacked/raw/CodeItem.java | 4 + .../VerificationErrorInstruction.java | 36 +++++++++ .../instruction/formats/Instruction20bc.java | 38 ++++++++++ .../instruction/ImmutableInstruction.java | 2 + .../instruction/ImmutableInstruction20bc.java | 73 +++++++++++++++++++ .../org/jf/dexlib2/util/Preconditions.java | 10 +++ 10 files changed, 304 insertions(+), 9 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index 75d19741..3602f398 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -33,7 +33,9 @@ import org.jf.baksmali.Adaptors.MethodItem; import org.jf.baksmali.Adaptors.ReferenceFormatter; import org.jf.baksmali.Renderers.LongRenderer; import org.jf.dexlib.Code.Format.UnknownInstruction; +import org.jf.dexlib2.VerificationError; import org.jf.dexlib2.iface.instruction.*; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; import org.jf.util.IndentingWriter; import javax.annotation.Nonnull; @@ -89,14 +91,13 @@ public class InstructionMethodItem extends MethodItem { writer.write(", "); writeSecondRegister(writer); return true; - //TODO: uncomment - /*case Format20bc: + case Format20bc: writeOpcode(writer); writer.write(' '); writeVerificationErrorType(writer); writer.write(", "); writeReference(writer); - return true;*/ + return true; case Format20t: case Format30t: writeOpcode(writer); @@ -236,7 +237,7 @@ public class InstructionMethodItem extends MethodItem { } protected void writeTargetLabel(IndentingWriter writer) throws IOException { - //this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that + //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that //have a target throw new RuntimeException(); } @@ -339,9 +340,8 @@ public class InstructionMethodItem extends MethodItem { ((ReferenceInstruction)instruction).getReference()); } - //TODO: uncomment - /*protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { - VerificationErrorType validationErrorType = ((Instruction20bc)instruction).getValidationErrorType(); - writer.write(validationErrorType.getName()); - }*/ + protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { + int verificationError = ((Instruction20bc)instruction).getVerificationError(); + writer.write(VerificationError.getVerificationErrorName(verificationError)); + } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java b/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java new file mode 100644 index 00000000..4e491a88 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, 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; + +public class VerificationError { + public static final int GENERIC = 1; + public static final int NO_SUCH_CLASS = 2; + public static final int NO_SUCH_FIELD = 3; + public static final int NO_SUCH_METHOD = 4; + public static final int ILLEGAL_CLASS_ACCESS = 5; + public static final int ILLEGAL_FIELD_ACCESS = 6; + public static final int ILLEGAL_METHOD_ACCESS = 7; + public static final int CLASS_CHANGE_ERROR = 8; + public static final int INSTANTIATION_ERROR = 9; + + public static String getVerificationErrorName(int verificationError) { + switch (verificationError) { + case GENERIC: + return "generic-error"; + case NO_SUCH_CLASS: + return "no-such-class"; + case NO_SUCH_FIELD: + return "no-such-field"; + case NO_SUCH_METHOD: + return "no-such-method"; + case ILLEGAL_CLASS_ACCESS: + return "illegal-class-access"; + case ILLEGAL_FIELD_ACCESS: + return "illegal-field-access"; + case ILLEGAL_METHOD_ACCESS: + return "illegal-method-access"; + case CLASS_CHANGE_ERROR: + return "class-change-error"; + case INSTANTIATION_ERROR: + return "instantiation-error"; + default: + return null; + } + } + + public static boolean isValidVerificationError(int verificationError) { + return verificationError > 0 && verificationError < 10; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java index e0613818..2628ff7a 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java @@ -84,6 +84,8 @@ public abstract class DexBackedInstruction implements Instruction { return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset); case Format12x: return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset); + case Format20bc: + return new DexBackedInstruction20bc(dexFile, opcode, instructionStartOffset); case Format20t: return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset); case Format21c: diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java new file mode 100644 index 00000000..1f9ec41c --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction20bc extends DexBackedInstruction implements Instruction20bc { + public DexBackedInstruction20bc(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getVerificationError() { return dexFile.readUbyte(instructionStart + 1) & 0x3f; } + + @Nonnull + @Override + public Reference getReference() { + int refType = (dexFile.readUbyte(instructionStart + 1) >>> 6) + 1; + return DexBackedReference.makeReference(dexFile, refType, dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java index 53590aaf..3486f11f 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java @@ -33,6 +33,7 @@ package org.jf.dexlib2.dexbacked.raw; import com.google.common.base.Joiner; import com.google.common.collect.Lists; +import org.jf.dexlib2.VerificationError; import org.jf.dexlib2.dexbacked.DexReader; import org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction; import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; @@ -261,6 +262,9 @@ public class CodeItem { args.add(formatRegister(((ThreeRegisterInstruction)instruction).getRegisterC())); } } + } else if (instruction instanceof VerificationErrorInstruction) { + args.add(VerificationError.getVerificationErrorName( + ((VerificationErrorInstruction)instruction).getVerificationError())); } if (instruction instanceof ReferenceInstruction) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java new file mode 100644 index 00000000..24a71215 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.iface.instruction; + +public interface VerificationErrorInstruction extends Instruction { + int getVerificationError(); +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java new file mode 100644 index 00000000..09d7439a --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.VerificationErrorInstruction; + +public interface Instruction20bc extends VerificationErrorInstruction, ReferenceInstruction { +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java index d32c46a5..430db35d 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java @@ -67,6 +67,8 @@ public abstract class ImmutableInstruction implements Instruction { return ImmutableInstruction11x.of((Instruction11x)instruction); case Format12x: return ImmutableInstruction12x.of((Instruction12x)instruction); + case Format20bc: + return ImmutableInstruction20bc.of((Instruction20bc)instruction); case Format20t: return ImmutableInstruction20t.of((Instruction20t)instruction); case Format21c: diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java new file mode 100644 index 00000000..9674d3d4 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction20bc extends ImmutableInstruction implements Instruction20bc { + public static final Format FORMAT = Format.Format20bc; + + protected final int verificationError; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction20bc(@Nonnull Opcode opcode, + int verificationError, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.verificationError = Preconditions.checkVerificationError(verificationError); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction20bc of(Instruction20bc instruction) { + if (instruction instanceof ImmutableInstruction20bc) { + return (ImmutableInstruction20bc)instruction; + } + return new ImmutableInstruction20bc( + instruction.getOpcode(), + instruction.getVerificationError(), + instruction.getReference()); + } + + @Override public int getVerificationError() { return verificationError; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java index ea9cfb69..917d9901 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java @@ -33,6 +33,7 @@ package org.jf.dexlib2.util; import org.jf.dexlib2.Format; import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.VerificationError; public class Preconditions { public static void checkFormat(Opcode opcode, Format expectedFormat) { @@ -175,4 +176,13 @@ public class Preconditions { } return inlineIndex; } + + public static int checkVerificationError(int verificationError) { + if (!VerificationError.isValidVerificationError(verificationError)) { + throw new IllegalArgumentException( + String.format("Invalid verification error value: %d. Must be between 1 and 9, inclusive", + verificationError)); + } + return verificationError; + } }