mirror of
https://github.com/revanced/smali.git
synced 2025-05-09 10:54:29 +02:00
Redid how instructions are handled
git-svn-id: https://smali.googlecode.com/svn/trunk@137 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
0e91ee0cc2
commit
67a4c3cbb2
@ -323,92 +323,92 @@ instruction returns [int size]
|
||||
@init {boolean needsNop = false; int targetCount = 0;}
|
||||
: //e.g. goto endloop:
|
||||
//e.g. goto +3
|
||||
INSTRUCTION_FORMAT10t (LABEL | OFFSET) {$size = Format10t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT10t (LABEL | OFFSET) {$size = Format.Format10t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t LABEL? OFFSET?)
|
||||
| //e.g. return
|
||||
INSTRUCTION_FORMAT10x {$size = Format10x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x)
|
||||
| //e.g. const/4 v0, 5
|
||||
INSTRUCTION_FORMAT11n REGISTER integral_literal {$size = Format11n.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT11n REGISTER integral_literal {$size = Format.Format11n.size;}
|
||||
-> ^(I_STATEMENT_FORMAT11n[$start, "I_STARTMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal)
|
||||
| //e.g. move-result-object v1
|
||||
INSTRUCTION_FORMAT11x REGISTER {$size = Format11x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER)
|
||||
| //e.g. move v1 v2
|
||||
INSTRUCTION_FORMAT12x REGISTER REGISTER {$size = Format12x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT12x REGISTER REGISTER {$size = Format.Format12x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] INSTRUCTION_FORMAT12x REGISTER REGISTER)
|
||||
| //e.g. goto/16 endloop:
|
||||
INSTRUCTION_FORMAT20t (LABEL | OFFSET) {$size = Format20t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT20t (LABEL | OFFSET) {$size = Format.Format20t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t LABEL? OFFSET?)
|
||||
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
||||
INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field {$size = Format21c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field {$size = Format.Format21c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
||||
| //e.g. const-string v1 "Hello World!"
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL {$size = Format21c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL {$size = Format.Format21c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL)
|
||||
| //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor {$size = Format21c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor {$size = Format.Format21c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||
| //e.g. const/high16 v1, 1234
|
||||
INSTRUCTION_FORMAT21h REGISTER integral_literal {$size = Format21h.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21h REGISTER integral_literal {$size = Format.Format21h.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal)
|
||||
| //e.g. const/16 v1, 1234
|
||||
INSTRUCTION_FORMAT21s REGISTER integral_literal {$size = Format21s.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21s REGISTER integral_literal {$size = Format.Format21s.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal)
|
||||
| //e.g. if-eqz v0, endloop:
|
||||
INSTRUCTION_FORMAT21t REGISTER (LABEL | OFFSET) {$size = Format21t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT21t REGISTER (LABEL | OFFSET) {$size = Format.Format21t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER LABEL? OFFSET?)
|
||||
| //e.g. add-int v0, v1, 123
|
||||
INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal {$size = Format22b.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal {$size = Format.Format22b.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal)
|
||||
| //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
|
||||
INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field {$size = Format22c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field {$size = Format.Format22c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field)
|
||||
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor {$size = Format22c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor {$size = Format.Format22c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor)
|
||||
| //e.g. add-int/lit16 v0, v1, 12345
|
||||
INSTRUCTION_FORMAT22s REGISTER REGISTER integral_literal {$size = Format22s.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22s REGISTER REGISTER integral_literal {$size = Format.Format22s.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] INSTRUCTION_FORMAT22s REGISTER REGISTER integral_literal)
|
||||
| //e.g. if-eq v0, v1, endloop:
|
||||
INSTRUCTION_FORMAT22t REGISTER REGISTER (LABEL | OFFSET) {$size = Format22t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22t REGISTER REGISTER (LABEL | OFFSET) {$size = Format.Format22t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER LABEL? OFFSET?)
|
||||
| //e.g. move/from16 v1, v1234
|
||||
INSTRUCTION_FORMAT22x REGISTER REGISTER {$size = Format22x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT22x REGISTER REGISTER {$size = Format.Format22x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER)
|
||||
| //e.g. add-int v1, v2, v3
|
||||
INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER {$size = Format23x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER {$size = Format.Format23x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER)
|
||||
| //e.g. goto/32 endloop:
|
||||
INSTRUCTION_FORMAT30t (LABEL | OFFSET) {$size = Format30t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT30t (LABEL | OFFSET) {$size = Format.Format30t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t LABEL? OFFSET?)
|
||||
| //e.g. const-string/jumbo v1 "Hello World!"
|
||||
INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL {$size = Format31c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL {$size = Format.Format31c.size;}
|
||||
->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL)
|
||||
| //e.g. const v0, 123456
|
||||
INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal {$size = Format31i.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal {$size = Format.Format31i.size;}
|
||||
-> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
||||
| //e.g. fill-array-data v0, ArrayData:
|
||||
INSTRUCTION_FORMAT31t REGISTER (LABEL | OFFSET) {$size = Format31t.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT31t REGISTER (LABEL | OFFSET) {$size = Format.Format31t.size;}
|
||||
-> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER LABEL? OFFSET?)
|
||||
| //e.g. move/16 v4567, v1234
|
||||
INSTRUCTION_FORMAT32x REGISTER REGISTER {$size = Format32x.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT32x REGISTER REGISTER {$size = Format.Format32x.size;}
|
||||
-> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER)
|
||||
| //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
|
||||
INSTRUCTION_FORMAT35c_METHOD OPEN_BRACKET register_list CLOSE_BRACKET fully_qualified_method {$size = Format35c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT35c_METHOD OPEN_BRACKET register_list CLOSE_BRACKET fully_qualified_method {$size = Format.Format35c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method)
|
||||
| //e.g. filled-new-array {v0,v1}, I
|
||||
INSTRUCTION_FORMAT35c_TYPE OPEN_BRACKET register_list CLOSE_BRACKET nonvoid_type_descriptor {$size = Format35c.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT35c_TYPE OPEN_BRACKET register_list CLOSE_BRACKET nonvoid_type_descriptor {$size = Format.Format35c.size;}
|
||||
-> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor)
|
||||
| //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACKET register_range CLOSE_BRACKET fully_qualified_method {$size = Format3rc.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACKET register_range CLOSE_BRACKET fully_qualified_method {$size = Format.Format3rc.size;}
|
||||
-> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method)
|
||||
| //e.g. filled-new-array/range {v0..v6} I
|
||||
INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACKET register_range CLOSE_BRACKET nonvoid_type_descriptor {$size = Format3rc.Format.getByteCount();}
|
||||
INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACKET register_range CLOSE_BRACKET nonvoid_type_descriptor {$size = Format.Format3rc.size;}
|
||||
-> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor)
|
||||
| //e.g. const-wide v0, 5000000000L
|
||||
INSTRUCTION_FORMAT51l REGISTER fixed_literal {$size = Format51l.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal)
|
||||
INSTRUCTION_FORMAT51l REGISTER fixed_literal {$size = Format.Format51l.size;}
|
||||
-> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal)
|
||||
|
|
||||
ARRAY_DATA_DIRECTIVE
|
||||
{
|
||||
|
@ -401,7 +401,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
||||
annotations
|
||||
)
|
||||
{
|
||||
ArrayList<Instruction> instructions = $statements.instructions;
|
||||
ArrayList<InstructionField> instructions = $statements.instructions;
|
||||
|
||||
Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(dexFile);
|
||||
List<CodeItem.TryItem> tries = temp.first;
|
||||
@ -640,16 +640,16 @@ source
|
||||
$method::debugInfo.addSetFile($address.address, $string_literal.value);
|
||||
};
|
||||
|
||||
statements[int totalMethodRegisters, int methodParameterRegisters] returns[ArrayList<Instruction> instructions]
|
||||
statements[int totalMethodRegisters, int methodParameterRegisters] returns[ArrayList<InstructionField> instructions]
|
||||
@init
|
||||
{
|
||||
$instructions = new ArrayList<Instruction>();
|
||||
$instructions = new ArrayList<InstructionField>();
|
||||
}
|
||||
: ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters]
|
||||
{
|
||||
if ($instruction.instruction != null) {
|
||||
$instructions.add($instruction.instruction);
|
||||
$method::currentAddress += $instruction.instruction.getBytes().length/2;
|
||||
$method::currentAddress += $instruction.instruction.getSize($method::currentAddress) / 2;
|
||||
}
|
||||
})*);
|
||||
|
||||
@ -690,7 +690,7 @@ offset_or_label returns[int offsetValue]
|
||||
: offset {$offsetValue = $offset.offsetValue;}
|
||||
| label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
|
||||
|
||||
instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Instruction instruction]
|
||||
instruction[int totalMethodRegisters, int methodParameterRegisters] returns[InstructionField instruction]
|
||||
: //e.g. goto endloop:
|
||||
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
|
||||
{
|
||||
@ -702,13 +702,13 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127].");
|
||||
}
|
||||
|
||||
$instruction = Format10t.Format.make(dexFile, opcode.value, (byte)addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction10t(dexFile, opcode, (byte)addressOffset));
|
||||
}
|
||||
| //e.g. return
|
||||
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
||||
{
|
||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
|
||||
$instruction = Format10x.Format.make(dexFile, opcode.value);
|
||||
$instruction = new InstructionField(dexFile, new Instruction10x(dexFile, opcode));
|
||||
}
|
||||
| //e.g. const/4 v0, 5
|
||||
^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
|
||||
@ -719,7 +719,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
short litB = $short_integral_literal.value;
|
||||
literalTools.checkNibble(litB);
|
||||
|
||||
$instruction = Format11n.Format.make(dexFile, opcode.value, regA, (byte)litB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction11n(dexFile, opcode, regA, (byte)litB));
|
||||
}
|
||||
| //e.g. move-result-object v1
|
||||
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
|
||||
@ -727,7 +727,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
|
||||
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
|
||||
$instruction = Format11x.Format.make(dexFile, opcode.value, regA);
|
||||
$instruction = new InstructionField(dexFile, new Instruction11x(dexFile, opcode, regA));
|
||||
}
|
||||
| //e.g. move v1 v2
|
||||
^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
|
||||
@ -736,7 +736,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
|
||||
$instruction = Format12x.Format.make(dexFile, opcode.value, regA, regB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction12x(dexFile, opcode, regA, regB));
|
||||
}
|
||||
| //e.g. goto/16 endloop:
|
||||
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label)
|
||||
@ -749,7 +749,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||
}
|
||||
|
||||
$instruction = Format20t.Format.make(dexFile, opcode.value, (short)addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction20t(dexFile, opcode, (short)addressOffset));
|
||||
}
|
||||
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
||||
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
||||
@ -759,7 +759,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
||||
|
||||
$instruction = Format21c.Format.make(dexFile, opcode.value, regA, fieldIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, fieldIdItem));
|
||||
}
|
||||
| //e.g. const-string v1 "Hello World!"
|
||||
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
|
||||
@ -769,7 +769,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
|
||||
|
||||
$instruction = Format21c.Format.make(dexFile, opcode.value, regA, stringIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, stringIdItem));
|
||||
}
|
||||
| //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2
|
||||
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||
@ -779,7 +779,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
TypeIdItem typeIdItem = $reference_type_descriptor.type;
|
||||
|
||||
$instruction = Format21c.Format.make(dexFile, opcode.value, regA, typeIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, typeIdItem));
|
||||
}
|
||||
| //e.g. const/high16 v1, 1234
|
||||
^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal)
|
||||
@ -789,7 +789,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
short litB = $short_integral_literal.value;
|
||||
|
||||
$instruction = Format21h.Format.make(dexFile, opcode.value, regA, litB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21h(dexFile, opcode, regA, litB));
|
||||
}
|
||||
| //e.g. const/16 v1, 1234
|
||||
^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
|
||||
@ -799,7 +799,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
short litB = $short_integral_literal.value;
|
||||
|
||||
$instruction = Format21s.Format.make(dexFile, opcode.value, regA, litB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21s(dexFile, opcode, regA, litB));
|
||||
}
|
||||
| //e.g. if-eqz v0, endloop:
|
||||
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label)
|
||||
@ -813,7 +813,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||
}
|
||||
|
||||
$instruction = Format21t.Format.make(dexFile, opcode.value, regA, (short)addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction21t(dexFile, opcode, regA, (short)addressOffset));
|
||||
}
|
||||
| //e.g. add-int v0, v1, 123
|
||||
^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||
@ -825,7 +825,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
short litC = $short_integral_literal.value;
|
||||
literalTools.checkByte(litC);
|
||||
|
||||
$instruction = Format22b.Format.make(dexFile, opcode.value, regA, regB, (byte)litC);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22b(dexFile, opcode, regA, regB, (byte)litC));
|
||||
}
|
||||
| //e.g. iput-object v1 v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
|
||||
^(I_STATEMENT_FORMAT22c_FIELD INSTRUCTION_FORMAT22c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field)
|
||||
@ -836,7 +836,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
||||
|
||||
$instruction = Format22c.Format.make(dexFile, opcode.value, regA, regB, fieldIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22c(dexFile, opcode, regA, regB, fieldIdItem));
|
||||
}
|
||||
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
|
||||
@ -847,7 +847,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||
|
||||
$instruction = Format22c.Format.make(dexFile, opcode.value, regA, regB, typeIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22c(dexFile, opcode, regA, regB, typeIdItem));
|
||||
}
|
||||
| //e.g. add-int/lit16 v0, v1, 12345
|
||||
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||
@ -858,7 +858,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
short litC = $short_integral_literal.value;
|
||||
|
||||
$instruction = Format22s.Format.make(dexFile, opcode.value, regA, regB, litC);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22s(dexFile, opcode, regA, regB, litC));
|
||||
}
|
||||
| //e.g. if-eq v0, v1, endloop:
|
||||
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label)
|
||||
@ -873,7 +873,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||
}
|
||||
|
||||
$instruction = Format22t.Format.make(dexFile, opcode.value, regA, regB, (short)addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22t(dexFile, opcode, regA, regB, (short)addressOffset));
|
||||
}
|
||||
| //e.g. move/from16 v1, v1234
|
||||
^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
|
||||
@ -882,7 +882,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
|
||||
$instruction = Format22x.Format.make(dexFile, opcode.value, regA, regB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction22x(dexFile, opcode, regA, regB));
|
||||
}
|
||||
| //e.g. add-int v1, v2, v3
|
||||
^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
|
||||
@ -892,7 +892,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
|
||||
$instruction = Format23x.Format.make(dexFile, opcode.value, regA, regB, regC);
|
||||
$instruction = new InstructionField(dexFile, new Instruction23x(dexFile, opcode, regA, regB, regC));
|
||||
}
|
||||
| //e.g. goto/32 endloop:
|
||||
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label)
|
||||
@ -901,7 +901,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
int addressOffset = $offset_or_label.offsetValue;
|
||||
|
||||
$instruction = Format30t.Format.make(dexFile, opcode.value, addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction30t(dexFile, opcode, addressOffset));
|
||||
}
|
||||
| //e.g. const-string/jumbo v1 "Hello World!"
|
||||
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
|
||||
@ -911,7 +911,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
|
||||
|
||||
$instruction = Format31c.Format.make(dexFile, opcode.value, regA, stringIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction31c(dexFile, opcode, regA, stringIdItem));
|
||||
}
|
||||
| //e.g. const v0, 123456
|
||||
^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
||||
@ -921,7 +921,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
int litB = $fixed_32bit_literal.value;
|
||||
|
||||
$instruction = Format31i.Format.make(dexFile, opcode.value, regA, litB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction31i(dexFile, opcode, regA, litB));
|
||||
}
|
||||
| //e.g. fill-array-data v0, ArrayData:
|
||||
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label)
|
||||
@ -935,7 +935,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
addressOffset++;
|
||||
}
|
||||
|
||||
$instruction = Format31t.Format.make(dexFile, opcode.value, regA, addressOffset);
|
||||
$instruction = new InstructionField(dexFile, new Instruction31t(dexFile, opcode, regA, addressOffset));
|
||||
}
|
||||
| //e.g. move/16 v5678, v1234
|
||||
^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
|
||||
@ -944,7 +944,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||
|
||||
$instruction = Format32x.Format.make(dexFile, opcode.value, regA, regB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction32x(dexFile, opcode, regA, regB));
|
||||
}
|
||||
| //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
|
||||
^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
||||
@ -957,7 +957,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
||||
|
||||
$instruction = Format35c.Format.make(dexFile, opcode.value, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction35c(dexFile, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem));
|
||||
}
|
||||
| //e.g. filled-new-array {v0,v1}, I
|
||||
^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
||||
@ -970,7 +970,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||
|
||||
$instruction = Format35c.Format.make(dexFile, opcode.value, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction35c(dexFile, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem));
|
||||
}
|
||||
| //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
||||
@ -990,7 +990,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
||||
|
||||
//not supported yet
|
||||
$instruction = Format3rc.Format.make(dexFile, opcode.value, (short)registerCount, startRegister, methodIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction3rc(dexFile, opcode, (short)registerCount, startRegister, methodIdItem));
|
||||
}
|
||||
| //e.g. filled-new-array/range {v0..v6} I
|
||||
^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
||||
@ -1010,7 +1010,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||
|
||||
//not supported yet
|
||||
$instruction = Format3rc.Format.make(dexFile, opcode.value, (short)registerCount, startRegister, typeIdItem);
|
||||
$instruction = new InstructionField(dexFile, new Instruction3rc(dexFile, opcode, (short)registerCount, startRegister, typeIdItem));
|
||||
}
|
||||
| //e.g. const-wide v0, 5000000000L
|
||||
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
|
||||
@ -1020,7 +1020,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
|
||||
long litB = $fixed_64bit_literal.value;
|
||||
|
||||
$instruction = Format51l.Format.make(dexFile, opcode.value, regA, litB);
|
||||
$instruction = new InstructionField(dexFile, new Instruction51l(dexFile, opcode, regA, litB));
|
||||
}
|
||||
| //e.g. .array-data 4 1000000 .end array-data
|
||||
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
|
||||
@ -1028,7 +1028,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
int elementWidth = $short_integral_literal.value;
|
||||
List<byte[]> byteValues = $array_elements.values;
|
||||
|
||||
$instruction = ArrayData.make(dexFile, elementWidth, byteValues);
|
||||
$instruction = new InstructionField(dexFile, new ArrayDataPseudoInstruction(dexFile, elementWidth, byteValues));
|
||||
}
|
||||
|
|
||||
|
||||
@ -1037,7 +1037,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
int startKey = $fixed_32bit_literal.value;
|
||||
int[] targets = $packed_switch_targets.targets;
|
||||
|
||||
$instruction = PackedSwitchData.make(dexFile, startKey, targets);
|
||||
$instruction = new InstructionField(dexFile, new PackedSwitchDataPseudoInstruction(dexFile, startKey, targets));
|
||||
}
|
||||
|
|
||||
^(I_STATEMENT_SPARSE_SWITCH ^(I_SPARSE_SWITCH_BASE_OFFSET base_offset=offset_or_label) sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount] sparse_switch_targets[$base_offset.offsetValue, $sparse_switch_target_count.targetCount])
|
||||
@ -1045,7 +1045,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
||||
int[] keys = $sparse_switch_keys.keys;
|
||||
int[] targets = $sparse_switch_targets.targets;
|
||||
|
||||
$instruction = SparseSwitchData.make(dexFile, keys, targets);
|
||||
$instruction = new InstructionField(dexFile, new SparseSwitchDataPseudoInstruction(dexFile, keys, targets));
|
||||
};
|
||||
catch [Exception ex] {
|
||||
reportError(new SemanticException(input, ex));
|
||||
|
@ -30,6 +30,7 @@ package org.jf.dexlib;
|
||||
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.code.InstructionField;
|
||||
import org.jf.dexlib.ItemType;
|
||||
import org.jf.dexlib.util.Input;
|
||||
import org.jf.dexlib.util.AnnotatedOutput;
|
||||
@ -39,7 +40,7 @@ import java.util.List;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
private final ArrayList<Instruction> instructionList;
|
||||
private final ArrayList<InstructionField> instructionList;
|
||||
private final ArrayList<TryItem> tryItems = new ArrayList<TryItem>();
|
||||
private final ArrayList<EncodedCatchHandler> catchHandlerList = new ArrayList<EncodedCatchHandler>();
|
||||
|
||||
@ -57,7 +58,7 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
public CodeItem(final DexFile dexFile, int offset) {
|
||||
super(offset);
|
||||
|
||||
instructionList = new ArrayList<Instruction>();
|
||||
instructionList = new ArrayList<InstructionField>();
|
||||
|
||||
fields = new Field[] {
|
||||
registersCountField = new ShortIntegerField("registers_size"),
|
||||
@ -82,7 +83,7 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
public CodeItem(final DexFile dexFile,
|
||||
int registersCount,
|
||||
int inArguments,
|
||||
List<Instruction> instructions,
|
||||
List<InstructionField> instructions,
|
||||
DebugInfoItem debugInfo,
|
||||
List<TryItem> tries,
|
||||
List<EncodedCatchHandler> handlers) {
|
||||
@ -447,7 +448,7 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
|
||||
public void writeTo(AnnotatedOutput out) {
|
||||
int startPosition = out.getCursor();
|
||||
for (Instruction instruction: instructionList) {
|
||||
for (InstructionField instruction: instructionList) {
|
||||
instruction.writeTo(out);
|
||||
}
|
||||
if ((out.getCursor() - startPosition) != (instructionsSizeField.getCachedValue() * 2)) {
|
||||
@ -460,7 +461,7 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
int startPosition = in.getCursor();
|
||||
|
||||
do {
|
||||
Instruction instruction = new Instruction(dexFile);
|
||||
InstructionField instruction = new InstructionField(dexFile);
|
||||
instruction.readFrom(in);
|
||||
instructionList.add(instruction);
|
||||
} while (in.getCursor() - startPosition < numBytes);
|
||||
@ -475,23 +476,23 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
}
|
||||
|
||||
public void copyTo(DexFile dexFile, InstructionListField copy) {
|
||||
ArrayList<Instruction> copyInstructionList = copy.getInstructionList();
|
||||
ArrayList<InstructionField> copyInstructionList = copy.getInstructionList();
|
||||
copyInstructionList.clear();
|
||||
for (Instruction instruction: instructionList) {
|
||||
Instruction instructionCopy = new Instruction(dexFile);
|
||||
for (InstructionField instruction: instructionList) {
|
||||
InstructionField instructionCopy = new InstructionField(dexFile);
|
||||
instruction.copyTo(dexFile, instructionCopy);
|
||||
copyInstructionList.add(instructionCopy);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Instruction> getInstructionList() {
|
||||
private ArrayList<InstructionField> getInstructionList() {
|
||||
return instructionList;
|
||||
}
|
||||
|
||||
//return the word size of the instruction list
|
||||
public int getInstructionWordCount() {
|
||||
int bytes = 0;
|
||||
for (Instruction instruction: instructionList) {
|
||||
for (InstructionField instruction: instructionList) {
|
||||
bytes += instruction.getSize(bytes);
|
||||
}
|
||||
return bytes/2;
|
||||
@ -500,11 +501,11 @@ public class CodeItem extends OffsettedItem<CodeItem> {
|
||||
//return the highest parameter word count of any method invokation
|
||||
public int getOutArguments() {
|
||||
int maxParamWordCount = 0;
|
||||
for (Instruction instruction: instructionList) {
|
||||
IndexedItem item = instruction.getReference();
|
||||
for (InstructionField instruction: instructionList) {
|
||||
IndexedItem item = instruction.getInstruction().getReferencedItem();
|
||||
if (item instanceof MethodIdItem) {
|
||||
MethodIdItem methodIdItem = (MethodIdItem)item;
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
Opcode opcode = instruction.getInstruction().getOpcode();
|
||||
|
||||
boolean isStatic = false;
|
||||
if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) {
|
||||
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayData
|
||||
{
|
||||
public static Instruction make(DexFile dexFile, int elementWidth, List<byte[]> values) {
|
||||
byte[] bytes;
|
||||
|
||||
int byteCount = 0;
|
||||
|
||||
for (byte[] value: values) {
|
||||
byteCount += value.length;
|
||||
}
|
||||
|
||||
if (byteCount % elementWidth != 0) {
|
||||
throw new RuntimeException("There are not a whole number of " + ((Integer)elementWidth).toString() + " byte elements");
|
||||
}
|
||||
|
||||
bytes = new byte[byteCount+8];
|
||||
int position = 8;
|
||||
|
||||
for (byte[] value: values) {
|
||||
for (byte byteValue: value) {
|
||||
bytes[position++] = byteValue;
|
||||
}
|
||||
}
|
||||
|
||||
//fill-array-data psuedo-opcode
|
||||
bytes[0] = 0x00;
|
||||
bytes[1] = 0x03;
|
||||
|
||||
bytes[2] = (byte)elementWidth;
|
||||
bytes[3] = (byte)(elementWidth >> 8);
|
||||
|
||||
int elementCount = byteCount / elementWidth;
|
||||
|
||||
bytes[4] = (byte)elementCount;
|
||||
bytes[5] = (byte)(elementCount >> 8);
|
||||
bytes[6] = (byte)(elementCount >> 16);
|
||||
bytes[7] = (byte)(elementCount >> 24);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.Input;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ArrayDataPseudoInstruction extends Instruction
|
||||
{
|
||||
public ArrayDataPseudoInstruction(DexFile dexFile, int elementWidth, List<byte[]> values) {
|
||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||
|
||||
int byteCount = 0;
|
||||
|
||||
for (byte[] value: values) {
|
||||
byteCount += value.length;
|
||||
}
|
||||
|
||||
if (byteCount % elementWidth != 0) {
|
||||
throw new RuntimeException("There are not a whole number of " + ((Integer)elementWidth).toString() + " byte elements");
|
||||
}
|
||||
|
||||
int elementCount = byteCount / elementWidth;
|
||||
|
||||
encodedInstruction = new byte[byteCount+8];
|
||||
encodedInstruction[0] = 0x00;
|
||||
encodedInstruction[1] = 0x03; //fill-array-data psuedo-opcode
|
||||
|
||||
encodedInstruction[2] = (byte)elementWidth;
|
||||
encodedInstruction[3] = (byte)(elementWidth >> 8);
|
||||
|
||||
encodedInstruction[4] = (byte)elementCount;
|
||||
encodedInstruction[5] = (byte)(elementCount >> 8);
|
||||
encodedInstruction[6] = (byte)(elementCount >> 16);
|
||||
encodedInstruction[7] = (byte)(elementCount >> 24);
|
||||
|
||||
int position = 8;
|
||||
|
||||
for (byte[] value: values) {
|
||||
for (byte byteValue: value) {
|
||||
encodedInstruction[position++] = byteValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayDataPseudoInstruction() {
|
||||
}
|
||||
|
||||
protected void checkFormat(Format format) {
|
||||
//no need to check the format
|
||||
}
|
||||
|
||||
public static ArrayDataPseudoInstruction make(DexFile dexFile, Input input) {
|
||||
byte opcodeByte = input.readByte();
|
||||
if (opcodeByte != 0x00) {
|
||||
throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction");
|
||||
}
|
||||
byte subopcodeByte = input.readByte();
|
||||
if (subopcodeByte != 0x02) {
|
||||
throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction");
|
||||
}
|
||||
|
||||
int elementWidth = input.readShort();
|
||||
int size = input.readInt();
|
||||
|
||||
List<byte[]> elementsList = new ArrayList<byte[]>();
|
||||
|
||||
for (int i=0; i<size; i++) {
|
||||
elementsList.add(input.readBytes(elementWidth));
|
||||
}
|
||||
|
||||
return new ArrayDataPseudoInstruction(dexFile, elementWidth, elementsList);
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.ArrayData;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new ArrayDataPseudoInstruction();
|
||||
}
|
||||
}
|
@ -28,16 +28,43 @@
|
||||
|
||||
package org.jf.dexlib.code.Format;
|
||||
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
|
||||
public abstract class Format
|
||||
public enum Format
|
||||
{
|
||||
public abstract int getByteCount();
|
||||
public abstract String getFormatName();
|
||||
Format10t(Instruction10t.Factory, 2),
|
||||
Format10x(Instruction10x.Factory, 2),
|
||||
Format11n(Instruction11n.Factory, 2),
|
||||
Format11x(Instruction11x.Factory, 2),
|
||||
Format12x(Instruction12x.Factory, 2),
|
||||
Format20t(Instruction20t.Factory, 4),
|
||||
Format21c(Instruction21c.Factory, 4),
|
||||
Format21h(Instruction21h.Factory, 4),
|
||||
Format21s(Instruction21s.Factory, 4),
|
||||
Format21t(Instruction21t.Factory, 4),
|
||||
Format22b(Instruction22b.Factory, 4),
|
||||
Format22c(Instruction22c.Factory, 4),
|
||||
Format22s(Instruction22s.Factory, 4),
|
||||
Format22t(Instruction22t.Factory, 4),
|
||||
Format22x(Instruction22x.Factory, 4),
|
||||
Format23x(Instruction23x.Factory, 4),
|
||||
Format30t(Instruction30t.Factory, 6),
|
||||
Format31c(Instruction31c.Factory, 6),
|
||||
Format31i(Instruction31i.Factory, 6),
|
||||
Format31t(Instruction31t.Factory, 6),
|
||||
Format32x(Instruction32x.Factory, 6),
|
||||
Format35c(Instruction35c.Factory, 6),
|
||||
Format3rc(Instruction3rc.Factory, 6),
|
||||
Format51l(Instruction51l.Factory, 10),
|
||||
ArrayData(null, -1),
|
||||
PackedSwitchData(null, -1),
|
||||
SparseSwitchData(null, -1);
|
||||
|
||||
protected void checkOpcodeFormat(Opcode opcode) {
|
||||
if (!opcode.format.equals(getFormatName())) {
|
||||
throw new RuntimeException("Opcode " + opcode.name + " does not use format " + getFormatName());
|
||||
}
|
||||
public final Instruction.InstructionFactory Factory;
|
||||
public final int size;
|
||||
|
||||
private Format(Instruction.InstructionFactory factory, int size) {
|
||||
this.Factory = factory;
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class Format10x extends Format
|
||||
{
|
||||
public static final Format10x Format = new Format10x();
|
||||
|
||||
private Format10x() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode) {
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
return new Instruction(dexFile, new byte[]{opcode,0x00}, null);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "10x";
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class Format30t extends Format
|
||||
{
|
||||
public static final Format30t Format = new Format30t();
|
||||
|
||||
private Format30t() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, int offA) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[2] = (byte)offA;
|
||||
bytes[3] = (byte)(offA >> 8);
|
||||
bytes[4] = (byte)(offA >> 16);
|
||||
bytes[5] = (byte)(offA >> 24);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "30t";
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class Format31t extends Format
|
||||
{
|
||||
public static final Format31t Format = new Format31t();
|
||||
|
||||
private Format31t() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, int offB) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
|
||||
bytes[2] = (byte)offB;
|
||||
bytes[3] = (byte)(offB >> 8);
|
||||
|
||||
bytes[4] = (byte)(offB >> 16);
|
||||
bytes[5] = (byte)(offB >> 24);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "31t";
|
||||
}
|
||||
}
|
@ -31,33 +31,51 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
|
||||
public class Format10t extends Format
|
||||
public class Instruction10t extends Instruction
|
||||
{
|
||||
public static final Format10t Format = new Format10t();
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format10t() {
|
||||
}
|
||||
public Instruction10t(DexFile dexFile, Opcode opcode, byte offA) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte offA) {
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (offA == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
return new Instruction(dexFile, new byte[]{opcode,offA}, null);
|
||||
encodedInstruction = new byte[2];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = offA;
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 2;
|
||||
private Instruction10t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (getOffset() == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "10t";
|
||||
private Instruction10t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format10t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction10t();
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction10t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getOffset() {
|
||||
return encodedInstruction[1];
|
||||
}
|
||||
}
|
@ -32,41 +32,40 @@ import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
|
||||
public class Format21c extends Format
|
||||
public class Instruction10x extends Instruction
|
||||
{
|
||||
public static final Format21c Format = new Format21c();
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public Instruction10x(DexFile dexFile, Opcode opcode) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
encodedInstruction = new byte[2];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
}
|
||||
|
||||
public Instruction10x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (rest[0] != 0x00) {
|
||||
throw new RuntimeException("The second byte of the instruction must be 0");
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction10x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format10x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction10x();
|
||||
}
|
||||
|
||||
private Format21c() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, IndexedItem item) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction10x(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
if (opcode == Opcode.NEW_INSTANCE.value && ((TypeIdItem)item).getTypeDescriptor().charAt(0) != 'L') {
|
||||
throw new RuntimeException("Only class references can be used with the new-instance opcode");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
|
||||
return new Instruction(dexFile, bytes, item);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "21c";
|
||||
}
|
||||
}
|
||||
}
|
@ -31,21 +31,15 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format11n extends Format
|
||||
public class Instruction11n extends Instruction
|
||||
{
|
||||
public static final Format11n Format = new Format11n();
|
||||
|
||||
private Format11n() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte litB) {
|
||||
byte[] bytes = new byte[2];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public Instruction11n(DexFile dexFile, Opcode opcode, byte regA, byte litB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
@ -55,21 +49,39 @@ public class Format11n extends Format
|
||||
litB >= 1<<3) {
|
||||
throw new RuntimeException("The literal value must be between -8 and 7 inclusive");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((litB << 4) | regA);
|
||||
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
|
||||
encodedInstruction = new byte[2];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((litB << 4) | regA);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 2;
|
||||
private Instruction11n(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "11n";
|
||||
private Instruction11n() {
|
||||
}
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format11n;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction11n();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction11n(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getRegister() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getLiteral() {
|
||||
return NumberUtils.decodeHighSignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -32,36 +32,47 @@ import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format31c extends Format
|
||||
public class Instruction11x extends Instruction
|
||||
{
|
||||
public static final Format31c Format = new Format31c();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format31c() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, IndexedItem item) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction11x(DexFile dexFile, Opcode opcode, short regA) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
|
||||
return new Instruction(dexFile, bytes, item);
|
||||
encodedInstruction = new byte[2];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
private Instruction11x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "31c";
|
||||
private Instruction11x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format11x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction11x();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction11x(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -32,38 +32,52 @@ import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format22c extends Format
|
||||
public class Instruction12x extends Instruction
|
||||
{
|
||||
public static final Format22c Format = new Format22c();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format22c() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB, IndexedItem item) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction12x(DexFile dexFile, Opcode opcode, byte regA, byte regB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<4 ||
|
||||
regB >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((regB << 4) | regA);
|
||||
|
||||
return new Instruction(dexFile, bytes, item);
|
||||
encodedInstruction = new byte[2];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((regB << 4) | regA);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
private Instruction12x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "22c";
|
||||
private Instruction12x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format12x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction12x();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction12x(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getRegisterA() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getRegisterB() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -31,39 +31,53 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format20t extends Format
|
||||
public class Instruction20t extends Instruction
|
||||
{
|
||||
public static final Format20t Format = new Format20t();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format20t() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short offA) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction20t(DexFile dexFile, Opcode opcode, short offA) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (offA == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[2] = (byte)offA;
|
||||
bytes[3] = (byte)(offA >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[2] = (byte)offA;
|
||||
encodedInstruction[3] = (byte)(offA>>8);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 4;
|
||||
private Instruction20t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (getOffset() == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "20t";
|
||||
private Instruction20t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format20t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction20t();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction20t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getOffset() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
88
src/main/java/org/jf/dexlib/code/Format/Instruction21c.java
Normal file
88
src/main/java/org/jf/dexlib/code/Format/Instruction21c.java
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Instruction21c extends Instruction
|
||||
{
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
public Instruction21c(DexFile dexFile, Opcode opcode, short regA, IndexedItem item) {
|
||||
super(dexFile, opcode, item);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
if (opcode == Opcode.NEW_INSTANCE && ((TypeIdItem)item).getTypeDescriptor().charAt(0) != 'L') {
|
||||
throw new RuntimeException("Only class references can be used with the new-instance opcode");
|
||||
}
|
||||
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
//the item index will be set later, during placement/writing
|
||||
}
|
||||
|
||||
private Instruction21c(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (opcode == Opcode.NEW_INSTANCE && ((TypeIdItem)this.getReferencedItem()).getTypeDescriptor().charAt(0) != 'L') {
|
||||
throw new RuntimeException("Only class references can be used with the new-instance opcode");
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction21c() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format21c;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction21c();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction21c(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -31,40 +31,54 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format21h extends Format
|
||||
public class Instruction21h extends Instruction
|
||||
{
|
||||
public static final Format21h Format = new Format21h();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format21h() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, short litB) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction21h(DexFile dexFile, Opcode opcode, short regA, short litB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)litB;
|
||||
bytes[3] = (byte)(litB >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)litB;
|
||||
encodedInstruction[3] = (byte)(litB >> 8);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 4;
|
||||
private Instruction21h(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "21h";
|
||||
private Instruction21h() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format21h;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction21h();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction21h(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getLiteral() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
@ -31,40 +31,54 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format21s extends Format
|
||||
public class Instruction21s extends Instruction
|
||||
{
|
||||
public static final Format21s Format = new Format21s();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format21s() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, short litB) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction21s(DexFile dexFile, Opcode opcode, short regA, short litB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)litB;
|
||||
bytes[3] = (byte)(litB >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)litB;
|
||||
encodedInstruction[3] = (byte)(litB >> 8);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 4;
|
||||
private Instruction21s(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "21s";
|
||||
private Instruction21s() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format21s;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction21s();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction21s(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getLiteral() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
@ -31,44 +31,62 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format21t extends Format
|
||||
public class Instruction21t extends Instruction
|
||||
{
|
||||
public static final Format21t Format = new Format21t();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format21t() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, short offB) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction21t(DexFile dexFile, Opcode opcode, short regA, short offB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
if (offB == 0) {
|
||||
if (offB == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)offB;
|
||||
bytes[3] = (byte)(offB >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)offB;
|
||||
encodedInstruction[3] = (byte)(offB >> 8);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 4;
|
||||
private Instruction21t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (getOffset() == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "21t";
|
||||
private Instruction21t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format21t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction21t();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction21t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getOffset() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
89
src/main/java/org/jf/dexlib/code/Format/Instruction22b.java
Normal file
89
src/main/java/org/jf/dexlib/code/Format/Instruction22b.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Instruction22b extends Instruction
|
||||
{
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
public Instruction22b(DexFile dexFile, Opcode opcode, short regA, short regB, byte litC) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8 ||
|
||||
regB >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)regB;
|
||||
encodedInstruction[3] = litC;
|
||||
}
|
||||
|
||||
private Instruction22b(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
private Instruction22b() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format22b;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction22b();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction22b(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegisterA() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getRegisterB() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[2]);
|
||||
}
|
||||
|
||||
public byte getLiteral() {
|
||||
return encodedInstruction[3];
|
||||
}
|
||||
}
|
@ -31,39 +31,54 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format12x extends Format
|
||||
public class Instruction22c extends Instruction
|
||||
{
|
||||
public static final Format12x Format = new Format12x();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format12x() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB) {
|
||||
byte[] bytes = new byte[2];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction22c(DexFile dexFile, Opcode opcode, byte regA, byte regB, IndexedItem item) {
|
||||
super(dexFile, opcode, item);
|
||||
|
||||
if (regA >= 1<<4 ||
|
||||
regB >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((regB << 4) | regA);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((regB << 4) | regA);
|
||||
//the item index will be set later, during placement/writing
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 2;
|
||||
private Instruction22c(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "12x";
|
||||
private Instruction22c() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format22c;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction22c();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction22c(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getRegisterA() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getRegisterB() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -31,44 +31,59 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format22s extends Format
|
||||
public class Instruction22s extends Instruction
|
||||
{
|
||||
public static final Format22s Format = new Format22s();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format22s() {
|
||||
}
|
||||
public Instruction22s(DexFile dexFile, Opcode opcode, byte regA, byte regB, short litC) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB, short litC) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<4) {
|
||||
if (regA >= 1<<4 ||
|
||||
regB >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
if (regB >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((regB << 4) | regA);
|
||||
encodedInstruction[2] = (byte)litC;
|
||||
encodedInstruction[3] = (byte)(litC >> 8);
|
||||
}
|
||||
|
||||
private Instruction22s(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
private Instruction22s() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format22s;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction22s();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction22s(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((regB << 4) | regA);
|
||||
bytes[2] = (byte)litC;
|
||||
bytes[3] = (byte)(litC >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 4;
|
||||
|
||||
public byte getRegisterA() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "22s";
|
||||
public byte getRegisterB() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getLiteral() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
@ -31,26 +31,18 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format22t extends Format
|
||||
public class Instruction22t extends Instruction
|
||||
{
|
||||
public static final Format22t Format = new Format22t();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format22t() {
|
||||
}
|
||||
public Instruction22t(DexFile dexFile, Opcode opcode, byte regA, byte regB, short offC) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB, short offC) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
if (regB >= 1<<4) {
|
||||
if (regA >= 1<<4 ||
|
||||
regB >= 1<<4) {
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
@ -58,19 +50,48 @@ public class Format22t extends Format
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((regB << 4) | regA);
|
||||
bytes[2] = (byte)offC;
|
||||
bytes[3] = (byte)(offC >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((regB << 4) | regA);
|
||||
encodedInstruction[2] = (byte)offC;
|
||||
encodedInstruction[3] = (byte)(offC >> 8);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
private Instruction22t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (getOffset() == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "22t";
|
||||
private Instruction22t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format22t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction22t();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction22t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getRegisterA() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getRegisterB() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getOffset() {
|
||||
return NumberUtils.decodeShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
@ -31,42 +31,58 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format22x extends Format
|
||||
public class Instruction22x extends Instruction
|
||||
{
|
||||
public static final Format22x Format = new Format22x();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format22x() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, int regB) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction22x(DexFile dexFile, Opcode opcode, short regA, int regB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
throw new RuntimeException("The register number must be less than v16");
|
||||
}
|
||||
|
||||
if (regB >= 1<<16) {
|
||||
throw new RuntimeException("The register number must be less than v65536");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)regB;
|
||||
bytes[3] = (byte)(regB >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)regB;
|
||||
encodedInstruction[3] = (byte)(regB >> 8);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
private Instruction22x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "22x";
|
||||
private Instruction22x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format22x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction22x();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction22x(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegisterA() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public int getRegisterB() {
|
||||
return NumberUtils.decodeUnsignedShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
}
|
@ -31,46 +31,60 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format23x extends Format
|
||||
public class Instruction23x extends Instruction
|
||||
{
|
||||
public static final Format23x Format = new Format23x();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format23x() {
|
||||
}
|
||||
public Instruction23x(DexFile dexFile, Opcode opcode, short regA, short regB, short regC) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, short regB, short regC) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
if (regA >= 1<<8 ||
|
||||
regB >= 1<<8 ||
|
||||
regC >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
if (regB >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
if (regC >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)regB;
|
||||
bytes[3] = (byte)regC;
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[4];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)regB;
|
||||
encodedInstruction[3] = (byte)regC;
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
private Instruction23x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "23x";
|
||||
private Instruction23x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format23x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction23x();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction23x(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegisterA() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public short getRegisterB() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[2]);
|
||||
}
|
||||
|
||||
public short getRegisterC() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[3]);
|
||||
}
|
||||
}
|
78
src/main/java/org/jf/dexlib/code/Format/Instruction30t.java
Normal file
78
src/main/java/org/jf/dexlib/code/Format/Instruction30t.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Instruction30t extends Instruction
|
||||
{
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
public Instruction30t(DexFile dexFile, Opcode opcode, int offA) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[2] = (byte)offA;
|
||||
encodedInstruction[3] = (byte)(offA >> 8);
|
||||
encodedInstruction[4] = (byte)(offA >> 16);
|
||||
encodedInstruction[5] = (byte)(offA >> 24);
|
||||
}
|
||||
|
||||
private Instruction30t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
private Instruction30t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format30t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction30t();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction30t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getOffset() {
|
||||
return NumberUtils.decodeInt(encodedInstruction[2], encodedInstruction[3], encodedInstruction[4],
|
||||
encodedInstruction[5]);
|
||||
}
|
||||
}
|
@ -31,42 +31,49 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format22b extends Format
|
||||
public class Instruction31c extends Instruction
|
||||
{
|
||||
public static final Format22b Format = new Format22b();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format22b() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, short regB, byte litC) {
|
||||
byte[] bytes = new byte[4];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction31c(DexFile dexFile, Opcode opcode, short regA, IndexedItem item) {
|
||||
super(dexFile, opcode, item);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
if (regB >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
//the item index will be set later, during placement/writing
|
||||
}
|
||||
|
||||
private Instruction31c(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
private Instruction31c() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format31c;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction31c();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction31c(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
bytes[2] = (byte)regB;
|
||||
bytes[3] = litC;
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "22b";
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
}
|
@ -31,42 +31,57 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format31i extends Format
|
||||
public class Instruction31i extends Instruction
|
||||
{
|
||||
public static final Format31i Format = new Format31i();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format31i() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, int litB) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction31i(DexFile dexFile, Opcode opcode, short regA, int litB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
|
||||
bytes[2] = (byte)litB;
|
||||
bytes[3] = (byte)(litB >> 8);
|
||||
|
||||
bytes[4] = (byte)(litB >> 16);
|
||||
bytes[5] = (byte)(litB >> 24);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)litB;
|
||||
encodedInstruction[3] = (byte)(litB >> 8);
|
||||
encodedInstruction[4] = (byte)(litB >> 16);
|
||||
encodedInstruction[5] = (byte)(litB >> 24);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
private Instruction31i(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "31i";
|
||||
private Instruction31i() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format31i;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction31i();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction31i(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public int getLiteral() {
|
||||
return NumberUtils.decodeInt(encodedInstruction[2], encodedInstruction[3], encodedInstruction[4],
|
||||
encodedInstruction[5]);
|
||||
}
|
||||
}
|
@ -31,33 +31,57 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format11x extends Format
|
||||
public class Instruction31t extends Instruction
|
||||
{
|
||||
public static final Format11x Format = new Format11x();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format11x() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA) {
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction31t(DexFile dexFile, Opcode opcode, short regA, int offB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
return new Instruction(dexFile, new byte[]{opcode,(byte)regA}, null);
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)offB;
|
||||
encodedInstruction[3] = (byte)(offB >> 8);
|
||||
encodedInstruction[4] = (byte)(offB >> 16);
|
||||
encodedInstruction[5] = (byte)(offB >> 24);
|
||||
}
|
||||
|
||||
public int getByteCount()
|
||||
{
|
||||
return 2;
|
||||
private Instruction31t(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName()
|
||||
{
|
||||
return "11x";
|
||||
private Instruction31t() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format31t;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction31t();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction31t(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return NumberUtils.decodeInt(encodedInstruction[2], encodedInstruction[3], encodedInstruction[4],
|
||||
encodedInstruction[5]);
|
||||
}
|
||||
}
|
@ -31,45 +31,56 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format32x extends Format
|
||||
public class Instruction32x extends Instruction
|
||||
{
|
||||
public static final Format32x Format = new Format32x();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format32x() {
|
||||
}
|
||||
public Instruction32x(DexFile dexFile, Opcode opcode, int regA, int regB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, int regA, int regB) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
|
||||
if (regA >= 1<<16) {
|
||||
if (regA >= 1<<16 ||
|
||||
regB >= 1<<16) {
|
||||
throw new RuntimeException("The register number must be less than v65536");
|
||||
}
|
||||
|
||||
if (regB >= 1<<16) {
|
||||
throw new RuntimeException("The register number must be less than v65536");
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[2] = (byte)regA;
|
||||
encodedInstruction[3] = (byte)(regA >> 8);
|
||||
encodedInstruction[4] = (byte)regB;
|
||||
encodedInstruction[5] = (byte)(regB >> 8);
|
||||
}
|
||||
|
||||
private Instruction32x(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
private Instruction32x() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format32x;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction32x();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction32x(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
|
||||
bytes[2] = (byte)regA;
|
||||
bytes[3] = (byte)(regA >> 8);
|
||||
|
||||
bytes[4] = (byte)regB;
|
||||
bytes[5] = (byte)(regB >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
|
||||
public int getRegisterA() {
|
||||
return NumberUtils.decodeUnsignedShort(encodedInstruction[2], encodedInstruction[3]);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "32x";
|
||||
public int getRegisterB() {
|
||||
return NumberUtils.decodeUnsignedShort(encodedInstruction[4], encodedInstruction[5]);
|
||||
}
|
||||
}
|
@ -29,27 +29,23 @@
|
||||
package org.jf.dexlib.code.Format;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import static org.jf.dexlib.code.Opcode.*;
|
||||
|
||||
public class Format35c extends Format
|
||||
public class Instruction35c extends Instruction
|
||||
{
|
||||
public static final Format35c Format = new Format35c();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format35c() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, byte regCount, byte regD, byte regE, byte regF, byte regG, byte regA, IndexedItem item) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction35c(DexFile dexFile, Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
|
||||
byte regA, IndexedItem item) {
|
||||
super(dexFile, opcode, item);
|
||||
|
||||
if (regCount > 5) {
|
||||
throw new RuntimeException("regCount cannot be greater than 5");
|
||||
}
|
||||
|
||||
if (regD >= 1<<4 ||
|
||||
regE >= 1<<4 ||
|
||||
regF >= 1<<4 ||
|
||||
@ -58,16 +54,73 @@ public class Format35c extends Format
|
||||
throw new RuntimeException("All register args must fit in 4 bits");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)((regCount << 4) | regA);
|
||||
bytes[4] = (byte)((regE << 4) | regD);
|
||||
bytes[5] = (byte)((regG << 4) | regF);
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)((regCount << 4) | regA);
|
||||
//the item index will be set later, during placement/writing
|
||||
encodedInstruction[4] = (byte)((regE << 4) | regD);
|
||||
encodedInstruction[5] = (byte)((regG << 4) | regF);
|
||||
|
||||
//go ahead and make the instruction, to verify that item is the correct type. If it isn't,
|
||||
//the construction will throw an exception
|
||||
Instruction instruction = new Instruction(dexFile, bytes, item);
|
||||
checkItem();
|
||||
}
|
||||
|
||||
if (opcode == FILLED_NEW_ARRAY.value) {
|
||||
private Instruction35c(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
if (getRegCount() > 5) {
|
||||
throw new RuntimeException("regCount cannot be greater than 5");
|
||||
}
|
||||
|
||||
checkItem();
|
||||
}
|
||||
|
||||
private Instruction35c() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format35c;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction35c();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction35c(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte getRegisterA() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getRegCount() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public byte getRegisterD() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[4]);
|
||||
}
|
||||
|
||||
public byte getRegisterE() {
|
||||
return NumberUtils.decodeHighUnsignedNibble(encodedInstruction[4]);
|
||||
}
|
||||
|
||||
public byte getRegisterF() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[5]);
|
||||
}
|
||||
|
||||
public byte getRegisterG() {
|
||||
return NumberUtils.decodeLowUnsignedNibble(encodedInstruction[5]);
|
||||
}
|
||||
|
||||
private void checkItem() {
|
||||
Opcode opcode = getOpcode();
|
||||
IndexedItem item = getReferencedItem();
|
||||
|
||||
if (opcode == FILLED_NEW_ARRAY) {
|
||||
//check data for filled-new-array opcode
|
||||
String type = ((TypeIdItem)item).getTypeDescriptor();
|
||||
if (type.charAt(0) != '[') {
|
||||
@ -76,39 +129,13 @@ public class Format35c extends Format
|
||||
if (type.charAt(1) == 'J' || type.charAt(1) == 'D') {
|
||||
throw new RuntimeException("The type cannot be an array of longs or doubles");
|
||||
}
|
||||
} else if (opcode >= INVOKE_VIRTUAL.value && opcode <= INVOKE_INTERFACE.value) {
|
||||
} else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value) {
|
||||
//check data for invoke-* opcodes
|
||||
MethodIdItem methodIdItem = (MethodIdItem)item;
|
||||
if (methodIdItem.getParameterRegisterCount(opcode == INVOKE_STATIC.value) != regCount) {
|
||||
if (methodIdItem.getParameterRegisterCount(opcode == INVOKE_STATIC) != getRegCount()) {
|
||||
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Opcode " + Integer.toHexString(opcode) + " does not use the 35c format");
|
||||
}
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "35c";
|
||||
}
|
||||
|
||||
/*@Test
|
||||
public void testInvoke() {
|
||||
DexFile dexFile = new DexFile();
|
||||
ArrayList<TypeIdItem> types = new ArrayList<TypeIdItem>();
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
MethodIdItem method = new MethodIdItem(dexFile, new TypeIdItem(dexFile, "test"), "test", new ProtoIdItem(dexFile, new TypeIdItem(dexFile, "V"), types));
|
||||
|
||||
Instruction ins = make(dexFile, (byte)INVOKE_VIRTUAL.value, (byte)5, (byte)0, (byte)1, (byte)2, (byte)3, (byte)4, method);
|
||||
assertTrue("Is everything put in the right place?", java.util.Arrays.equals(ins.getBytes(), new byte[] {0x6e, 0x54, 0x00, 0x00, 0x10, 0x32}));
|
||||
}*/
|
||||
}
|
@ -29,23 +29,17 @@
|
||||
package org.jf.dexlib.code.Format;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import static org.jf.dexlib.code.Opcode.*;
|
||||
|
||||
public class Format3rc extends Format
|
||||
public class Instruction3rc extends Instruction
|
||||
{
|
||||
public static final Format3rc Format = new Format3rc();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
public Format3rc() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regCount, int startReg, IndexedItem item) {
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction3rc(DexFile dexFile, Opcode opcode, short regCount, int startReg, IndexedItem item) {
|
||||
super(dexFile, opcode, item);
|
||||
|
||||
if (regCount >= 1<<8) {
|
||||
throw new RuntimeException("regCount must be less than 256");
|
||||
@ -61,16 +55,53 @@ public class Format3rc extends Format
|
||||
throw new RuntimeException("The beginning register of the range cannot be negative");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regCount;
|
||||
bytes[4] = (byte)startReg;
|
||||
bytes[5] = (byte)(startReg >> 8);
|
||||
encodedInstruction = new byte[6];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regCount;
|
||||
//the item index will be set later, during placement/writing
|
||||
encodedInstruction[4] = (byte)startReg;
|
||||
encodedInstruction[5] = (byte)(startReg >> 8);
|
||||
|
||||
//go ahead and make the instruction now, which will verify that item is the correct type. If it isn't,
|
||||
//the construction will throw an exception
|
||||
Instruction instruction = new Instruction(dexFile, bytes, item);
|
||||
checkItem();
|
||||
}
|
||||
|
||||
if (opcode == FILLED_NEW_ARRAY_RANGE.value) {
|
||||
private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
|
||||
checkItem();
|
||||
}
|
||||
|
||||
private Instruction3rc() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format3rc;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction3rc();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction3rc(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegCount() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public int getStartRegister() {
|
||||
return NumberUtils.decodeUnsignedShort(encodedInstruction[4], encodedInstruction[5]);
|
||||
}
|
||||
|
||||
private void checkItem() {
|
||||
Opcode opcode = getOpcode();
|
||||
IndexedItem item = getReferencedItem();
|
||||
|
||||
if (opcode == FILLED_NEW_ARRAY_RANGE) {
|
||||
//check data for filled-new-array/range opcode
|
||||
String type = ((TypeIdItem)item).getTypeDescriptor();
|
||||
if (type.charAt(0) != '[') {
|
||||
@ -79,40 +110,12 @@ public class Format3rc extends Format
|
||||
if (type.charAt(1) == 'J' || type.charAt(1) == 'D') {
|
||||
throw new RuntimeException("The type cannot be an array of longs or doubles");
|
||||
}
|
||||
} else if (opcode >= INVOKE_VIRTUAL_RANGE.value && opcode <= INVOKE_INTERFACE_RANGE.value) {
|
||||
} else if (opcode.value >= INVOKE_VIRTUAL_RANGE.value && opcode.value <= INVOKE_INTERFACE_RANGE.value) {
|
||||
//check data for invoke-*/range opcodes
|
||||
MethodIdItem methodIdItem = (MethodIdItem)item;
|
||||
if (methodIdItem.getParameterRegisterCount(opcode == INVOKE_STATIC_RANGE.value) != regCount) {
|
||||
if (methodIdItem.getParameterRegisterCount(opcode == INVOKE_STATIC_RANGE) != getRegCount()) {
|
||||
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Opcode " + Integer.toHexString(opcode) + " does not use the 35c format");
|
||||
}
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "3rc";
|
||||
}
|
||||
|
||||
/*@Test
|
||||
public void testInvoke() {
|
||||
DexFile dexFile = DexFile.makeBlankDexFile();
|
||||
ArrayList<TypeIdItem> types = new ArrayList<TypeIdItem>();
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
types.add(new TypeIdItem(dexFile, "I"));
|
||||
MethodIdItem method = new MethodIdItem(dexFile, new TypeIdItem(dexFile, "test"), "test", new ProtoIdItem(dexFile, new TypeIdItem(dexFile, "V"), types));
|
||||
|
||||
Instruction ins = Format.make(dexFile, (byte)INVOKE_VIRTUAL_RANGE.value, (short)6, 65500, method);
|
||||
byte[] bytes = new byte[] {0x74, 0x06, 0x00, 0x00, (byte)0xDC, (byte)0xFF};
|
||||
assertTrue("Is everything put in the right place?", java.util.Arrays.equals(ins.getBytes(), bytes));
|
||||
}*/
|
||||
}
|
@ -31,48 +31,60 @@ package org.jf.dexlib.code.Format;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.NumberUtils;
|
||||
|
||||
public class Format51l extends Format
|
||||
public class Instruction51l extends Instruction
|
||||
{
|
||||
public static final Format51l Format = new Format51l();
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
private Format51l() {
|
||||
}
|
||||
|
||||
public Instruction make(DexFile dexFile, byte opcode, short regA, long litB) {
|
||||
byte[] bytes = new byte[10];
|
||||
|
||||
Opcode op = Opcode.getOpcodeByValue(opcode);
|
||||
|
||||
checkOpcodeFormat(op);
|
||||
public Instruction51l(DexFile dexFile, Opcode opcode, short regA, long litB) {
|
||||
super(dexFile, opcode, (IndexedItem)null);
|
||||
|
||||
if (regA >= 1<<8) {
|
||||
throw new RuntimeException("The register number must be less than v256");
|
||||
}
|
||||
|
||||
bytes[0] = opcode;
|
||||
bytes[1] = (byte)regA;
|
||||
|
||||
bytes[2] = (byte)litB;
|
||||
bytes[3] = (byte)(litB >> 8);
|
||||
|
||||
bytes[4] = (byte)(litB >> 16);
|
||||
bytes[5] = (byte)(litB >> 24);
|
||||
|
||||
bytes[6] = (byte)(litB >> 32);
|
||||
bytes[7] = (byte)(litB >> 40);
|
||||
|
||||
bytes[8] = (byte)(litB >> 48);
|
||||
bytes[9] = (byte)(litB >> 56);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
encodedInstruction = new byte[10];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
encodedInstruction[1] = (byte)regA;
|
||||
encodedInstruction[2] = (byte)litB;
|
||||
encodedInstruction[3] = (byte)(litB >> 8);
|
||||
encodedInstruction[4] = (byte)(litB >> 16);
|
||||
encodedInstruction[5] = (byte)(litB >> 24);
|
||||
encodedInstruction[6] = (byte)(litB >> 32);
|
||||
encodedInstruction[7] = (byte)(litB >> 40);
|
||||
encodedInstruction[8] = (byte)(litB >> 48);
|
||||
encodedInstruction[9] = (byte)(litB >> 56);
|
||||
}
|
||||
|
||||
public int getByteCount() {
|
||||
return 10;
|
||||
private Instruction51l(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
super(dexFile, opcode, rest);
|
||||
}
|
||||
|
||||
public String getFormatName() {
|
||||
return "51l";
|
||||
private Instruction51l() {
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format51l;
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new Instruction51l();
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
return new Instruction51l(dexFile, opcode, rest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public short getRegister() {
|
||||
return NumberUtils.decodeUnsignedByte(encodedInstruction[1]);
|
||||
}
|
||||
|
||||
public long getLiteral() {
|
||||
return NumberUtils.decodeLong(encodedInstruction, 2);
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class PackedSwitchData
|
||||
{
|
||||
public static Instruction make(DexFile dexFile, int firstKey, int[] targets) {
|
||||
byte[] bytes;
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
bytes = new byte[targets.length * 4 + 8];
|
||||
int position = 8;
|
||||
|
||||
for (int target: targets) {
|
||||
bytes[position++] = (byte)target;
|
||||
bytes[position++] = (byte)(target >> 8);
|
||||
bytes[position++] = (byte)(target >> 16);
|
||||
bytes[position++] = (byte)(target >> 24);
|
||||
}
|
||||
|
||||
//packed-switch psuedo-opcode
|
||||
bytes[0] = 0x00;
|
||||
bytes[1] = 0x01;
|
||||
|
||||
bytes[2] = (byte)targets.length;
|
||||
bytes[3] = (byte)(targets.length >> 8);
|
||||
|
||||
bytes[4] = (byte)firstKey;
|
||||
bytes[5] = (byte)(firstKey >> 8);
|
||||
bytes[6] = (byte)(firstKey >> 16);
|
||||
bytes[7] = (byte)(firstKey >> 24);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.Input;
|
||||
|
||||
public class PackedSwitchDataPseudoInstruction extends Instruction
|
||||
{
|
||||
public PackedSwitchDataPseudoInstruction(DexFile dexFile, int firstKey, int[] targets) {
|
||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
encodedInstruction = new byte[targets.length * 4 + 8];
|
||||
encodedInstruction[0] = 0x00;
|
||||
encodedInstruction[1] = 0x01; //packed-switch pseudo-opcode
|
||||
|
||||
encodedInstruction[2] = (byte)targets.length;
|
||||
encodedInstruction[3] = (byte)(targets.length >> 8);
|
||||
|
||||
encodedInstruction[4] = (byte)firstKey;
|
||||
encodedInstruction[5] = (byte)(firstKey >> 8);
|
||||
encodedInstruction[6] = (byte)(firstKey >> 16);
|
||||
encodedInstruction[7] = (byte)(firstKey >> 24);
|
||||
|
||||
int position= 8;
|
||||
for (int target: targets) {
|
||||
encodedInstruction[position++] = (byte)target;
|
||||
encodedInstruction[position++] = (byte)(target >> 8);
|
||||
encodedInstruction[position++] = (byte)(target >> 16);
|
||||
encodedInstruction[position++] = (byte)(target >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkFormat(Format format) {
|
||||
//no need to check the format
|
||||
}
|
||||
|
||||
private PackedSwitchDataPseudoInstruction() {
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new PackedSwitchDataPseudoInstruction();
|
||||
}
|
||||
|
||||
|
||||
public static PackedSwitchDataPseudoInstruction make(DexFile dexFile, Input input) {
|
||||
byte opcodeByte = input.readByte();
|
||||
if (opcodeByte != 0x00) {
|
||||
throw new RuntimeException("Invalid opcode byte for a PackedSwitchData pseudo-instruction");
|
||||
}
|
||||
byte subopcodeByte = input.readByte();
|
||||
if (subopcodeByte != 0x01) {
|
||||
throw new RuntimeException("Invalid sub-opcode byte for a PackedSwitchData pseudo-instruction");
|
||||
}
|
||||
|
||||
int targetCount = input.readShort();
|
||||
|
||||
int firstKey = input.readInt();
|
||||
int[] targets = new int[targetCount];
|
||||
|
||||
for (int i=0; i<targetCount; i++) {
|
||||
targets[i] = input.readInt();
|
||||
}
|
||||
|
||||
return new PackedSwitchDataPseudoInstruction(dexFile, firstKey, targets);
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.SparseSwitchData;
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
public class SparseSwitchData
|
||||
{
|
||||
public static Instruction make(DexFile dexFile, int[] keys, int[] targets) {
|
||||
byte[] bytes;
|
||||
|
||||
if (keys.length != targets.length) {
|
||||
throw new RuntimeException("The number of keys and offsets don't match");
|
||||
}
|
||||
|
||||
if (targets.length == 0) {
|
||||
throw new RuntimeException("The sparse-switch data must contain at least 1 key/target");
|
||||
}
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The sparse-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
bytes = new byte[targets.length * 8 + 4];
|
||||
int position = 8;
|
||||
|
||||
if (targets.length > 0) {
|
||||
int key = keys[0];
|
||||
bytes[4] = (byte)key;
|
||||
bytes[5] = (byte)(key >> 8);
|
||||
bytes[6] = (byte)(key >> 16);
|
||||
bytes[7] = (byte)(key >> 24);
|
||||
|
||||
for (int i=1; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
if (key <= keys[i-1]) {
|
||||
throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
|
||||
"order, by key");
|
||||
}
|
||||
|
||||
bytes[position++] = (byte)key;
|
||||
bytes[position++] = (byte)(key >> 8);
|
||||
bytes[position++] = (byte)(key >> 16);
|
||||
bytes[position++] = (byte)(key >> 24);
|
||||
}
|
||||
|
||||
for (int target: targets) {
|
||||
bytes[position++] = (byte)target;
|
||||
bytes[position++] = (byte)(target >> 8);
|
||||
bytes[position++] = (byte)(target >> 16);
|
||||
bytes[position++] = (byte)(target >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
//sparse-switch psuedo-opcode
|
||||
bytes[0] = 0x00;
|
||||
bytes[1] = 0x02;
|
||||
|
||||
bytes[2] = (byte)targets.length;
|
||||
bytes[3] = (byte)(targets.length >> 8);
|
||||
|
||||
return new Instruction(dexFile, bytes, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.code.Instruction;
|
||||
import org.jf.dexlib.code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.util.Input;
|
||||
|
||||
public class SparseSwitchDataPseudoInstruction extends Instruction
|
||||
{
|
||||
public SparseSwitchDataPseudoInstruction(DexFile dexFile, int[] keys, int[] targets) {
|
||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||
|
||||
if (keys.length != targets.length) {
|
||||
throw new RuntimeException("The number of keys and offsets don't match");
|
||||
}
|
||||
|
||||
if (targets.length == 0) {
|
||||
throw new RuntimeException("The sparse-switch data must contain at least 1 key/target");
|
||||
}
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The sparse-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
encodedInstruction = new byte[targets.length * 8 + 4];
|
||||
encodedInstruction[0] = 0x00;
|
||||
encodedInstruction[1] = 0x02; //sparse-switch psuedo-opcode
|
||||
|
||||
encodedInstruction[2] = (byte)targets.length;
|
||||
encodedInstruction[3] = (byte)(targets.length >> 8);
|
||||
|
||||
int position = 8;
|
||||
|
||||
if (targets.length > 0) {
|
||||
int key = keys[0];
|
||||
encodedInstruction[4] = (byte)key;
|
||||
encodedInstruction[5] = (byte)(key >> 8);
|
||||
encodedInstruction[6] = (byte)(key >> 16);
|
||||
encodedInstruction[7] = (byte)(key >> 24);
|
||||
|
||||
for (int i=1; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
if (key <= keys[i-1]) {
|
||||
throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
|
||||
"order, by key");
|
||||
}
|
||||
|
||||
encodedInstruction[position++] = (byte)key;
|
||||
encodedInstruction[position++] = (byte)(key >> 8);
|
||||
encodedInstruction[position++] = (byte)(key >> 16);
|
||||
encodedInstruction[position++] = (byte)(key >> 24);
|
||||
}
|
||||
|
||||
for (int target: targets) {
|
||||
encodedInstruction[position++] = (byte)target;
|
||||
encodedInstruction[position++] = (byte)(target >> 8);
|
||||
encodedInstruction[position++] = (byte)(target >> 16);
|
||||
encodedInstruction[position++] = (byte)(target >> 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkFormat(Format format) {
|
||||
//no need to check the format
|
||||
}
|
||||
|
||||
private SparseSwitchDataPseudoInstruction() {
|
||||
}
|
||||
|
||||
protected Instruction makeClone() {
|
||||
return new SparseSwitchDataPseudoInstruction();
|
||||
}
|
||||
|
||||
public static SparseSwitchDataPseudoInstruction make(DexFile dexFile, Input input) {
|
||||
byte opcodeByte = input.readByte();
|
||||
if (opcodeByte != 0x00) {
|
||||
throw new RuntimeException("Invalid opcode byte for a SparseSwitchData pseudo-instruction");
|
||||
}
|
||||
byte subopcodeByte = input.readByte();
|
||||
if (subopcodeByte != 0x02) {
|
||||
throw new RuntimeException("Invalid sub-opcode byte for a SparseSwitchData pseudo-instruction");
|
||||
}
|
||||
|
||||
int targetCount = input.readShort();
|
||||
|
||||
int[] keys = new int[targetCount];
|
||||
int[] targets = new int[targetCount];
|
||||
|
||||
for (int i=0; i<targetCount; i++) {
|
||||
keys[i] = input.readInt();
|
||||
}
|
||||
|
||||
for (int i=0; i<targetCount; i++) {
|
||||
targets[i] = input.readInt();
|
||||
}
|
||||
|
||||
return new SparseSwitchDataPseudoInstruction(dexFile, keys, targets);
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.SparseSwitchData;
|
||||
}
|
||||
}
|
@ -29,179 +29,300 @@
|
||||
package org.jf.dexlib.code;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.code.Format.Format;
|
||||
import org.jf.dexlib.util.Input;
|
||||
import org.jf.dexlib.util.AnnotatedOutput;
|
||||
|
||||
public final class Instruction implements Field<Instruction> {
|
||||
import java.util.Collections;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
public abstract class Instruction {
|
||||
private DexFile dexFile;
|
||||
private byte[] bytes;
|
||||
private Opcode opcode;
|
||||
private IndexedItem referencedItem;
|
||||
protected byte[] encodedInstruction;
|
||||
|
||||
private IndexedItem reference;
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
public int getSize() {
|
||||
return encodedInstruction.length;
|
||||
}
|
||||
|
||||
public Opcode getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
public IndexedItem getReference() {
|
||||
return reference;
|
||||
public IndexedItem getReferencedItem() {
|
||||
return referencedItem;
|
||||
}
|
||||
|
||||
public Instruction(DexFile dexFile) {
|
||||
this.dexFile = dexFile;
|
||||
protected void setReferencedItem(IndexedItem referencedItem) {
|
||||
checkReferenceType(referencedItem, this.opcode);
|
||||
this.referencedItem = referencedItem;
|
||||
}
|
||||
|
||||
public Instruction(DexFile dexFile, byte[] bytes, IndexedItem item) {
|
||||
protected Instruction(DexFile dexFile, Opcode opcode, IndexedItem referencedItem) {
|
||||
this.dexFile = dexFile;
|
||||
this.bytes = bytes;
|
||||
this.reference = item;
|
||||
this.opcode = Opcode.getOpcodeByValue(bytes[0]);
|
||||
if (!this.opcode.referenceType.checkItem(item)) {
|
||||
throw new RuntimeException("item is not the correct type for this opcode (got " + item.getClass().toString() + ", expecting " + opcode.referenceType.toString() + ")");
|
||||
this.opcode = opcode;
|
||||
this.referencedItem = referencedItem;
|
||||
|
||||
checkFormat(opcode.format);
|
||||
checkReferenceType(referencedItem, this.opcode);
|
||||
}
|
||||
|
||||
protected void checkFormat(Format format) {
|
||||
if (format != getFormat()) {
|
||||
throw new RuntimeException(opcode.name + " does not use " + getFormat().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void readFrom(Input in) {
|
||||
int startPos = in.getCursor();
|
||||
|
||||
byte opByte = in.readByte();
|
||||
protected Instruction(DexFile dexFile, Opcode opcode, byte[] rest) {
|
||||
this.dexFile = dexFile;
|
||||
this.opcode = opcode;
|
||||
|
||||
if (opByte == 0x00) {
|
||||
reference = null;
|
||||
byte secondByte = in.readByte();
|
||||
|
||||
int count;
|
||||
|
||||
|
||||
switch (secondByte) {
|
||||
case 0x00:
|
||||
/** nop */
|
||||
bytes = new byte[] { 0x00, 0x00 };
|
||||
return;
|
||||
case 0x01:
|
||||
/** packed switch */
|
||||
count = in.readShort();
|
||||
in.setCursor(startPos);
|
||||
bytes = in.readBytes((count * 4) + 8);
|
||||
return;
|
||||
case 0x02:
|
||||
/** sparse switch */
|
||||
count = in.readShort();
|
||||
in.setCursor(startPos);
|
||||
bytes = in.readBytes((count * 8) + 4);
|
||||
return;
|
||||
case 0x03:
|
||||
/** fill array data */
|
||||
int elementWidth = in.readShort();
|
||||
count = in.readInt();
|
||||
in.setCursor(startPos);
|
||||
bytes = in.readBytes(((elementWidth * count + 1)/2 + 4) * 2);
|
||||
return;
|
||||
default:
|
||||
throw new RuntimeException("Invalid 2nd byte for opcode 0x00");
|
||||
}
|
||||
if ((rest.length + 1) != opcode.format.size) {
|
||||
throw new RuntimeException("Invalid instruction size. This opcode is " +
|
||||
Integer.toString(rest.length + 1) + " bytes, but the opcode should be " +
|
||||
Integer.toString(opcode.format.size) + " bytes.");
|
||||
}
|
||||
|
||||
this.opcode = Opcode.getOpcodeByValue(opByte);
|
||||
this.encodedInstruction = new byte[rest.length + 1];
|
||||
encodedInstruction[0] = opcode.value;
|
||||
System.arraycopy(rest, 0, encodedInstruction, 1, rest.length);
|
||||
|
||||
if (opcode.referenceType != ReferenceType.none) {
|
||||
in.skipBytes(1);
|
||||
int referenceIndex = in.readShort();
|
||||
|
||||
//handle const-string/jumbo as a special case
|
||||
if (opByte == 0x1b) {
|
||||
int hiWord = in.readShort();
|
||||
if (hiWord != 0) {
|
||||
referenceIndex += (hiWord<<16);
|
||||
}
|
||||
}
|
||||
|
||||
switch (opcode.referenceType) {
|
||||
case string:
|
||||
reference = dexFile.StringIdsSection.getByIndex(referenceIndex);
|
||||
break;
|
||||
case type:
|
||||
reference = dexFile.TypeIdsSection.getByIndex(referenceIndex);
|
||||
break;
|
||||
case field:
|
||||
reference = dexFile.FieldIdsSection.getByIndex(referenceIndex);
|
||||
break;
|
||||
case method:
|
||||
reference = dexFile.MethodIdsSection.getByIndex(referenceIndex);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
reference = null;
|
||||
}
|
||||
|
||||
in.setCursor(startPos);
|
||||
bytes = in.readBytes(opcode.numBytes);
|
||||
}
|
||||
|
||||
public void writeTo(AnnotatedOutput out) {
|
||||
out.annotate(bytes.length, "instruction");
|
||||
if (needsAlign()) {
|
||||
//the "special instructions" must be 4 byte aligned
|
||||
out.alignTo(4);
|
||||
out.write(bytes);
|
||||
} else if (reference == null) {
|
||||
out.write(bytes);
|
||||
} else {
|
||||
out.write(bytes,0,2);
|
||||
//handle const-string/jumbo as a special case
|
||||
if (bytes[0] == 0x1b) {
|
||||
out.writeInt(reference.getIndex());
|
||||
} else {
|
||||
int index = reference.getIndex();
|
||||
if (index > 0xFFFF) {
|
||||
throw new RuntimeException("String index doesn't fit.");
|
||||
}
|
||||
out.writeShort(reference.getIndex());
|
||||
out.write(bytes, 4, bytes.length - 4);
|
||||
}
|
||||
int itemIndex = (encodedInstruction[3] << 8) | encodedInstruction[2];
|
||||
getReferencedItem(dexFile, opcode, itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyTo(DexFile dexFile, Instruction copy) {
|
||||
copy.bytes = bytes;
|
||||
copy.opcode = opcode;
|
||||
protected Instruction() {
|
||||
//this should only be used to make a blank clone within cloneTo()
|
||||
}
|
||||
|
||||
private void checkReferenceType(IndexedItem referencedItem, Opcode opcode) {
|
||||
switch (opcode.referenceType) {
|
||||
case field:
|
||||
if (!(referencedItem instanceof FieldIdItem)) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
" is the wrong item type for opcode " + opcode.name + ". Expecting FieldIdItem.");
|
||||
}
|
||||
return;
|
||||
case method:
|
||||
if (!(referencedItem instanceof MethodIdItem)) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
" is the wrong item type for opcode " + opcode.name + ". Expecting MethodIdItem.");
|
||||
}
|
||||
return;
|
||||
case type:
|
||||
if (!(referencedItem instanceof TypeIdItem)) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
" is the wrong item type for opcode " + opcode.name + ". Expecting TypeIdItem.");
|
||||
}
|
||||
return;
|
||||
case string:
|
||||
if (!(referencedItem instanceof StringIdItem)) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
" is the wrong item type for opcode " + opcode.name + ". Expecting StringIdItem.");
|
||||
}
|
||||
return;
|
||||
default:
|
||||
if (referencedItem != null) {
|
||||
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
|
||||
" is invalid for opcode " + opcode.name + ". This opcode does not reference an item");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void getReferencedItem(DexFile dexFile, Opcode opcode, int itemIndex) {
|
||||
switch (opcode.referenceType) {
|
||||
case field:
|
||||
referencedItem = dexFile.FieldIdsSection.getByIndex(itemIndex);
|
||||
return;
|
||||
case method:
|
||||
referencedItem = dexFile.MethodIdsSection.getByIndex(itemIndex);
|
||||
return;
|
||||
case type:
|
||||
referencedItem = dexFile.TypeIdsSection.getByIndex(itemIndex);
|
||||
return;
|
||||
case string:
|
||||
referencedItem = dexFile.StringIdsSection.getByIndex(itemIndex);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public abstract Format getFormat();
|
||||
|
||||
public static interface InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] rest);
|
||||
}
|
||||
|
||||
public Instruction cloneTo(DexFile dexFile) {
|
||||
Instruction clone = makeClone();
|
||||
clone.encodedInstruction = encodedInstruction.clone();
|
||||
clone.dexFile = dexFile;
|
||||
clone.opcode = opcode;
|
||||
if (referencedItem != null) {
|
||||
switch (opcode.referenceType) {
|
||||
case string:
|
||||
copy.reference = dexFile.StringIdsSection.intern(dexFile, (StringIdItem)reference);
|
||||
clone.referencedItem = dexFile.StringIdsSection.intern(dexFile, (StringIdItem)referencedItem);
|
||||
break;
|
||||
case type:
|
||||
copy.reference = dexFile.TypeIdsSection.intern(dexFile, (TypeIdItem)reference);
|
||||
clone.referencedItem = dexFile.TypeIdsSection.intern(dexFile, (TypeIdItem)referencedItem);
|
||||
break;
|
||||
case field:
|
||||
copy.reference = dexFile.FieldIdsSection.intern(dexFile, (FieldIdItem)reference);
|
||||
clone.referencedItem = dexFile.FieldIdsSection.intern(dexFile, (FieldIdItem)referencedItem);
|
||||
break;
|
||||
case method:
|
||||
copy.reference = dexFile.MethodIdsSection.intern(dexFile, (MethodIdItem)reference);
|
||||
clone.referencedItem = dexFile.MethodIdsSection.intern(dexFile, (MethodIdItem)referencedItem);
|
||||
break;
|
||||
case none:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int place(int offset) {
|
||||
return offset + getSize(offset);
|
||||
}
|
||||
|
||||
public int getSize(int offset) {
|
||||
if (this.needsAlign() && (offset % 4) != 0) {
|
||||
return bytes.length + 2;
|
||||
} else {
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
private boolean needsAlign() {
|
||||
//true if the opcode is one of the "special format" opcodes
|
||||
return bytes[0] == 0 && bytes[1] > 0;
|
||||
}
|
||||
protected abstract Instruction makeClone();
|
||||
|
||||
// public void readFrom(Input in) {
|
||||
// int startPos = in.getCursor();
|
||||
//
|
||||
// byte opByte = in.readByte();
|
||||
//
|
||||
// if (opByte == 0x00) {
|
||||
// reference = null;
|
||||
// byte secondByte = in.readByte();
|
||||
//
|
||||
// int count;
|
||||
//
|
||||
//
|
||||
// switch (secondByte) {
|
||||
// case 0x00:
|
||||
// /** nop */
|
||||
// bytes = new byte[] { 0x00, 0x00 };
|
||||
// return;
|
||||
// case 0x01:
|
||||
// /** packed switch */
|
||||
// count = in.readShort();
|
||||
// in.setCursor(startPos);
|
||||
// bytes = in.readBytes((count * 4) + 8);
|
||||
// return;
|
||||
// case 0x02:
|
||||
// /** sparse switch */
|
||||
// count = in.readShort();
|
||||
// in.setCursor(startPos);
|
||||
// bytes = in.readBytes((count * 8) + 4);
|
||||
// return;
|
||||
// case 0x03:
|
||||
// /** fill array data */
|
||||
// int elementWidth = in.readShort();
|
||||
// count = in.readInt();
|
||||
// in.setCursor(startPos);
|
||||
// bytes = in.readBytes(((elementWidth * count + 1)/2 + 4) * 2);
|
||||
// return;
|
||||
// default:
|
||||
// throw new RuntimeException("Invalid 2nd byte for opcode 0x00");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.opcode = Opcode.getOpcodeByValue(opByte);
|
||||
//
|
||||
// if (opcode.referenceType != ReferenceType.none) {
|
||||
// in.skipBytes(1);
|
||||
// int referenceIndex = in.readShort();
|
||||
//
|
||||
// //handle const-string/jumbo as a special case
|
||||
// if (opByte == 0x1b) {
|
||||
// int hiWord = in.readShort();
|
||||
// if (hiWord != 0) {
|
||||
// referenceIndex += (hiWord<<16);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// switch (opcode.referenceType) {
|
||||
// case string:
|
||||
// reference = dexFile.StringIdsSection.getByIndex(referenceIndex);
|
||||
// break;
|
||||
// case type:
|
||||
// reference = dexFile.TypeIdsSection.getByIndex(referenceIndex);
|
||||
// break;
|
||||
// case field:
|
||||
// reference = dexFile.FieldIdsSection.getByIndex(referenceIndex);
|
||||
// break;
|
||||
// case method:
|
||||
// reference = dexFile.MethodIdsSection.getByIndex(referenceIndex);
|
||||
// break;
|
||||
// }
|
||||
// } else {
|
||||
// reference = null;
|
||||
// }
|
||||
//
|
||||
// in.setCursor(startPos);
|
||||
// bytes = in.readBytes(opcode.numBytes);
|
||||
// }
|
||||
//
|
||||
// public void writeTo(AnnotatedOutput out) {
|
||||
// out.annotate(bytes.length, "instruction");
|
||||
// if (needsAlign()) {
|
||||
// //the "special instructions" must be 4 byte aligned
|
||||
// out.alignTo(4);
|
||||
// out.write(bytes);
|
||||
// } else if (reference == null) {
|
||||
// out.write(bytes);
|
||||
// } else {
|
||||
// out.write(bytes,0,2);
|
||||
// //handle const-string/jumbo as a special case
|
||||
// if (bytes[0] == 0x1b) {
|
||||
// out.writeInt(reference.getIndex());
|
||||
// } else {
|
||||
// int index = reference.getIndex();
|
||||
// if (index > 0xFFFF) {
|
||||
// throw new RuntimeException("String index doesn't fit.");
|
||||
// }
|
||||
// out.writeShort(reference.getIndex());
|
||||
// out.write(bytes, 4, bytes.length - 4);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void copyTo(DexFile dexFile, Instruction copy) {
|
||||
// copy.bytes = bytes;
|
||||
// copy.opcode = opcode;
|
||||
//
|
||||
// switch (opcode.referenceType) {
|
||||
// case string:
|
||||
// copy.reference = dexFile.StringIdsSection.intern(dexFile, (StringIdItem)reference);
|
||||
// break;
|
||||
// case type:
|
||||
// copy.reference = dexFile.TypeIdsSection.intern(dexFile, (TypeIdItem)reference);
|
||||
// break;
|
||||
// case field:
|
||||
// copy.reference = dexFile.FieldIdsSection.intern(dexFile, (FieldIdItem)reference);
|
||||
// break;
|
||||
// case method:
|
||||
// copy.reference = dexFile.MethodIdsSection.intern(dexFile, (MethodIdItem)reference);
|
||||
// break;
|
||||
// case none:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public int place(int offset) {
|
||||
// return offset + getSize(offset);
|
||||
// }
|
||||
//
|
||||
// public int getSize(int offset) {
|
||||
// if (this.needsAlign() && (offset % 4) != 0) {
|
||||
// return bytes.length + 2;
|
||||
// } else {
|
||||
// return bytes.length;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private boolean needsAlign() {
|
||||
// //true if the opcode is one of the "special format" opcodes
|
||||
// return bytes[0] == 0 && bytes[1] > 0;
|
||||
// }
|
||||
}
|
||||
|
141
src/main/java/org/jf/dexlib/code/InstructionField.java
Normal file
141
src/main/java/org/jf/dexlib/code/InstructionField.java
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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;
|
||||
|
||||
import org.jf.dexlib.Field;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.IndexedItem;
|
||||
import org.jf.dexlib.code.Format.PackedSwitchDataPseudoInstruction;
|
||||
import org.jf.dexlib.code.Format.SparseSwitchDataPseudoInstruction;
|
||||
import org.jf.dexlib.code.Format.ArrayDataPseudoInstruction;
|
||||
import org.jf.dexlib.util.AnnotatedOutput;
|
||||
import org.jf.dexlib.util.Input;
|
||||
|
||||
public class InstructionField implements Field<InstructionField> {
|
||||
private Instruction instruction;
|
||||
private DexFile dexFile;
|
||||
|
||||
public InstructionField(DexFile dexFile) {
|
||||
this.dexFile = dexFile;
|
||||
}
|
||||
|
||||
public InstructionField(DexFile dexFile, Instruction instruction) {
|
||||
this.dexFile = dexFile;
|
||||
this.instruction = instruction;
|
||||
}
|
||||
|
||||
public void writeTo(AnnotatedOutput out) {
|
||||
byte[] bytes = instruction.encodedInstruction;
|
||||
IndexedItem reference = instruction.getReferencedItem();
|
||||
|
||||
out.annotate(bytes.length, "instruction");
|
||||
if (needsAlign()) {
|
||||
//the "special instructions" must be 4 byte aligned
|
||||
out.alignTo(4);
|
||||
out.write(bytes);
|
||||
} else if (reference == null) {
|
||||
out.write(bytes);
|
||||
} else {
|
||||
out.write(bytes,0,2);
|
||||
//handle const-string/jumbo as a special case
|
||||
if (bytes[0] == 0x1b) {
|
||||
out.writeInt(reference.getIndex());
|
||||
} else {
|
||||
int index = reference.getIndex();
|
||||
if (index > 0xFFFF) {
|
||||
throw new RuntimeException("String index doesn't fit.");
|
||||
}
|
||||
out.writeShort(reference.getIndex());
|
||||
out.write(bytes, 4, bytes.length - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readFrom(Input in) {
|
||||
int startPos = in.getCursor();
|
||||
|
||||
byte opByte = in.readByte();
|
||||
|
||||
if (opByte == 0x00) {
|
||||
byte secondByte = in.readByte();
|
||||
|
||||
switch (secondByte) {
|
||||
case 0x00:
|
||||
//nop
|
||||
instruction = Opcode.NOP.format.Factory.makeInstruction(dexFile, Opcode.NOP, new byte[]{0x00, 0x00});
|
||||
return;
|
||||
case 0x01:
|
||||
//packed switch
|
||||
in.setCursor(startPos);
|
||||
instruction = PackedSwitchDataPseudoInstruction.make(dexFile, in);
|
||||
return;
|
||||
case 0x02:
|
||||
//sparse switch
|
||||
in.setCursor(startPos);
|
||||
instruction = SparseSwitchDataPseudoInstruction.make(dexFile, in);
|
||||
return;
|
||||
case 0x03:
|
||||
//array data
|
||||
in.setCursor(startPos);
|
||||
instruction = ArrayDataPseudoInstruction.make(dexFile, in);
|
||||
return;
|
||||
default:
|
||||
throw new RuntimeException("Invalid 2nd byte for opcode 0x00");
|
||||
}
|
||||
}
|
||||
|
||||
Opcode opcode = Opcode.getOpcodeByValue(opByte);
|
||||
instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, in.readBytes(opcode.format.size - 1));
|
||||
}
|
||||
|
||||
public int place(int offset) {
|
||||
return offset + getSize(offset);
|
||||
}
|
||||
|
||||
public void copyTo(DexFile dexFile, InstructionField copy) {
|
||||
copy.instruction = instruction.cloneTo(dexFile);
|
||||
}
|
||||
|
||||
public int getSize(int offset) {
|
||||
if (this.needsAlign() && (offset % 4) != 0) {
|
||||
return instruction.encodedInstruction.length + 2;
|
||||
} else {
|
||||
return instruction.encodedInstruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needsAlign() {
|
||||
//true if the opcode is one of the "special format" opcodes
|
||||
return instruction.encodedInstruction[0] == 0 && instruction.encodedInstruction[1] > 0;
|
||||
}
|
||||
|
||||
public Instruction getInstruction() {
|
||||
return instruction;
|
||||
}
|
||||
}
|
@ -28,229 +28,231 @@
|
||||
|
||||
package org.jf.dexlib.code;
|
||||
|
||||
import org.jf.dexlib.code.Format.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public enum Opcode
|
||||
{
|
||||
NOP((byte)0x00, "NOP", (byte)2, ReferenceType.none, "10x"),
|
||||
MOVE((byte)0x01, "MOVE", (byte)2, ReferenceType.none, "12x"),
|
||||
MOVE_FROM16((byte)0x02, "MOVE/FROM16", (byte)4, ReferenceType.none, "22x"),
|
||||
MOVE_16((byte)0x03, "MOVE/16", (byte)6, ReferenceType.none, "32x"),
|
||||
MOVE_WIDE((byte)0x04, "MOVE-WIDE", (byte)2, ReferenceType.none, "12x"),
|
||||
MOVE_WIDE_FROM16((byte)0x05, "MOVE-WIDE/FROM16", (byte)4, ReferenceType.none, "22x"),
|
||||
MOVE_WIDE_16((byte)0x06, "MOVE-WIDE/16", (byte)6, ReferenceType.none, "32x"),
|
||||
MOVE_OBJECT((byte)0x07, "MOVE-OBJECT", (byte)2, ReferenceType.none, "12x"),
|
||||
MOVE_OBJECT_FROM16((byte)0x08, "MOVE-OBJECT/FROM16", (byte)4, ReferenceType.none, "22x"),
|
||||
MOVE_OBJECT_16((byte)0x09, "MOVE-OBJECT/16", (byte)6, ReferenceType.none, "32x"),
|
||||
MOVE_RESULT((byte)0x0a, "MOVE-RESULT", (byte)2, ReferenceType.none, "11x"),
|
||||
MOVE_RESULT_WIDE((byte)0x0b, "MOVE-RESULT-WIDE", (byte)2, ReferenceType.none, "11x"),
|
||||
MOVE_RESULT_OBJECT((byte)0x0c, "MOVE-RESULT-OBJECT", (byte)2, ReferenceType.none, "11x"),
|
||||
MOVE_EXCEPTION((byte)0x0d, "MOVE-EXCEPTION", (byte)2, ReferenceType.none, "11x"),
|
||||
RETURN_VOID((byte)0x0e, "RETURN-VOID", (byte)2, ReferenceType.none, "10x"),
|
||||
RETURN((byte)0x0f, "RETURN", (byte)2, ReferenceType.none, "11x"),
|
||||
RETURN_WIDE((byte)0x10, "RETURN-WIDE", (byte)2, ReferenceType.none, "11x"),
|
||||
RETURN_OBJECT((byte)0x11, "RETURN-OBJECT", (byte)2, ReferenceType.none, "11x"),
|
||||
CONST_4((byte)0x12, "CONST/4", (byte)2, ReferenceType.none, "11n"),
|
||||
CONST_16((byte)0x13, "CONST/16", (byte)4, ReferenceType.none, "21s"),
|
||||
CONST((byte)0x14, "CONST", (byte)6, ReferenceType.none, "31i"),
|
||||
CONST_HIGH16((byte)0x15, "CONST/HIGH16", (byte)4, ReferenceType.none, "21h"),
|
||||
CONST_WIDE_16((byte)0x16, "CONST-WIDE/16", (byte)4, ReferenceType.none, "21s"),
|
||||
CONST_WIDE_32((byte)0x17, "CONST-WIDE/32", (byte)6, ReferenceType.none, "31i"),
|
||||
CONST_WIDE((byte)0x18, "CONST-WIDE", (byte)10, ReferenceType.none, "51l"),
|
||||
CONST_WIDE_HIGH16((byte)0x19, "CONST-WIDE/HIGH16", (byte)4, ReferenceType.none, "21h"),
|
||||
CONST_STRING((byte)0x1a, "CONST-STRING", (byte)4, ReferenceType.string, "21c"),
|
||||
CONST_STRING_JUMBO((byte)0x1b, "CONST-STRING/JUMBO", (byte)6, ReferenceType.string, "31c"),
|
||||
CONST_CLASS((byte)0x1c, "CONST-CLASS", (byte)4, ReferenceType.type, "21c"),
|
||||
MONITOR_ENTER((byte)0x1d, "MONITOR-ENTER", (byte)2, ReferenceType.none, "11x"),
|
||||
MONITOR_EXIT((byte)0x1e, "MONITOR-EXIT", (byte)2, ReferenceType.none, "11x"),
|
||||
CHECK_CAST((byte)0x1f, "CHECK-CAST", (byte)4, ReferenceType.type, "21c"),
|
||||
INSTANCE_OF((byte)0x20, "INSTANCE-OF", (byte)4, ReferenceType.type, "22c"),
|
||||
ARRAY_LENGTH((byte)0x21, "ARRAY-LENGTH", (byte)2, ReferenceType.none, "12x"),
|
||||
NEW_INSTANCE((byte)0x22, "NEW-INSTANCE", (byte)4, ReferenceType.type, "21c"),
|
||||
NEW_ARRAY((byte)0x23, "NEW-ARRAY", (byte)4, ReferenceType.type, "22c"),
|
||||
FILLED_NEW_ARRAY((byte)0x24, "FILLED-NEW-ARRAY", (byte)6, ReferenceType.type, "35c"),
|
||||
FILLED_NEW_ARRAY_RANGE((byte)0x25, "FILLED-NEW-ARRAY/RANGE", (byte)6, ReferenceType.type, "3rc"),
|
||||
FILL_ARRAY_DATA((byte)0x26, "FILL-ARRAY-DATA", (byte)6, ReferenceType.none, "31t"),
|
||||
THROW((byte)0x27, "THROW", (byte)2, ReferenceType.none, "11x"),
|
||||
GOTO((byte)0x28, "GOTO", (byte)2, ReferenceType.none, "10t"),
|
||||
GOTO_16((byte)0x29, "GOTO/16", (byte)4, ReferenceType.none, "20t"),
|
||||
GOTO_32((byte)0x2a, "GOTO/32", (byte)6, ReferenceType.none, "30t"),
|
||||
PACKED_SWITCH((byte)0x2b, "PACKED-SWITCH", (byte)6, ReferenceType.none, "31t"),
|
||||
SPARSE_SWITCH((byte)0x2c, "SPARSE-SWITCH", (byte)6, ReferenceType.none, "31t"),
|
||||
CMPL_FLOAT((byte)0x2d, "CMPL-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
CMPG_FLOAT((byte)0x2e, "CMPG-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
CMPL_DOUBLE((byte)0x2f, "CMPL-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
CMPG_DOUBLE((byte)0x30, "CMPG-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
CMP_LONG((byte)0x31, "CMP-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
IF_EQ((byte)0x32, "IF-EQ", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_NE((byte)0x33, "IF-NE", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_LT((byte)0x34, "IF-LT", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_GE((byte)0x35, "IF-GE", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_GT((byte)0x36, "IF-GT", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_LE((byte)0x37, "IF-LE", (byte)4, ReferenceType.none, "22t"),
|
||||
IF_EQZ((byte)0x38, "IF-EQZ", (byte)4, ReferenceType.none, "21t"),
|
||||
IF_NEZ((byte)0x39, "IF-NEZ", (byte)4, ReferenceType.none, "21t"),
|
||||
IF_LTZ((byte)0x3a, "IF-LTZ", (byte)4, ReferenceType.none, "21t"),
|
||||
IF_GEZ((byte)0x3b, "IF-GEZ", (byte)4, ReferenceType.none, "21t"),
|
||||
IF_GTZ((byte)0x3c, "IF-GTZ", (byte)4, ReferenceType.none, "21t"),
|
||||
IF_LEZ((byte)0x3d, "IF-LEZ", (byte)4, ReferenceType.none, "21t"),
|
||||
AGET((byte)0x44, "AGET", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_WIDE((byte)0x45, "AGET-WIDE", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_OBJECT((byte)0x46, "AGET-OBJECT", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_BOOLEAN((byte)0x47, "AGET-BOOLEAN", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_BYTE((byte)0x48, "AGET-BYTE", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_CHAR((byte)0x49, "AGET-CHAR", (byte)4, ReferenceType.none, "23x"),
|
||||
AGET_SHORT((byte)0x4a, "AGET-SHORT", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT((byte)0x4b, "APUT", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_WIDE((byte)0x4c, "APUT-WIDE", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_OBJECT((byte)0x4d, "APUT-OBJECT", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_BOOLEAN((byte)0x4e, "APUT-BOOLEAN", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_BYTE((byte)0x4f, "APUT-BYTE", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_CHAR((byte)0x50, "APUT-CHAR", (byte)4, ReferenceType.none, "23x"),
|
||||
APUT_SHORT((byte)0x51, "APUT-SHORT", (byte)4, ReferenceType.none, "23x"),
|
||||
IGET((byte)0x52, "IGET", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_WIDE((byte)0x53, "IGET-WIDE", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_OBJECT((byte)0x54, "IGET-OBJECT", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_BOOLEAN((byte)0x55, "IGET-BOOLEAN", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_BYTE((byte)0x56, "IGET-BYTE", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_CHAR((byte)0x57, "IGET-CHAR", (byte)4, ReferenceType.field, "22c"),
|
||||
IGET_SHORT((byte)0x58, "IGET-SHORT", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT((byte)0x59, "IPUT", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_WIDE((byte)0x5a, "IPUT-WIDE", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_OBJECT((byte)0x5b, "IPUT-OBJECT", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_BOOLEAN((byte)0x5c, "IPUT-BOOLEAN", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_BYTE((byte)0x5d, "IPUT-BYTE", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_CHAR((byte)0x5e, "IPUT-CHAR", (byte)4, ReferenceType.field, "22c"),
|
||||
IPUT_SHORT((byte)0x5f, "IPUT-SHORT", (byte)4, ReferenceType.field, "22c"),
|
||||
SGET((byte)0x60, "SGET", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_WIDE((byte)0x61, "SGET-WIDE", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_OBJECT((byte)0x62, "SGET-OBJECT", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_BOOLEAN((byte)0x63, "SGET-BOOLEAN", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_BYTE((byte)0x64, "SGET-BYTE", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_CHAR((byte)0x65, "SGET-CHAR", (byte)4, ReferenceType.field, "21c"),
|
||||
SGET_SHORT((byte)0x66, "SGET-SHORT", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT((byte)0x67, "SPUT", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_WIDE((byte)0x68, "SPUT-WIDE", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_OBJECT((byte)0x69, "SPUT-OBJECT", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_BOOLEAN((byte)0x6a, "SPUT-BOOLEAN", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_BYTE((byte)0x6b, "SPUT-BYTE", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_CHAR((byte)0x6c, "SPUT-CHAR", (byte)4, ReferenceType.field, "21c"),
|
||||
SPUT_SHORT((byte)0x6d, "SPUT-SHORT", (byte)4, ReferenceType.field, "21c"),
|
||||
INVOKE_VIRTUAL((byte)0x6e, "INVOKE-VIRTUAL", (byte)6, ReferenceType.method, "35c"),
|
||||
INVOKE_SUPER((byte)0x6f, "INVOKE-SUPER", (byte)6, ReferenceType.method, "35c"),
|
||||
INVOKE_DIRECT((byte)0x70, "INVOKE-DIRECT", (byte)6, ReferenceType.method, "35c"),
|
||||
INVOKE_STATIC((byte)0x71, "INVOKE-STATIC", (byte)6, ReferenceType.method, "35c"),
|
||||
INVOKE_INTERFACE((byte)0x72, "INVOKE-INTERFACE", (byte)6, ReferenceType.method, "35c"),
|
||||
INVOKE_VIRTUAL_RANGE((byte)0x74, "INVOKE-VIRTUAL/RANGE", (byte)6, ReferenceType.method, "3rc"),
|
||||
INVOKE_SUPER_RANGE((byte)0x75, "INVOKE-SUPER/RANGE", (byte)6, ReferenceType.method, "3rc"),
|
||||
INVOKE_DIRECT_RANGE((byte)0x76, "INVOKE-DIRECT/RANGE", (byte)6, ReferenceType.method, "3rc"),
|
||||
INVOKE_STATIC_RANGE((byte)0x77, "INVOKE-STATIC/RANGE", (byte)6, ReferenceType.method, "3rc"),
|
||||
INVOKE_INTERFACE_RANGE((byte)0x78, "INVOKE-INTERFACE/RANGE", (byte)6, ReferenceType.method, "3rc"),
|
||||
NEG_INT((byte)0x7b, "NEG-INT", (byte)2, ReferenceType.none, "12x"),
|
||||
NOT_INT((byte)0x7c, "NOT-INT", (byte)2, ReferenceType.none, "12x"),
|
||||
NEG_LONG((byte)0x7d, "NEG-LONG", (byte)2, ReferenceType.none, "12x"),
|
||||
NOT_LONG((byte)0x7e, "NOT-LONG", (byte)2, ReferenceType.none, "12x"),
|
||||
NEG_FLOAT((byte)0x7f, "NEG-FLOAT", (byte)2, ReferenceType.none, "12x"),
|
||||
NEG_DOUBLE((byte)0x80, "NEG-DOUBLE", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_LONG((byte)0x81, "INT-TO-LONG", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_FLOAT((byte)0x82, "INT-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_DOUBLE((byte)0x83, "INT-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
|
||||
LONG_TO_INT((byte)0x84, "LONG-TO-INT", (byte)2, ReferenceType.none, "12x"),
|
||||
LONG_TO_FLOAT((byte)0x85, "LONG-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
|
||||
LONG_TO_DOUBLE((byte)0x86, "LONG-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
|
||||
FLOAT_TO_INT((byte)0x87, "FLOAT-TO-INT", (byte)2, ReferenceType.none, "12x"),
|
||||
FLOAT_TO_LONG((byte)0x88, "FLOAT-TO-LONG", (byte)2, ReferenceType.none, "12x"),
|
||||
FLOAT_TO_DOUBLE((byte)0x89, "FLOAT-TO-DOUBLE", (byte)2, ReferenceType.none, "12x"),
|
||||
DOUBLE_TO_INT((byte)0x8a, "DOUBLE-TO-INT", (byte)2, ReferenceType.none, "12x"),
|
||||
DOUBLE_TO_LONG((byte)0x8b, "DOUBLE-TO-LONG", (byte)2, ReferenceType.none, "12x"),
|
||||
DOUBLE_TO_FLOAT((byte)0x8c, "DOUBLE-TO-FLOAT", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_BYTE((byte)0x8d, "INT-TO-BYTE", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_CHAR((byte)0x8e, "INT-TO-CHAR", (byte)2, ReferenceType.none, "12x"),
|
||||
INT_TO_SHORT((byte)0x8f, "INT-TO-SHORT", (byte)2, ReferenceType.none, "12x"),
|
||||
ADD_INT((byte)0x90, "ADD-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
SUB_INT((byte)0x91, "SUB-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
MUL_INT((byte)0x92, "MUL-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
DIV_INT((byte)0x93, "DIV-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
REM_INT((byte)0x94, "REM-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
AND_INT((byte)0x95, "AND-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
OR_INT((byte)0x96, "OR-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
XOR_INT((byte)0x97, "XOR-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
SHL_INT((byte)0x98, "SHL-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
SHR_INT((byte)0x99, "SHR-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
USHR_INT((byte)0x9a, "USHR-INT", (byte)4, ReferenceType.none, "23x"),
|
||||
ADD_LONG((byte)0x9b, "ADD-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
SUB_LONG((byte)0x9c, "SUB-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
MUL_LONG((byte)0x9d, "MUL-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
DIV_LONG((byte)0x9e, "DIV-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
REM_LONG((byte)0x9f, "REM-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
AND_LONG((byte)0xa0, "AND-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
OR_LONG((byte)0xa1, "OR-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
XOR_LONG((byte)0xa2, "XOR-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
SHL_LONG((byte)0xa3, "SHL-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
SHR_LONG((byte)0xa4, "SHR-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
USHR_LONG((byte)0xa5, "USHR-LONG", (byte)4, ReferenceType.none, "23x"),
|
||||
ADD_FLOAT((byte)0xa6, "ADD-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
SUB_FLOAT((byte)0xa7, "SUB-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
MUL_FLOAT((byte)0xa8, "MUL-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
DIV_FLOAT((byte)0xa9, "DIV-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
REM_FLOAT((byte)0xaa, "REM-FLOAT", (byte)4, ReferenceType.none, "23x"),
|
||||
ADD_DOUBLE((byte)0xab, "ADD-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
SUB_DOUBLE((byte)0xac, "SUB-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
MUL_DOUBLE((byte)0xad, "MUL-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
DIV_DOUBLE((byte)0xae, "DIV-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
REM_DOUBLE((byte)0xaf, "REM-DOUBLE", (byte)4, ReferenceType.none, "23x"),
|
||||
ADD_INT_2ADDR((byte)0xb0, "ADD-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SUB_INT_2ADDR((byte)0xb1, "SUB-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
MUL_INT_2ADDR((byte)0xb2, "MUL-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
DIV_INT_2ADDR((byte)0xb3, "DIV-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
REM_INT_2ADDR((byte)0xb4, "REM-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
AND_INT_2ADDR((byte)0xb5, "AND-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
OR_INT_2ADDR((byte)0xb6, "OR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
XOR_INT_2ADDR((byte)0xb7, "XOR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SHL_INT_2ADDR((byte)0xb8, "SHL-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SHR_INT_2ADDR((byte)0xb9, "SHR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
USHR_INT_2ADDR((byte)0xba, "USHR-INT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
ADD_LONG_2ADDR((byte)0xbb, "ADD-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SUB_LONG_2ADDR((byte)0xbc, "SUB-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
MUL_LONG_2ADDR((byte)0xbd, "MUL-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
DIV_LONG_2ADDR((byte)0xbe, "DIV-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
REM_LONG_2ADDR((byte)0xbf, "REM-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
AND_LONG_2ADDR((byte)0xc0, "AND-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
OR_LONG_2ADDR((byte)0xc1, "OR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
XOR_LONG_2ADDR((byte)0xc2, "XOR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SHL_LONG_2ADDR((byte)0xc3, "SHL-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SHR_LONG_2ADDR((byte)0xc4, "SHR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
USHR_LONG_2ADDR((byte)0xc5, "USHR-LONG/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
ADD_FLOAT_2ADDR((byte)0xc6, "ADD-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SUB_FLOAT_2ADDR((byte)0xc7, "SUB-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
MUL_FLOAT_2ADDR((byte)0xc8, "MUL-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
DIV_FLOAT_2ADDR((byte)0xc9, "DIV-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
REM_FLOAT_2ADDR((byte)0xca, "REM-FLOAT/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
ADD_DOUBLE_2ADDR((byte)0xcb, "ADD-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
SUB_DOUBLE_2ADDR((byte)0xcc, "SUB-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
MUL_DOUBLE_2ADDR((byte)0xcd, "MUL-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
DIV_DOUBLE_2ADDR((byte)0xce, "DIV-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
REM_DOUBLE_2ADDR((byte)0xcf, "REM-DOUBLE/2ADDR", (byte)2, ReferenceType.none, "12x"),
|
||||
ADD_INT_LIT16((byte)0xd0, "ADD-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
RSUB_INT((byte)0xd1, "RSUB-INT", (byte)4, ReferenceType.none, "22s"),
|
||||
MUL_INT_LIT16((byte)0xd2, "MUL-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
DIV_INT_LIT16((byte)0xd3, "DIV-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
REM_INT_LIT16((byte)0xd4, "REM-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
AND_INT_LIT16((byte)0xd5, "AND-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
OR_INT_LIT16((byte)0xd6, "OR-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
XOR_INT_LIT16((byte)0xd7, "XOR-INT/LIT16", (byte)4, ReferenceType.none, "22s"),
|
||||
ADD_INT_LIT8((byte)0xd8, "ADD-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
RSUB_INT_LIT8((byte)0xd9, "RSUB-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
MUL_INT_LIT8((byte)0xda, "MUL-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
DIV_INT_LIT8((byte)0xdb, "DIV-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
REM_INT_LIT8((byte)0xdc, "REM-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
AND_INT_LIT8((byte)0xdd, "AND-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
OR_INT_LIT8((byte)0xde, "OR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
XOR_INT_LIT8((byte)0xdf, "XOR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
SHL_INT_LIT8((byte)0xe0, "SHL-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
SHR_INT_LIT8((byte)0xe1, "SHR-INT/LIT8", (byte)4, ReferenceType.none, "22b"),
|
||||
USHR_INT_LIT8((byte)0xe2, "USHR-INT/LIT8", (byte)4, ReferenceType.none, "22b");
|
||||
NOP((byte)0x00, "nop", ReferenceType.none, Format.Format10x),
|
||||
MOVE((byte)0x01, "move", ReferenceType.none, Format.Format12x),
|
||||
MOVE_FROM16((byte)0x02, "move/from16", ReferenceType.none, Format.Format22x),
|
||||
MOVE_16((byte)0x03, "move/16", ReferenceType.none, Format.Format32x),
|
||||
MOVE_WIDE((byte)0x04, "move-wide", ReferenceType.none, Format.Format12x),
|
||||
MOVE_WIDE_FROM16((byte)0x05, "move-wide/from16", ReferenceType.none, Format.Format22x),
|
||||
MOVE_WIDE_16((byte)0x06, "move-wide/16", ReferenceType.none, Format.Format32x),
|
||||
MOVE_OBJECT((byte)0x07, "move-object", ReferenceType.none, Format.Format12x),
|
||||
MOVE_OBJECT_FROM16((byte)0x08, "move-object/from16", ReferenceType.none, Format.Format22x),
|
||||
MOVE_OBJECT_16((byte)0x09, "move-object/16", ReferenceType.none, Format.Format32x),
|
||||
MOVE_RESULT((byte)0x0a, "move-result", ReferenceType.none, Format.Format11x),
|
||||
MOVE_RESULT_WIDE((byte)0x0b, "move-result-wide", ReferenceType.none, Format.Format11x),
|
||||
MOVE_RESULT_OBJECT((byte)0x0c, "move-result-object", ReferenceType.none, Format.Format11x),
|
||||
MOVE_EXCEPTION((byte)0x0d, "move-exception", ReferenceType.none, Format.Format11x),
|
||||
RETURN_VOID((byte)0x0e, "return-void", ReferenceType.none, Format.Format10x),
|
||||
RETURN((byte)0x0f, "return", ReferenceType.none, Format.Format11x),
|
||||
RETURN_WIDE((byte)0x10, "return-wide", ReferenceType.none, Format.Format11x),
|
||||
RETURN_OBJECT((byte)0x11, "return-object", ReferenceType.none, Format.Format11x),
|
||||
CONST_4((byte)0x12, "const/4", ReferenceType.none, Format.Format11n),
|
||||
CONST_16((byte)0x13, "const/16", ReferenceType.none, Format.Format21s),
|
||||
CONST((byte)0x14, "const", ReferenceType.none, Format.Format31i),
|
||||
CONST_HIGH16((byte)0x15, "const/high16", ReferenceType.none, Format.Format21h),
|
||||
CONST_WIDE_16((byte)0x16, "const-wide/16", ReferenceType.none, Format.Format21s),
|
||||
CONST_WIDE_32((byte)0x17, "const-wide/32", ReferenceType.none, Format.Format31i),
|
||||
CONST_WIDE((byte)0x18, "const-wide", ReferenceType.none, Format.Format51l),
|
||||
CONST_WIDE_HIGH16((byte)0x19, "const-wide/high16", ReferenceType.none, Format.Format21h),
|
||||
CONST_STRING((byte)0x1a, "const-string", ReferenceType.string, Format.Format21c),
|
||||
CONST_STRING_JUMBO((byte)0x1b, "const-string/jumbo", ReferenceType.string, Format.Format31c),
|
||||
CONST_CLASS((byte)0x1c, "const-class", ReferenceType.type, Format.Format21c),
|
||||
MONITOR_ENTER((byte)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x),
|
||||
MONITOR_EXIT((byte)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x),
|
||||
CHECK_CAST((byte)0x1f, "check-cast", ReferenceType.type, Format.Format21c),
|
||||
INSTANCE_OF((byte)0x20, "instance-of", ReferenceType.type, Format.Format22c),
|
||||
ARRAY_LENGTH((byte)0x21, "array-length", ReferenceType.none, Format.Format12x),
|
||||
NEW_INSTANCE((byte)0x22, "new-instance", ReferenceType.type, Format.Format21c),
|
||||
NEW_ARRAY((byte)0x23, "new-array", ReferenceType.type, Format.Format22c),
|
||||
FILLED_NEW_ARRAY((byte)0x24, "filled-new-array", ReferenceType.type, Format.Format35c),
|
||||
FILLED_NEW_ARRAY_RANGE((byte)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc),
|
||||
FILL_ARRAY_DATA((byte)0x26, "fill-array-data", ReferenceType.none, Format.Format31t),
|
||||
THROW((byte)0x27, "throw", ReferenceType.none, Format.Format11x),
|
||||
GOTO((byte)0x28, "goto", ReferenceType.none, Format.Format10t),
|
||||
GOTO_16((byte)0x29, "goto/16", ReferenceType.none, Format.Format20t),
|
||||
GOTO_32((byte)0x2a, "goto/32", ReferenceType.none, Format.Format30t),
|
||||
PACKED_SWITCH((byte)0x2b, "packed-switch", ReferenceType.none, Format.Format31t),
|
||||
SPARSE_SWITCH((byte)0x2c, "sparse-switch", ReferenceType.none, Format.Format31t),
|
||||
CMPL_FLOAT((byte)0x2d, "cmpl-float", ReferenceType.none, Format.Format23x),
|
||||
CMPG_FLOAT((byte)0x2e, "cmpg-float", ReferenceType.none, Format.Format23x),
|
||||
CMPL_DOUBLE((byte)0x2f, "cmpl-double", ReferenceType.none, Format.Format23x),
|
||||
CMPG_DOUBLE((byte)0x30, "cmpg-double", ReferenceType.none, Format.Format23x),
|
||||
CMP_LONG((byte)0x31, "cmp-long", ReferenceType.none, Format.Format23x),
|
||||
IF_EQ((byte)0x32, "if-eq", ReferenceType.none, Format.Format22t),
|
||||
IF_NE((byte)0x33, "if-ne", ReferenceType.none, Format.Format22t),
|
||||
IF_LT((byte)0x34, "if-lt", ReferenceType.none, Format.Format22t),
|
||||
IF_GE((byte)0x35, "if-ge", ReferenceType.none, Format.Format22t),
|
||||
IF_GT((byte)0x36, "if-gt", ReferenceType.none, Format.Format22t),
|
||||
IF_LE((byte)0x37, "if-le", ReferenceType.none, Format.Format22t),
|
||||
IF_EQZ((byte)0x38, "if-eqz", ReferenceType.none, Format.Format21t),
|
||||
IF_NEZ((byte)0x39, "if-nez", ReferenceType.none, Format.Format21t),
|
||||
IF_LTZ((byte)0x3a, "if-ltz", ReferenceType.none, Format.Format21t),
|
||||
IF_GEZ((byte)0x3b, "if-gez", ReferenceType.none, Format.Format21t),
|
||||
IF_GTZ((byte)0x3c, "if-gtz", ReferenceType.none, Format.Format21t),
|
||||
IF_LEZ((byte)0x3d, "if-lez", ReferenceType.none, Format.Format21t),
|
||||
AGET((byte)0x44, "aget", ReferenceType.none, Format.Format23x),
|
||||
AGET_WIDE((byte)0x45, "aget-wide", ReferenceType.none, Format.Format23x),
|
||||
AGET_OBJECT((byte)0x46, "aget-object", ReferenceType.none, Format.Format23x),
|
||||
AGET_BOOLEAN((byte)0x47, "aget-boolean", ReferenceType.none, Format.Format23x),
|
||||
AGET_BYTE((byte)0x48, "aget-byte", ReferenceType.none, Format.Format23x),
|
||||
AGET_CHAR((byte)0x49, "aget-char", ReferenceType.none, Format.Format23x),
|
||||
AGET_SHORT((byte)0x4a, "aget-short", ReferenceType.none, Format.Format23x),
|
||||
APUT((byte)0x4b, "aput", ReferenceType.none, Format.Format23x),
|
||||
APUT_WIDE((byte)0x4c, "aput-wide", ReferenceType.none, Format.Format23x),
|
||||
APUT_OBJECT((byte)0x4d, "aput-object", ReferenceType.none, Format.Format23x),
|
||||
APUT_BOOLEAN((byte)0x4e, "aput-boolean", ReferenceType.none, Format.Format23x),
|
||||
APUT_BYTE((byte)0x4f, "aput-byte", ReferenceType.none, Format.Format23x),
|
||||
APUT_CHAR((byte)0x50, "aput-char", ReferenceType.none, Format.Format23x),
|
||||
APUT_SHORT((byte)0x51, "aput-short", ReferenceType.none, Format.Format23x),
|
||||
IGET((byte)0x52, "iget", ReferenceType.field, Format.Format22c),
|
||||
IGET_WIDE((byte)0x53, "iget-wide", ReferenceType.field, Format.Format22c),
|
||||
IGET_OBJECT((byte)0x54, "iget-object", ReferenceType.field, Format.Format22c),
|
||||
IGET_BOOLEAN((byte)0x55, "iget-boolean", ReferenceType.field, Format.Format22c),
|
||||
IGET_BYTE((byte)0x56, "iget-byte", ReferenceType.field, Format.Format22c),
|
||||
IGET_CHAR((byte)0x57, "iget-char", ReferenceType.field, Format.Format22c),
|
||||
IGET_SHORT((byte)0x58, "iget-short", ReferenceType.field, Format.Format22c),
|
||||
IPUT((byte)0x59, "iput", ReferenceType.field, Format.Format22c),
|
||||
IPUT_WIDE((byte)0x5a, "iput-wide", ReferenceType.field, Format.Format22c),
|
||||
IPUT_OBJECT((byte)0x5b, "iput-object", ReferenceType.field, Format.Format22c),
|
||||
IPUT_BOOLEAN((byte)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c),
|
||||
IPUT_BYTE((byte)0x5d, "iput-byte", ReferenceType.field, Format.Format22c),
|
||||
IPUT_CHAR((byte)0x5e, "iput-char", ReferenceType.field, Format.Format22c),
|
||||
IPUT_SHORT((byte)0x5f, "iput-short", ReferenceType.field, Format.Format22c),
|
||||
SGET((byte)0x60, "sget", ReferenceType.field, Format.Format21c),
|
||||
SGET_WIDE((byte)0x61, "sget-wide", ReferenceType.field, Format.Format21c),
|
||||
SGET_OBJECT((byte)0x62, "sget-object", ReferenceType.field, Format.Format21c),
|
||||
SGET_BOOLEAN((byte)0x63, "sget-boolean", ReferenceType.field, Format.Format21c),
|
||||
SGET_BYTE((byte)0x64, "sget-byte", ReferenceType.field, Format.Format21c),
|
||||
SGET_CHAR((byte)0x65, "sget-char", ReferenceType.field, Format.Format21c),
|
||||
SGET_SHORT((byte)0x66, "sget-short", ReferenceType.field, Format.Format21c),
|
||||
SPUT((byte)0x67, "sput", ReferenceType.field, Format.Format21c),
|
||||
SPUT_WIDE((byte)0x68, "sput-wide", ReferenceType.field, Format.Format21c),
|
||||
SPUT_OBJECT((byte)0x69, "sput-object", ReferenceType.field, Format.Format21c),
|
||||
SPUT_BOOLEAN((byte)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c),
|
||||
SPUT_BYTE((byte)0x6b, "sput-byte", ReferenceType.field, Format.Format21c),
|
||||
SPUT_CHAR((byte)0x6c, "sput-char", ReferenceType.field, Format.Format21c),
|
||||
SPUT_SHORT((byte)0x6d, "sput-short", ReferenceType.field, Format.Format21c),
|
||||
INVOKE_VIRTUAL((byte)0x6e, "invoke-virtual", ReferenceType.method, Format.Format35c),
|
||||
INVOKE_SUPER((byte)0x6f, "invoke-super", ReferenceType.method, Format.Format35c),
|
||||
INVOKE_DIRECT((byte)0x70, "invoke-direct", ReferenceType.method, Format.Format35c),
|
||||
INVOKE_STATIC((byte)0x71, "invoke-static", ReferenceType.method, Format.Format35c),
|
||||
INVOKE_INTERFACE((byte)0x72, "invoke-interface", ReferenceType.method, Format.Format35c),
|
||||
INVOKE_VIRTUAL_RANGE((byte)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc),
|
||||
INVOKE_SUPER_RANGE((byte)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc),
|
||||
INVOKE_DIRECT_RANGE((byte)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc),
|
||||
INVOKE_STATIC_RANGE((byte)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc),
|
||||
INVOKE_INTERFACE_RANGE((byte)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc),
|
||||
NEG_INT((byte)0x7b, "neg-int", ReferenceType.none, Format.Format12x),
|
||||
NOT_INT((byte)0x7c, "not-int", ReferenceType.none, Format.Format12x),
|
||||
NEG_LONG((byte)0x7d, "neg-long", ReferenceType.none, Format.Format12x),
|
||||
NOT_LONG((byte)0x7e, "not-long", ReferenceType.none, Format.Format12x),
|
||||
NEG_FLOAT((byte)0x7f, "neg-float", ReferenceType.none, Format.Format12x),
|
||||
NEG_DOUBLE((byte)0x80, "neg-double", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_LONG((byte)0x81, "int-to-long", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_FLOAT((byte)0x82, "int-to-float", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_DOUBLE((byte)0x83, "int-to-double", ReferenceType.none, Format.Format12x),
|
||||
LONG_TO_INT((byte)0x84, "long-to-int", ReferenceType.none, Format.Format12x),
|
||||
LONG_TO_FLOAT((byte)0x85, "long-to-float", ReferenceType.none, Format.Format12x),
|
||||
LONG_TO_DOUBLE((byte)0x86, "long-to-double", ReferenceType.none, Format.Format12x),
|
||||
FLOAT_TO_INT((byte)0x87, "float-to-int", ReferenceType.none, Format.Format12x),
|
||||
FLOAT_TO_LONG((byte)0x88, "float-to-long", ReferenceType.none, Format.Format12x),
|
||||
FLOAT_TO_DOUBLE((byte)0x89, "float-to-double", ReferenceType.none, Format.Format12x),
|
||||
DOUBLE_TO_INT((byte)0x8a, "double-to-int", ReferenceType.none, Format.Format12x),
|
||||
DOUBLE_TO_LONG((byte)0x8b, "double-to-long", ReferenceType.none, Format.Format12x),
|
||||
DOUBLE_TO_FLOAT((byte)0x8c, "double-to-float", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_BYTE((byte)0x8d, "int-to-byte", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_CHAR((byte)0x8e, "int-to-char", ReferenceType.none, Format.Format12x),
|
||||
INT_TO_SHORT((byte)0x8f, "int-to-short", ReferenceType.none, Format.Format12x),
|
||||
ADD_INT((byte)0x90, "add-int", ReferenceType.none, Format.Format23x),
|
||||
SUB_INT((byte)0x91, "sub-int", ReferenceType.none, Format.Format23x),
|
||||
MUL_INT((byte)0x92, "mul-int", ReferenceType.none, Format.Format23x),
|
||||
DIV_INT((byte)0x93, "div-int", ReferenceType.none, Format.Format23x),
|
||||
REM_INT((byte)0x94, "rem-int", ReferenceType.none, Format.Format23x),
|
||||
AND_INT((byte)0x95, "and-int", ReferenceType.none, Format.Format23x),
|
||||
OR_INT((byte)0x96, "or-int", ReferenceType.none, Format.Format23x),
|
||||
XOR_INT((byte)0x97, "xor-int", ReferenceType.none, Format.Format23x),
|
||||
SHL_INT((byte)0x98, "shl-int", ReferenceType.none, Format.Format23x),
|
||||
SHR_INT((byte)0x99, "shr-int", ReferenceType.none, Format.Format23x),
|
||||
USHR_INT((byte)0x9a, "ushr-int", ReferenceType.none, Format.Format23x),
|
||||
ADD_LONG((byte)0x9b, "add-long", ReferenceType.none, Format.Format23x),
|
||||
SUB_LONG((byte)0x9c, "sub-long", ReferenceType.none, Format.Format23x),
|
||||
MUL_LONG((byte)0x9d, "mul-long", ReferenceType.none, Format.Format23x),
|
||||
DIV_LONG((byte)0x9e, "div-long", ReferenceType.none, Format.Format23x),
|
||||
REM_LONG((byte)0x9f, "rem-long", ReferenceType.none, Format.Format23x),
|
||||
AND_LONG((byte)0xa0, "and-long", ReferenceType.none, Format.Format23x),
|
||||
OR_LONG((byte)0xa1, "or-long", ReferenceType.none, Format.Format23x),
|
||||
XOR_LONG((byte)0xa2, "xor-long", ReferenceType.none, Format.Format23x),
|
||||
SHL_LONG((byte)0xa3, "shl-long", ReferenceType.none, Format.Format23x),
|
||||
SHR_LONG((byte)0xa4, "shr-long", ReferenceType.none, Format.Format23x),
|
||||
USHR_LONG((byte)0xa5, "ushr-long", ReferenceType.none, Format.Format23x),
|
||||
ADD_FLOAT((byte)0xa6, "add-float", ReferenceType.none, Format.Format23x),
|
||||
SUB_FLOAT((byte)0xa7, "sub-float", ReferenceType.none, Format.Format23x),
|
||||
MUL_FLOAT((byte)0xa8, "mul-float", ReferenceType.none, Format.Format23x),
|
||||
DIV_FLOAT((byte)0xa9, "div-float", ReferenceType.none, Format.Format23x),
|
||||
REM_FLOAT((byte)0xaa, "rem-float", ReferenceType.none, Format.Format23x),
|
||||
ADD_DOUBLE((byte)0xab, "add-double", ReferenceType.none, Format.Format23x),
|
||||
SUB_DOUBLE((byte)0xac, "sub-double", ReferenceType.none, Format.Format23x),
|
||||
MUL_DOUBLE((byte)0xad, "mul-double", ReferenceType.none, Format.Format23x),
|
||||
DIV_DOUBLE((byte)0xae, "div-double", ReferenceType.none, Format.Format23x),
|
||||
REM_DOUBLE((byte)0xaf, "rem-double", ReferenceType.none, Format.Format23x),
|
||||
ADD_INT_2ADDR((byte)0xb0, "add-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
SUB_INT_2ADDR((byte)0xb1, "sub-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
MUL_INT_2ADDR((byte)0xb2, "mul-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
DIV_INT_2ADDR((byte)0xb3, "div-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
REM_INT_2ADDR((byte)0xb4, "rem-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
AND_INT_2ADDR((byte)0xb5, "and-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
OR_INT_2ADDR((byte)0xb6, "or-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
XOR_INT_2ADDR((byte)0xb7, "xor-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
SHL_INT_2ADDR((byte)0xb8, "shl-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
SHR_INT_2ADDR((byte)0xb9, "shr-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
USHR_INT_2ADDR((byte)0xba, "ushr-int/2addr", ReferenceType.none, Format.Format12x),
|
||||
ADD_LONG_2ADDR((byte)0xbb, "add-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
SUB_LONG_2ADDR((byte)0xbc, "sub-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
MUL_LONG_2ADDR((byte)0xbd, "mul-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
DIV_LONG_2ADDR((byte)0xbe, "div-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
REM_LONG_2ADDR((byte)0xbf, "rem-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
AND_LONG_2ADDR((byte)0xc0, "and-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
OR_LONG_2ADDR((byte)0xc1, "or-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
XOR_LONG_2ADDR((byte)0xc2, "xor-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
SHL_LONG_2ADDR((byte)0xc3, "shl-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
SHR_LONG_2ADDR((byte)0xc4, "shr-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
USHR_LONG_2ADDR((byte)0xc5, "ushr-long/2addr", ReferenceType.none, Format.Format12x),
|
||||
ADD_FLOAT_2ADDR((byte)0xc6, "add-float/2addr", ReferenceType.none, Format.Format12x),
|
||||
SUB_FLOAT_2ADDR((byte)0xc7, "sub-float/2addr", ReferenceType.none, Format.Format12x),
|
||||
MUL_FLOAT_2ADDR((byte)0xc8, "mul-float/2addr", ReferenceType.none, Format.Format12x),
|
||||
DIV_FLOAT_2ADDR((byte)0xc9, "div-float/2addr", ReferenceType.none, Format.Format12x),
|
||||
REM_FLOAT_2ADDR((byte)0xca, "rem-float/2addr", ReferenceType.none, Format.Format12x),
|
||||
ADD_DOUBLE_2ADDR((byte)0xcb, "add-double/2addr", ReferenceType.none, Format.Format12x),
|
||||
SUB_DOUBLE_2ADDR((byte)0xcc, "sub-double/2addr", ReferenceType.none, Format.Format12x),
|
||||
MUL_DOUBLE_2ADDR((byte)0xcd, "mul-double/2addr", ReferenceType.none, Format.Format12x),
|
||||
DIV_DOUBLE_2ADDR((byte)0xce, "div-double/2addr", ReferenceType.none, Format.Format12x),
|
||||
REM_DOUBLE_2ADDR((byte)0xcf, "rem-double/2addr", ReferenceType.none, Format.Format12x),
|
||||
ADD_INT_LIT16((byte)0xd0, "add-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
RSUB_INT((byte)0xd1, "rsub-int", ReferenceType.none, Format.Format22s),
|
||||
MUL_INT_LIT16((byte)0xd2, "mul-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
DIV_INT_LIT16((byte)0xd3, "div-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
REM_INT_LIT16((byte)0xd4, "rem-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
AND_INT_LIT16((byte)0xd5, "and-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
OR_INT_LIT16((byte)0xd6, "or-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
XOR_INT_LIT16((byte)0xd7, "xor-int/lit16", ReferenceType.none, Format.Format22s),
|
||||
ADD_INT_LIT8((byte)0xd8, "add-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
RSUB_INT_LIT8((byte)0xd9, "rsub-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
MUL_INT_LIT8((byte)0xda, "mul-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
DIV_INT_LIT8((byte)0xdb, "div-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
REM_INT_LIT8((byte)0xdc, "rem-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
AND_INT_LIT8((byte)0xdd, "and-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
OR_INT_LIT8((byte)0xde, "or-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
XOR_INT_LIT8((byte)0xdf, "xor-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
SHL_INT_LIT8((byte)0xe0, "shl-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
SHR_INT_LIT8((byte)0xe1, "shr-int/lit8", ReferenceType.none, Format.Format22b),
|
||||
USHR_INT_LIT8((byte)0xe2, "ushr-int/lit8", ReferenceType.none, Format.Format22b);
|
||||
|
||||
|
||||
|
||||
@ -269,7 +271,7 @@ public enum Opcode
|
||||
|
||||
for (Opcode opcode: Opcode.values()) {
|
||||
opcodesByValue.set((opcode.value & 0xFF), opcode);
|
||||
opcodesByName.put(opcode.name.toLowerCase().hashCode(), opcode);
|
||||
opcodesByName.put(opcode.name.hashCode(), opcode);
|
||||
}
|
||||
}catch (Exception ex) {
|
||||
System.out.println(ex.toString());
|
||||
@ -286,14 +288,12 @@ public enum Opcode
|
||||
|
||||
public final byte value;
|
||||
public final String name;
|
||||
public final byte numBytes;
|
||||
public final ReferenceType referenceType;
|
||||
public final String format;
|
||||
public final Format format;
|
||||
|
||||
Opcode(byte opcodeValue, String opcodeName, byte numBytes, ReferenceType referenceType, String format) {
|
||||
Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format) {
|
||||
this.value = opcodeValue;
|
||||
this.name = opcodeName;
|
||||
this.numBytes = numBytes;
|
||||
this.referenceType = referenceType;
|
||||
this.format = format;
|
||||
}
|
||||
|
78
src/main/java/org/jf/dexlib/util/NumberUtils.java
Normal file
78
src/main/java/org/jf/dexlib/util/NumberUtils.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 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.util;
|
||||
|
||||
public class NumberUtils {
|
||||
|
||||
public static byte decodeHighSignedNibble(byte b) {
|
||||
return (byte)(b >> 4);
|
||||
}
|
||||
|
||||
public static byte decodeHighUnsignedNibble(byte b) {
|
||||
return (byte)((b & 0xFF) >>> 4);
|
||||
}
|
||||
|
||||
public static byte decodeLowUnsignedNibble(byte b) {
|
||||
return (byte)(b & 0x0F);
|
||||
}
|
||||
|
||||
public static short decodeUnsignedByte(byte b) {
|
||||
return (short)(b & 0xFF);
|
||||
}
|
||||
|
||||
public static short decodeShort(byte lsb, byte msb) {
|
||||
return (short)
|
||||
( lsb |
|
||||
(msb << 8)
|
||||
);
|
||||
}
|
||||
|
||||
public static int decodeUnsignedShort(byte lsb, byte msb) {
|
||||
return ((msb & 0xFF) << 8) |
|
||||
(lsb & 0xFF);
|
||||
}
|
||||
|
||||
public static int decodeInt(byte lsb, byte mlsb, byte mmsb, byte msb) {
|
||||
return lsb |
|
||||
(mlsb << 8) |
|
||||
(mmsb << 16) |
|
||||
(msb << 24);
|
||||
}
|
||||
|
||||
public static long decodeLong(byte[] array, int startIndex) {
|
||||
return array[startIndex++] |
|
||||
(array[startIndex++] >> 8) |
|
||||
(array[startIndex++] >> 16) |
|
||||
(array[startIndex++] >> 24) |
|
||||
((long)array[startIndex++] >> 32) |
|
||||
((long)array[startIndex++] >> 40) |
|
||||
((long)array[startIndex++] >> 48) |
|
||||
((long)array[startIndex++] >> 56);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user