mirror of
https://github.com/revanced/smali.git
synced 2025-05-04 16:44:25 +02:00
add support for the new odex opcodes for volatile field access that were added in gingerbread
git-svn-id: https://smali.googlecode.com/svn/trunk@799 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
595cdad3d6
commit
d4417d7269
@ -999,6 +999,19 @@ public class MethodAnalyzer {
|
||||
analyzeLiteralBinaryOp(analyzedInstruction, getDestTypeForLiteralShiftRight(analyzedInstruction, false),
|
||||
false);
|
||||
return true;
|
||||
|
||||
/*odexed instructions*/
|
||||
case IGET_VOLATILE:
|
||||
case IPUT_VOLATILE:
|
||||
case SGET_VOLATILE:
|
||||
case SPUT_VOLATILE:
|
||||
case IGET_OBJECT_VOLATILE:
|
||||
case IGET_WIDE_VOLATILE:
|
||||
case IPUT_WIDE_VOLATILE:
|
||||
case SGET_WIDE_VOLATILE:
|
||||
case SPUT_WIDE_VOLATILE:
|
||||
analyzePutGetVolatile(analyzedInstruction);
|
||||
return true;
|
||||
case EXECUTE_INLINE:
|
||||
analyzeExecuteInline(analyzedInstruction);
|
||||
return true;
|
||||
@ -1011,11 +1024,10 @@ public class MethodAnalyzer {
|
||||
case IGET_QUICK:
|
||||
case IGET_WIDE_QUICK:
|
||||
case IGET_OBJECT_QUICK:
|
||||
return analyzeIputIgetQuick(analyzedInstruction, false);
|
||||
case IPUT_QUICK:
|
||||
case IPUT_WIDE_QUICK:
|
||||
case IPUT_OBJECT_QUICK:
|
||||
return analyzeIputIgetQuick(analyzedInstruction, true);
|
||||
return analyzeIputIgetQuick(analyzedInstruction);
|
||||
case INVOKE_VIRTUAL_QUICK:
|
||||
return analyzeInvokeVirtualQuick(analyzedInstruction, false, false);
|
||||
case INVOKE_SUPER_QUICK:
|
||||
@ -1024,6 +1036,11 @@ public class MethodAnalyzer {
|
||||
return analyzeInvokeVirtualQuick(analyzedInstruction, false, true);
|
||||
case INVOKE_SUPER_QUICK_RANGE:
|
||||
return analyzeInvokeVirtualQuick(analyzedInstruction, true, true);
|
||||
case IPUT_OBJECT_VOLATILE:
|
||||
case SGET_OBJECT_VOLATILE:
|
||||
case SPUT_OBJECT_VOLATILE:
|
||||
analyzePutGetVolatile(analyzedInstruction);
|
||||
return true;
|
||||
default:
|
||||
assert false;
|
||||
return true;
|
||||
@ -1486,6 +1503,15 @@ public class MethodAnalyzer {
|
||||
case USHR_INT_LIT8:
|
||||
verifyLiteralBinaryOp(analyzedInstruction);
|
||||
return;
|
||||
case IGET_VOLATILE:
|
||||
case IPUT_VOLATILE:
|
||||
case SGET_VOLATILE:
|
||||
case SPUT_VOLATILE:
|
||||
case IGET_OBJECT_VOLATILE:
|
||||
case IGET_WIDE_VOLATILE:
|
||||
case IPUT_WIDE_VOLATILE:
|
||||
case SGET_WIDE_VOLATILE:
|
||||
case SPUT_WIDE_VOLATILE:
|
||||
case EXECUTE_INLINE:
|
||||
case EXECUTE_INLINE_RANGE:
|
||||
case INVOKE_DIRECT_EMPTY:
|
||||
@ -1499,6 +1525,9 @@ public class MethodAnalyzer {
|
||||
case INVOKE_SUPER_QUICK:
|
||||
case INVOKE_VIRTUAL_QUICK_RANGE:
|
||||
case INVOKE_SUPER_QUICK_RANGE:
|
||||
case IPUT_OBJECT_VOLATILE:
|
||||
case SGET_OBJECT_VOLATILE:
|
||||
case SPUT_OBJECT_VOLATILE:
|
||||
//TODO: throw validation exception?
|
||||
default:
|
||||
assert false;
|
||||
@ -3388,7 +3417,7 @@ public class MethodAnalyzer {
|
||||
analyzeInstruction(analyzedInstruction);
|
||||
}
|
||||
|
||||
private boolean analyzeIputIgetQuick(AnalyzedInstruction analyzedInstruction, boolean isIput) {
|
||||
private boolean analyzeIputIgetQuick(AnalyzedInstruction analyzedInstruction) {
|
||||
Instruction22cs instruction = (Instruction22cs)analyzedInstruction.instruction;
|
||||
|
||||
int fieldOffset = instruction.getFieldOffset();
|
||||
@ -3407,7 +3436,7 @@ public class MethodAnalyzer {
|
||||
|
||||
String fieldType = fieldIdItem.getFieldType().getTypeDescriptor();
|
||||
|
||||
Opcode opcode = getAndCheckIgetIputOpcodeForType(fieldType, instruction.opcode, isIput);
|
||||
Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType, instruction.opcode);
|
||||
|
||||
Instruction22c deodexedInstruction = new Instruction22c(opcode, (byte)instruction.getRegisterA(),
|
||||
(byte)instruction.getRegisterB(), fieldIdItem);
|
||||
@ -3499,87 +3528,33 @@ public class MethodAnalyzer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Opcode getAndCheckIgetIputOpcodeForType(String fieldType, Opcode odexedOpcode, boolean isIput) {
|
||||
Opcode opcode;
|
||||
Opcode validOdexedOpcode;
|
||||
switch (fieldType.charAt(0)) {
|
||||
case 'Z':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_QUICK;
|
||||
opcode = Opcode.IPUT_BOOLEAN;
|
||||
private boolean analyzePutGetVolatile(AnalyzedInstruction analyzedInstruction) {
|
||||
FieldIdItem fieldIdItem =
|
||||
(FieldIdItem)(((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem());
|
||||
|
||||
String fieldType = fieldIdItem.getFieldType().getTypeDescriptor();
|
||||
|
||||
Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType,
|
||||
analyzedInstruction.instruction.opcode);
|
||||
|
||||
Instruction deodexedInstruction;
|
||||
|
||||
if (analyzedInstruction.instruction.opcode.isOdexedStaticVolatile()) {
|
||||
SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
|
||||
|
||||
deodexedInstruction = new Instruction21c(opcode, (byte)instruction.getRegisterA(),
|
||||
fieldIdItem);
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_QUICK;
|
||||
opcode = Opcode.IGET_BOOLEAN;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_QUICK;
|
||||
opcode = Opcode.IPUT_BYTE;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_QUICK;
|
||||
opcode = Opcode.IGET_BYTE;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_QUICK;
|
||||
opcode = Opcode.IPUT_SHORT;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_QUICK;
|
||||
opcode = Opcode.IGET_SHORT;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_QUICK;
|
||||
opcode = Opcode.IPUT_CHAR;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_QUICK;
|
||||
opcode = Opcode.IGET_CHAR;
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
case 'F':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_QUICK;
|
||||
opcode = Opcode.IPUT;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_QUICK;
|
||||
opcode = Opcode.IGET;
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
case 'D':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_WIDE_QUICK;
|
||||
opcode = Opcode.IPUT_WIDE;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_WIDE_QUICK;
|
||||
opcode = Opcode.IGET_WIDE;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
case '[':
|
||||
if (isIput) {
|
||||
validOdexedOpcode = Opcode.IPUT_OBJECT_QUICK;
|
||||
opcode = Opcode.IPUT_OBJECT;
|
||||
} else {
|
||||
validOdexedOpcode = Opcode.IGET_OBJECT_QUICK;
|
||||
opcode = Opcode.IGET_OBJECT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(String.format("Unexpected field type %s for %s: ", fieldType,
|
||||
odexedOpcode.name));
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
|
||||
|
||||
deodexedInstruction = new Instruction22c(opcode, (byte)instruction.getRegisterA(),
|
||||
(byte)instruction.getRegisterB(), fieldIdItem);
|
||||
}
|
||||
|
||||
if (odexedOpcode != validOdexedOpcode) {
|
||||
throw new ValidationException(String.format("Incorrect field type \"%s\" for %s", fieldType,
|
||||
odexedOpcode.name));
|
||||
}
|
||||
analyzedInstruction.setDeodexedInstruction(deodexedInstruction);
|
||||
analyzeInstruction(analyzedInstruction);
|
||||
|
||||
return opcode;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory,
|
||||
|
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 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.Analysis;
|
||||
|
||||
import org.jf.dexlib.Code.Opcode;
|
||||
|
||||
public class OdexedFieldInstructionMapper {
|
||||
private static Opcode[][][][] opcodeMap = new Opcode[][][][] {
|
||||
//get opcodes
|
||||
new Opcode[][][] {
|
||||
//iget quick
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IGET_QUICK,
|
||||
/*B*/ Opcode.IGET_QUICK,
|
||||
/*S*/ Opcode.IGET_QUICK,
|
||||
/*C*/ Opcode.IGET_QUICK,
|
||||
/*I,F*/ Opcode.IGET_QUICK,
|
||||
/*J,D*/ Opcode.IGET_WIDE_QUICK,
|
||||
/*L,[*/ Opcode.IGET_OBJECT_QUICK
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IGET_BOOLEAN,
|
||||
/*B*/ Opcode.IGET_BYTE,
|
||||
/*S*/ Opcode.IGET_SHORT,
|
||||
/*C*/ Opcode.IGET_CHAR,
|
||||
/*I,F*/ Opcode.IGET,
|
||||
/*J,D*/ Opcode.IGET_WIDE,
|
||||
/*L,[*/ Opcode.IGET_OBJECT
|
||||
}
|
||||
},
|
||||
//iget volatile
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IGET_VOLATILE,
|
||||
/*B*/ Opcode.IGET_VOLATILE,
|
||||
/*S*/ Opcode.IGET_VOLATILE,
|
||||
/*C*/ Opcode.IGET_VOLATILE,
|
||||
/*I,F*/ Opcode.IGET_VOLATILE,
|
||||
/*J,D*/ Opcode.IGET_WIDE_VOLATILE,
|
||||
/*L,[*/ Opcode.IGET_OBJECT_VOLATILE
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IGET_BOOLEAN,
|
||||
/*B*/ Opcode.IGET_BYTE,
|
||||
/*S*/ Opcode.IGET_SHORT,
|
||||
/*C*/ Opcode.IGET_CHAR,
|
||||
/*I,F*/ Opcode.IGET,
|
||||
/*J,D*/ Opcode.IGET_WIDE,
|
||||
/*L,[*/ Opcode.IGET_OBJECT
|
||||
}
|
||||
},
|
||||
//sget volatile
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.SGET_VOLATILE,
|
||||
/*B*/ Opcode.SGET_VOLATILE,
|
||||
/*S*/ Opcode.SGET_VOLATILE,
|
||||
/*C*/ Opcode.SGET_VOLATILE,
|
||||
/*I,F*/ Opcode.SGET_VOLATILE,
|
||||
/*J,D*/ Opcode.SGET_WIDE_VOLATILE,
|
||||
/*L,[*/ Opcode.SGET_OBJECT_VOLATILE
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.SGET_BOOLEAN,
|
||||
/*B*/ Opcode.SGET_BYTE,
|
||||
/*S*/ Opcode.SGET_SHORT,
|
||||
/*C*/ Opcode.SGET_CHAR,
|
||||
/*I,F*/ Opcode.SGET,
|
||||
/*J,D*/ Opcode.SGET_WIDE,
|
||||
/*L,[*/ Opcode.SGET_OBJECT
|
||||
}
|
||||
}
|
||||
},
|
||||
//put opcodes
|
||||
new Opcode[][][] {
|
||||
//iput quick
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IPUT_QUICK,
|
||||
/*B*/ Opcode.IPUT_QUICK,
|
||||
/*S*/ Opcode.IPUT_QUICK,
|
||||
/*C*/ Opcode.IPUT_QUICK,
|
||||
/*I,F*/ Opcode.IPUT_QUICK,
|
||||
/*J,D*/ Opcode.IPUT_WIDE_QUICK,
|
||||
/*L,[*/ Opcode.IPUT_OBJECT_QUICK
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IPUT_BOOLEAN,
|
||||
/*B*/ Opcode.IPUT_BYTE,
|
||||
/*S*/ Opcode.IPUT_SHORT,
|
||||
/*C*/ Opcode.IPUT_CHAR,
|
||||
/*I,F*/ Opcode.IPUT,
|
||||
/*J,D*/ Opcode.IPUT_WIDE,
|
||||
/*L,[*/ Opcode.IPUT_OBJECT
|
||||
}
|
||||
},
|
||||
//iput volatile
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IPUT_VOLATILE,
|
||||
/*B*/ Opcode.IPUT_VOLATILE,
|
||||
/*S*/ Opcode.IPUT_VOLATILE,
|
||||
/*C*/ Opcode.IPUT_VOLATILE,
|
||||
/*I,F*/ Opcode.IPUT_VOLATILE,
|
||||
/*J,D*/ Opcode.IPUT_WIDE_VOLATILE,
|
||||
/*L,[*/ Opcode.IPUT_OBJECT_VOLATILE
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.IPUT_BOOLEAN,
|
||||
/*B*/ Opcode.IPUT_BYTE,
|
||||
/*S*/ Opcode.IPUT_SHORT,
|
||||
/*C*/ Opcode.IPUT_CHAR,
|
||||
/*I,F*/ Opcode.IPUT,
|
||||
/*J,D*/ Opcode.IPUT_WIDE,
|
||||
/*L,[*/ Opcode.IPUT_OBJECT
|
||||
}
|
||||
},
|
||||
//sput volatile
|
||||
new Opcode[][] {
|
||||
//odexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.SPUT_VOLATILE,
|
||||
/*B*/ Opcode.SPUT_VOLATILE,
|
||||
/*S*/ Opcode.SPUT_VOLATILE,
|
||||
/*C*/ Opcode.SPUT_VOLATILE,
|
||||
/*I,F*/ Opcode.SPUT_VOLATILE,
|
||||
/*J,D*/ Opcode.SPUT_WIDE_VOLATILE,
|
||||
/*L,[*/ Opcode.SPUT_OBJECT_VOLATILE
|
||||
},
|
||||
//deodexed
|
||||
new Opcode[] {
|
||||
/*Z*/ Opcode.SPUT_BOOLEAN,
|
||||
/*B*/ Opcode.SPUT_BYTE,
|
||||
/*S*/ Opcode.SPUT_SHORT,
|
||||
/*C*/ Opcode.SPUT_CHAR,
|
||||
/*I,F*/ Opcode.SPUT,
|
||||
/*J,D*/ Opcode.SPUT_WIDE,
|
||||
/*L,[*/ Opcode.SPUT_OBJECT
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static int getTypeIndex(char type) {
|
||||
switch (type) {
|
||||
case 'Z':
|
||||
return 0;
|
||||
case 'B':
|
||||
return 1;
|
||||
case 'S':
|
||||
return 2;
|
||||
case 'C':
|
||||
return 3;
|
||||
case 'I':
|
||||
case 'F':
|
||||
return 4;
|
||||
case 'J':
|
||||
case 'D':
|
||||
return 5;
|
||||
case 'L':
|
||||
case '[':
|
||||
return 6;
|
||||
default:
|
||||
}
|
||||
throw new RuntimeException(String.format("Unknown type %s: ", type));
|
||||
}
|
||||
|
||||
private static int getOpcodeSubtype(Opcode opcode) {
|
||||
if (opcode.isOdexedInstanceQuick()) {
|
||||
return 0;
|
||||
} else if (opcode.isOdexedInstanceVolatile()) {
|
||||
return 1;
|
||||
} else if (opcode.isOdexedStaticVolatile()) {
|
||||
return 2;
|
||||
}
|
||||
throw new RuntimeException(String.format("Not an odexed field access opcode: %s", opcode.name));
|
||||
}
|
||||
|
||||
static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(String fieldType, Opcode odexedOpcode) {
|
||||
int opcodeType = odexedOpcode.setsRegister()?0:1;
|
||||
int opcodeSubType = getOpcodeSubtype(odexedOpcode);
|
||||
int typeIndex = getTypeIndex(fieldType.charAt(0));
|
||||
|
||||
Opcode correctOdexedOpcode = opcodeMap[opcodeType][opcodeSubType][0][typeIndex];
|
||||
Opcode deodexedOpcode = opcodeMap[opcodeType][opcodeSubType][1][typeIndex];
|
||||
|
||||
if (correctOdexedOpcode != odexedOpcode) {
|
||||
throw new ValidationException(String.format("Incorrect field type \"%s\" for %s", fieldType,
|
||||
odexedOpcode.name));
|
||||
}
|
||||
|
||||
return deodexedOpcode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,19 +253,33 @@ public enum Opcode
|
||||
SHR_INT_LIT8((byte)0xe1, "shr-int/lit8", ReferenceType.none, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
USHR_INT_LIT8((byte)0xe2, "ushr-int/lit8", ReferenceType.none, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
|
||||
IGET_VOLATILE((byte)0xe3, "iget-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IPUT_VOLATILE((byte)0xe4, "iput-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
SGET_VOLATILE((byte)0xe5, "sget-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
SPUT_VOLATILE((byte)0xe6, "sput-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IGET_OBJECT_VOLATILE((byte)0xe7, "iget-object-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IGET_WIDE_VOLATILE((byte)0xe8, "iget-wide-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
||||
IPUT_WIDE_VOLATILE((byte)0xe9, "iput-wide-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
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),
|
||||
|
||||
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),
|
||||
IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
||||
IGET_OBJECT_QUICK((byte)0xf4, "iget-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IPUT_QUICK((byte)0xf5, "iput-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IPUT_WIDE_QUICK((byte)0xf6, "iput-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IPUT_OBJECT_QUICK((byte)0xf7, "iput-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
||||
IGET_OBJECT_QUICK((byte)0xf4, "iget-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
IPUT_QUICK((byte)0xf5, "iput-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IPUT_WIDE_QUICK((byte)0xf6, "iput-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
IPUT_OBJECT_QUICK((byte)0xf7, "iput-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
INVOKE_VIRTUAL_QUICK((byte)0xf8, "invoke-virtual-quick", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
INVOKE_VIRTUAL_QUICK_RANGE((byte)0xf9, "invoke-virtual-quick/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
INVOKE_SUPER_QUICK((byte)0xfa, "invoke-super-quick", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
INVOKE_SUPER_QUICK_RANGE((byte)0xfb, "invoke-super-quick/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT);
|
||||
INVOKE_SUPER_QUICK_RANGE((byte)0xfb, "invoke-super-quick/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||
|
||||
IPUT_OBJECT_VOLATILE((byte)0xfc, "iput-object-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||
SGET_OBJECT_VOLATILE((byte)0xfd, "sget-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
||||
SPUT_OBJECT_VOLATILE((byte)0xfe, "sput-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE);
|
||||
|
||||
|
||||
private static Opcode[] opcodesByValue;
|
||||
@ -283,6 +297,12 @@ public enum Opcode
|
||||
public static final int SETS_REGISTER = 0x10;
|
||||
//if the instruction sets the value of it's first register to a wide type
|
||||
public static final int SETS_WIDE_REGISTER = 0x20;
|
||||
//if the instruction is an odexed iget-quick/iput-quick instruction
|
||||
public static final int ODEXED_INSTANCE_QUICK = 0x40;
|
||||
//if the instruction is an odexed iget-volatile/iput-volatile instruction
|
||||
public static final int ODEXED_INSTANCE_VOLATILE = 0x80;
|
||||
//if the instruction is an odexed sget-volatile/sput-volatile instruction
|
||||
public static final int ODEXED_STATIC_VOLATILE = 0x100;
|
||||
|
||||
static {
|
||||
opcodesByValue = new Opcode[256];
|
||||
@ -343,4 +363,16 @@ public enum Opcode
|
||||
public final boolean setsWideRegister() {
|
||||
return (flags & SETS_WIDE_REGISTER) != 0;
|
||||
}
|
||||
|
||||
public final boolean isOdexedInstanceQuick() {
|
||||
return (flags & ODEXED_INSTANCE_QUICK) != 0;
|
||||
}
|
||||
|
||||
public final boolean isOdexedInstanceVolatile() {
|
||||
return (flags & ODEXED_INSTANCE_VOLATILE) != 0;
|
||||
}
|
||||
|
||||
public final boolean isOdexedStaticVolatile() {
|
||||
return (flags & ODEXED_STATIC_VOLATILE) != 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user