mirror of
https://github.com/revanced/smali.git
synced 2025-06-12 12:17:37 +02:00
Add support for the throw-verification-error opcode
This commit is contained in:
@ -36,6 +36,7 @@ public enum Format {
|
||||
Format11n(Instruction11n.Factory, 2),
|
||||
Format11x(Instruction11x.Factory, 2),
|
||||
Format12x(Instruction12x.Factory, 2),
|
||||
Format20bc(Instruction20bc.Factory, 4),
|
||||
Format20t(Instruction20t.Factory, 4),
|
||||
Format21c(Instruction21c.Factory, 4),
|
||||
Format21h(Instruction21h.Factory, 4),
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2011 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.dexlib.Code.Format;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Code.*;
|
||||
import org.jf.dexlib.Util.AnnotatedOutput;
|
||||
import org.jf.dexlib.Util.NumberUtils;
|
||||
|
||||
public class Instruction20bc extends InstructionWithReference {
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private VerificationErrorType validationErrorType;
|
||||
|
||||
public Instruction20bc(Opcode opcode, VerificationErrorType validationErrorType, Item referencedItem) {
|
||||
super(opcode, referencedItem, getReferenceType(referencedItem));
|
||||
|
||||
this.validationErrorType = validationErrorType;
|
||||
}
|
||||
|
||||
private static ReferenceType getReferenceType(Item item) {
|
||||
if (item instanceof TypeIdItem) {
|
||||
return ReferenceType.type;
|
||||
}
|
||||
if (item instanceof FieldIdItem) {
|
||||
return ReferenceType.field;
|
||||
}
|
||||
if (item instanceof MethodIdItem) {
|
||||
return ReferenceType.method;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Instruction20bc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
super(dexFile, opcode, buffer, bufferIndex);
|
||||
|
||||
short val = NumberUtils.decodeUnsignedByte(buffer[bufferIndex+1]);
|
||||
validationErrorType = VerificationErrorType.getValidationErrorType(val & 0x3f);
|
||||
}
|
||||
|
||||
protected ReferenceType readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
short val = NumberUtils.decodeUnsignedByte(buffer[bufferIndex+1]);
|
||||
short referenceType = (short)(val >> 6);
|
||||
return ReferenceType.fromValidationErrorReferenceType(referenceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Format getFormat() {
|
||||
return Format.Format20bc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
if(opcode == Opcode.CONST_STRING && getReferencedItem().getIndex() > 0xFFFF) {
|
||||
throw new RuntimeException("String offset is too large for const-string. Use string-const/jumbo instead.");
|
||||
}
|
||||
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte((this.getReferenceType().getValidationErrorReferenceType() << 6) &
|
||||
validationErrorType.getValue());
|
||||
|
||||
out.writeShort(getReferencedItem().getIndex());
|
||||
}
|
||||
|
||||
public VerificationErrorType getValidationErrorType() {
|
||||
return validationErrorType;
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return new Instruction20bc(dexFile, opcode, buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,17 +33,27 @@ import org.jf.dexlib.Util.NumberUtils;
|
||||
|
||||
public abstract class InstructionWithReference extends Instruction {
|
||||
private Item referencedItem;
|
||||
private ReferenceType referenceType;
|
||||
|
||||
protected InstructionWithReference(Opcode opcode, Item referencedItem) {
|
||||
super(opcode);
|
||||
this.referencedItem = referencedItem;
|
||||
this.referenceType = opcode.referenceType;
|
||||
checkReferenceType();
|
||||
}
|
||||
|
||||
protected InstructionWithReference(Opcode opcode, Item referencedItem, ReferenceType referenceType) {
|
||||
super(opcode);
|
||||
this.referencedItem = referencedItem;
|
||||
this.referenceType = referenceType;
|
||||
checkReferenceType();
|
||||
}
|
||||
|
||||
protected InstructionWithReference(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
super(opcode);
|
||||
|
||||
int itemIndex = getReferencedItemIndex(buffer, bufferIndex);
|
||||
this.referenceType = readReferenceType(opcode, buffer, bufferIndex);
|
||||
int itemIndex = getReferencedItemIndex(buffer, bufferIndex);
|
||||
lookupReferencedItem(dexFile, opcode, itemIndex);
|
||||
}
|
||||
|
||||
@ -51,12 +61,20 @@ public abstract class InstructionWithReference extends Instruction {
|
||||
return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
|
||||
}
|
||||
|
||||
public ReferenceType getReferenceType() {
|
||||
return referenceType;
|
||||
}
|
||||
|
||||
public Item getReferencedItem() {
|
||||
return referencedItem;
|
||||
}
|
||||
|
||||
protected ReferenceType readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return opcode.referenceType;
|
||||
}
|
||||
|
||||
private void lookupReferencedItem(DexFile dexFile, Opcode opcode, int itemIndex) {
|
||||
switch (opcode.referenceType) {
|
||||
switch (referenceType) {
|
||||
case field:
|
||||
referencedItem = dexFile.FieldIdsSection.getItemByIndex(itemIndex);
|
||||
return;
|
||||
@ -73,7 +91,7 @@ public abstract class InstructionWithReference extends Instruction {
|
||||
|
||||
|
||||
private void checkReferenceType() {
|
||||
switch (opcode.referenceType) {
|
||||
switch (referenceType) {
|
||||
case field:
|
||||
if (!(referencedItem instanceof FieldIdItem)) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
|
@ -263,6 +263,7 @@ public enum Opcode
|
||||
SGET_WIDE_VOLATILE((byte)0xea, "sget-wide-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
||||
SPUT_WIDE_VOLATILE((byte)0xeb, "sput-wide-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
|
||||
THROW_VERIFICATION_ERROR((byte)0xed, "throw-verification-error", ReferenceType.none, Format.Format20bc, Opcode.ODEX_ONLY | Opcode.CAN_THROW),
|
||||
EXECUTE_INLINE((byte)0xee, "execute-inline", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
EXECUTE_INLINE_RANGE((byte)0xef, "execute-inline/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
INVOKE_DIRECT_EMPTY((byte)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
|
@ -32,11 +32,17 @@ import org.jf.dexlib.*;
|
||||
|
||||
public enum ReferenceType
|
||||
{
|
||||
string,
|
||||
type,
|
||||
field,
|
||||
method,
|
||||
none;
|
||||
string(-1),
|
||||
type(0),
|
||||
field(1),
|
||||
method(2),
|
||||
none(-1);
|
||||
|
||||
private int validationErrorReferenceType;
|
||||
|
||||
private ReferenceType(int validationErrorReferenceType) {
|
||||
this.validationErrorReferenceType = validationErrorReferenceType;
|
||||
}
|
||||
|
||||
public boolean checkItem(Item item) {
|
||||
switch (this) {
|
||||
@ -48,9 +54,27 @@ public enum ReferenceType
|
||||
return item instanceof FieldIdItem;
|
||||
case method:
|
||||
return item instanceof MethodIdItem;
|
||||
case none:
|
||||
return item == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ReferenceType fromValidationErrorReferenceType(int validationErrorReferenceType) {
|
||||
switch (validationErrorReferenceType) {
|
||||
case 0:
|
||||
return type;
|
||||
case 1:
|
||||
return field;
|
||||
case 2:
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getValidationErrorReferenceType() {
|
||||
if (validationErrorReferenceType == -1) {
|
||||
throw new RuntimeException("This reference type cannot be referenced from a throw-validation-error" +
|
||||
" instruction");
|
||||
}
|
||||
return validationErrorReferenceType;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2011 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.dexlib.Code;
|
||||
|
||||
public enum VerificationErrorType {
|
||||
None(0, "no-error"),
|
||||
Generic(1, "generic-error"),
|
||||
NoClass(2, "no-such-class"),
|
||||
NoField(3, "no-such-field"),
|
||||
NoMethod(4, "no-such-method"),
|
||||
AccessClass(5, "illegal-class-access"),
|
||||
AccessField(6, "illegal-field-access"),
|
||||
AccessMethod(7, "illegal-method-access"),
|
||||
ClassChange(8, "class-change-error"),
|
||||
Instantiation(9, "instantiation-error");
|
||||
|
||||
private int value;
|
||||
private String name;
|
||||
private VerificationErrorType(int value, String name) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static VerificationErrorType getValidationErrorType(int validationErrorType) {
|
||||
switch (validationErrorType) {
|
||||
case 0:
|
||||
return None;
|
||||
case 1:
|
||||
return Generic;
|
||||
case 2:
|
||||
return NoClass;
|
||||
case 3:
|
||||
return NoField;
|
||||
case 4:
|
||||
return NoMethod;
|
||||
case 5:
|
||||
return AccessClass;
|
||||
case 6:
|
||||
return AccessField;
|
||||
case 7:
|
||||
return AccessMethod;
|
||||
case 8:
|
||||
return ClassChange;
|
||||
case 9:
|
||||
return Instantiation;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user