mirror of
https://github.com/revanced/smali.git
synced 2025-05-06 17:34:34 +02:00
Changed the implementation of the sparse and packed switch directives, so that they don't required the base offset label. Instead, it looks for and uses the offset of the first packed/sparse switch instruction that references it, to calculate the offset for each target
git-svn-id: https://smali.googlecode.com/svn/trunk@150 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
5a0f83d156
commit
3a76e6904b
@ -81,7 +81,7 @@ Label13:
|
|||||||
return-void
|
return-void
|
||||||
|
|
||||||
PackedSwitch:
|
PackedSwitch:
|
||||||
.packed-switch switch: 10
|
.packed-switch 10
|
||||||
Label10:
|
Label10:
|
||||||
Label11:
|
Label11:
|
||||||
Label12:
|
Label12:
|
||||||
@ -120,7 +120,7 @@ Label99:
|
|||||||
return-void
|
return-void
|
||||||
|
|
||||||
SparseSwitch:
|
SparseSwitch:
|
||||||
.sparse-switch switch:
|
.sparse-switch
|
||||||
10 -> Label10:
|
10 -> Label10:
|
||||||
13 -> Label13:
|
13 -> Label13:
|
||||||
15 -> Label15:
|
15 -> Label15:
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
const v0, 12
|
const v0, 12
|
||||||
|
|
||||||
switch:
|
|
||||||
packed-switch v0, PackedSwitch:
|
packed-switch v0, PackedSwitch:
|
||||||
|
|
||||||
Label10:
|
Label10:
|
||||||
@ -58,7 +57,7 @@ Label13:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
PackedSwitch:
|
PackedSwitch:
|
||||||
.packed-switch switch: 10
|
.packed-switch 10
|
||||||
Label10:
|
Label10:
|
||||||
Label11:
|
Label11:
|
||||||
Label12:
|
Label12:
|
||||||
|
@ -452,8 +452,6 @@ ARRAY_DATA_PHRASE
|
|||||||
|
|
||||||
PACKED_SWITCH_PHRASE
|
PACKED_SWITCH_PHRASE
|
||||||
: PACKED_SWITCH_DIRECTIVE_EMIT
|
: PACKED_SWITCH_DIRECTIVE_EMIT
|
||||||
WS
|
|
||||||
(LABEL_EMIT | OFFSET_EMIT)
|
|
||||||
WS
|
WS
|
||||||
FIXED_32BIT_LITERAL_EMITCHILD
|
FIXED_32BIT_LITERAL_EMITCHILD
|
||||||
(WSC (LABEL_EMIT | OFFSET_EMIT))*
|
(WSC (LABEL_EMIT | OFFSET_EMIT))*
|
||||||
@ -462,10 +460,8 @@ PACKED_SWITCH_PHRASE
|
|||||||
|
|
||||||
SPARSE_SWITCH_PHRASE
|
SPARSE_SWITCH_PHRASE
|
||||||
: SPARSE_SWITCH_DIRECTIVE_EMIT
|
: SPARSE_SWITCH_DIRECTIVE_EMIT
|
||||||
WS
|
|
||||||
(LABEL_EMIT | OFFSET_EMIT)
|
|
||||||
(WSC FIXED_32BIT_LITERAL_EMITCHILD WS? '->' WS? (LABEL_EMIT | OFFSET_EMIT))*
|
(WSC FIXED_32BIT_LITERAL_EMITCHILD WS? '->' WS? (LABEL_EMIT | OFFSET_EMIT))*
|
||||||
WSC
|
WSC?
|
||||||
END_SPARSE_SWITCH_DIRECTIVE_EMIT;
|
END_SPARSE_SWITCH_DIRECTIVE_EMIT;
|
||||||
|
|
||||||
REGISTERS_PHRASE
|
REGISTERS_PHRASE
|
||||||
|
@ -63,13 +63,15 @@ tokens {
|
|||||||
I_ARRAY_ELEMENT_SIZE;
|
I_ARRAY_ELEMENT_SIZE;
|
||||||
I_ARRAY_ELEMENTS;
|
I_ARRAY_ELEMENTS;
|
||||||
I_PACKED_SWITCH_START_KEY;
|
I_PACKED_SWITCH_START_KEY;
|
||||||
I_PACKED_SWITCH_BASE_OFFSET;
|
|
||||||
I_PACKED_SWITCH_TARGET_COUNT;
|
I_PACKED_SWITCH_TARGET_COUNT;
|
||||||
I_PACKED_SWITCH_TARGETS;
|
I_PACKED_SWITCH_TARGETS;
|
||||||
I_SPARSE_SWITCH_BASE_OFFSET;
|
I_PACKED_SWITCH_DECLARATION;
|
||||||
|
I_PACKED_SWITCH_DECLARATIONS;
|
||||||
I_SPARSE_SWITCH_KEYS;
|
I_SPARSE_SWITCH_KEYS;
|
||||||
I_SPARSE_SWITCH_TARGET_COUNT;
|
I_SPARSE_SWITCH_TARGET_COUNT;
|
||||||
I_SPARSE_SWITCH_TARGETS;
|
I_SPARSE_SWITCH_TARGETS;
|
||||||
|
I_SPARSE_SWITCH_DECLARATION;
|
||||||
|
I_SPARSE_SWITCH_DECLARATIONS;
|
||||||
I_ADDRESS;
|
I_ADDRESS;
|
||||||
I_CATCH;
|
I_CATCH;
|
||||||
I_CATCHES;
|
I_CATCHES;
|
||||||
@ -153,6 +155,14 @@ import org.jf.dexlib.code.Format.*;
|
|||||||
public String getErrorHeader(RecognitionException e) {
|
public String getErrorHeader(RecognitionException e) {
|
||||||
return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
|
return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CommonTree buildTree(int type, String text, List<CommonTree> children) {
|
||||||
|
CommonTree root = new CommonTree(new CommonToken(type, text));
|
||||||
|
for (CommonTree child: children) {
|
||||||
|
root.addChild(child);
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,10 +245,17 @@ fully_qualified_field
|
|||||||
-> reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor;
|
-> reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor;
|
||||||
|
|
||||||
statements_and_directives
|
statements_and_directives
|
||||||
scope {boolean hasRegistersDirective;}
|
scope
|
||||||
|
{
|
||||||
|
boolean hasRegistersDirective;
|
||||||
|
List<CommonTree> packedSwitchDeclarations;
|
||||||
|
List<CommonTree> sparseSwitchDeclarations;
|
||||||
|
}
|
||||||
: {
|
: {
|
||||||
$method::currentAddress = 0;
|
$method::currentAddress = 0;
|
||||||
$statements_and_directives::hasRegistersDirective = false;
|
$statements_and_directives::hasRegistersDirective = false;
|
||||||
|
$statements_and_directives::packedSwitchDeclarations = new ArrayList<CommonTree>();
|
||||||
|
$statements_and_directives::sparseSwitchDeclarations = new ArrayList<CommonTree>();
|
||||||
}
|
}
|
||||||
( instruction {$method::currentAddress += $instruction.size/2;}
|
( instruction {$method::currentAddress += $instruction.size/2;}
|
||||||
| {!$statements_and_directives::hasRegistersDirective}?=> registers_directive {$statements_and_directives::hasRegistersDirective = true;}
|
| {!$statements_and_directives::hasRegistersDirective}?=> registers_directive {$statements_and_directives::hasRegistersDirective = true;}
|
||||||
@ -250,6 +267,8 @@ statements_and_directives
|
|||||||
)*
|
)*
|
||||||
-> ^(I_REGISTERS registers_directive?)
|
-> ^(I_REGISTERS registers_directive?)
|
||||||
^(I_LABELS label*)
|
^(I_LABELS label*)
|
||||||
|
{buildTree(I_PACKED_SWITCH_DECLARATIONS, "I_PACKED_SWITCH_DECLARATIONS", $statements_and_directives::packedSwitchDeclarations)}
|
||||||
|
{buildTree(I_SPARSE_SWITCH_DECLARATIONS, "I_SPARSE_SWITCH_DECLARATIONS", $statements_and_directives::sparseSwitchDeclarations)}
|
||||||
^(I_STATEMENTS instruction*)
|
^(I_STATEMENTS instruction*)
|
||||||
^(I_CATCHES catch_directive*)
|
^(I_CATCHES catch_directive*)
|
||||||
^(I_PARAMETERS parameter_directive*)
|
^(I_PARAMETERS parameter_directive*)
|
||||||
@ -389,8 +408,23 @@ instruction returns [int size]
|
|||||||
INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal {$size = Format.Format31i.size;}
|
INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal {$size = Format.Format31i.size;}
|
||||||
-> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
-> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
||||||
| //e.g. fill-array-data v0, ArrayData:
|
| //e.g. fill-array-data v0, ArrayData:
|
||||||
INSTRUCTION_FORMAT31t REGISTER (LABEL | OFFSET) {$size = Format.Format31t.size;}
|
INSTRUCTION_FORMAT31t REGISTER offset_or_label {$size = Format.Format31t.size;}
|
||||||
-> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER LABEL? OFFSET?)
|
{
|
||||||
|
if ($INSTRUCTION_FORMAT31t.text.equals("packed-switch")) {
|
||||||
|
CommonTree root = new CommonTree(new CommonToken(I_PACKED_SWITCH_DECLARATION, "I_PACKED_SWITCH_DECLARATION"));
|
||||||
|
CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress)));
|
||||||
|
root.addChild(address);
|
||||||
|
root.addChild($offset_or_label.tree.dupNode());
|
||||||
|
$statements_and_directives::packedSwitchDeclarations.add(root);
|
||||||
|
} else if ($INSTRUCTION_FORMAT31t.text.equals("sparse-switch")) {
|
||||||
|
CommonTree root = new CommonTree(new CommonToken(I_SPARSE_SWITCH_DECLARATION, "I_SPARSE_SWITCH_DECLARATION"));
|
||||||
|
CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress)));
|
||||||
|
root.addChild(address);
|
||||||
|
root.addChild($offset_or_label.tree.dupNode());
|
||||||
|
$statements_and_directives::sparseSwitchDeclarations.add(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER offset_or_label)
|
||||||
| //e.g. move/16 v4567, v1234
|
| //e.g. move/16 v4567, v1234
|
||||||
INSTRUCTION_FORMAT32x REGISTER REGISTER {$size = Format.Format32x.size;}
|
INSTRUCTION_FORMAT32x REGISTER REGISTER {$size = Format.Format32x.size;}
|
||||||
-> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER)
|
-> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER)
|
||||||
@ -440,8 +474,6 @@ instruction returns [int size]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base_offset = offset_or_label
|
|
||||||
|
|
||||||
fixed_32bit_literal
|
fixed_32bit_literal
|
||||||
|
|
||||||
(switch_target += offset_or_label {$size+=4; targetCount++;})*
|
(switch_target += offset_or_label {$size+=4; targetCount++;})*
|
||||||
@ -451,13 +483,11 @@ instruction returns [int size]
|
|||||||
/*add a nop statement before this if needed to force the correct alignment*/
|
/*add a nop statement before this if needed to force the correct alignment*/
|
||||||
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
||||||
^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
|
^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
|
||||||
^(I_PACKED_SWITCH_BASE_OFFSET[$start, "I_PACKED_SWITCH_BASE_OFFSET"] $base_offset)
|
|
||||||
^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
|
^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
|
||||||
^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
|
^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
|
||||||
)
|
)
|
||||||
|
|
||||||
-> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
|
-> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"]
|
||||||
^(I_PACKED_SWITCH_BASE_OFFSET[$start, "I_PACKED_SWITCH_BASE_OFFSET"] $base_offset)
|
|
||||||
^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
|
^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal)
|
||||||
^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
|
^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*)
|
||||||
)
|
)
|
||||||
@ -474,8 +504,6 @@ instruction returns [int size]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base_offset = offset_or_label
|
|
||||||
|
|
||||||
(fixed_32bit_literal switch_target += offset_or_label {$size += 8; targetCount++;})*
|
(fixed_32bit_literal switch_target += offset_or_label {$size += 8; targetCount++;})*
|
||||||
|
|
||||||
END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;}
|
END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;}
|
||||||
@ -483,12 +511,10 @@ instruction returns [int size]
|
|||||||
/*add a nop statement before this if needed to force the correct alignment*/
|
/*add a nop statement before this if needed to force the correct alignment*/
|
||||||
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
||||||
^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
||||||
^(I_SPARSE_SWITCH_BASE_OFFSET[$start, "I_SPARSE_SWITCH_BASE_OFFSET"] $base_offset)
|
|
||||||
I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
|
I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
|
||||||
^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
|
^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
|
||||||
^(I_SPARSE_SWITCH_TARGETS $switch_target*))
|
^(I_SPARSE_SWITCH_TARGETS $switch_target*))
|
||||||
-> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
-> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
||||||
^(I_SPARSE_SWITCH_BASE_OFFSET[$start, "I_SPARSE_SWITCH_BASE_OFFSET"] $base_offset)
|
|
||||||
I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
|
I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)]
|
||||||
^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
|
^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*)
|
||||||
^(I_SPARSE_SWITCH_TARGETS $switch_target*))
|
^(I_SPARSE_SWITCH_TARGETS $switch_target*))
|
||||||
|
@ -132,6 +132,7 @@ smali_file
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec]
|
header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec]
|
||||||
: class_spec super_spec implements_list source_spec
|
: class_spec super_spec implements_list source_spec
|
||||||
{
|
{
|
||||||
@ -141,6 +142,7 @@ header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, Type
|
|||||||
$super_spec.type, $implements_list.implementsList, $source_spec.source, classDataItem);
|
$super_spec.type, $implements_list.implementsList, $source_spec.source, classDataItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class_spec returns[TypeIdItem type, int accessFlags]
|
class_spec returns[TypeIdItem type, int accessFlags]
|
||||||
: class_type_descriptor access_list
|
: class_type_descriptor access_list
|
||||||
{
|
{
|
||||||
@ -313,7 +315,7 @@ array_elements returns[List<byte[\]> values]
|
|||||||
packed_switch_target_count returns[int targetCount]
|
packed_switch_target_count returns[int targetCount]
|
||||||
: I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);};
|
: I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);};
|
||||||
|
|
||||||
packed_switch_targets[int baseOffset] returns[int[\] targets]
|
packed_switch_targets[int baseAddress] returns[int[\] targets]
|
||||||
:
|
:
|
||||||
^(I_PACKED_SWITCH_TARGETS
|
^(I_PACKED_SWITCH_TARGETS
|
||||||
packed_switch_target_count
|
packed_switch_target_count
|
||||||
@ -325,7 +327,7 @@ packed_switch_targets[int baseOffset] returns[int[\] targets]
|
|||||||
|
|
||||||
(offset_or_label
|
(offset_or_label
|
||||||
{
|
{
|
||||||
targets[targetsPosition++] = $offset_or_label.offsetValue - $baseOffset;
|
$targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress;
|
||||||
})*
|
})*
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -344,7 +346,8 @@ sparse_switch_keys[int targetCount] returns[int[\] keys]
|
|||||||
})*
|
})*
|
||||||
);
|
);
|
||||||
|
|
||||||
sparse_switch_targets[int baseOffset, int targetCount] returns[int[\] targets]
|
|
||||||
|
sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets]
|
||||||
: {
|
: {
|
||||||
$targets = new int[$targetCount];
|
$targets = new int[$targetCount];
|
||||||
int targetsPosition = 0;
|
int targetsPosition = 0;
|
||||||
@ -352,7 +355,7 @@ sparse_switch_targets[int baseOffset, int targetCount] returns[int[\] targets]
|
|||||||
^(I_SPARSE_SWITCH_TARGETS
|
^(I_SPARSE_SWITCH_TARGETS
|
||||||
(offset_or_label
|
(offset_or_label
|
||||||
{
|
{
|
||||||
$targets[targetsPosition++] = $offset_or_label.offsetValue - $baseOffset;
|
$targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress;
|
||||||
})*
|
})*
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -365,6 +368,8 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
TryListBuilder tryList;
|
TryListBuilder tryList;
|
||||||
int currentAddress;
|
int currentAddress;
|
||||||
DebugInfoBuilder debugInfo;
|
DebugInfoBuilder debugInfo;
|
||||||
|
HashMap<Integer, Integer> packedSwitchDeclarations;
|
||||||
|
HashMap<Integer, Integer> sparseSwitchDeclarations;
|
||||||
}
|
}
|
||||||
@init
|
@init
|
||||||
{
|
{
|
||||||
@ -379,6 +384,8 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
$method::tryList = new TryListBuilder();
|
$method::tryList = new TryListBuilder();
|
||||||
$method::currentAddress = 0;
|
$method::currentAddress = 0;
|
||||||
$method::debugInfo = new DebugInfoBuilder();
|
$method::debugInfo = new DebugInfoBuilder();
|
||||||
|
$method::packedSwitchDeclarations = new HashMap<Integer, Integer>();
|
||||||
|
$method::sparseSwitchDeclarations = new HashMap<Integer, Integer>();
|
||||||
}
|
}
|
||||||
^( I_METHOD
|
^( I_METHOD
|
||||||
method_name_and_prototype
|
method_name_and_prototype
|
||||||
@ -394,6 +401,8 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
totalMethodRegisters = $registers_directive.registers;
|
totalMethodRegisters = $registers_directive.registers;
|
||||||
}
|
}
|
||||||
labels
|
labels
|
||||||
|
packed_switch_declarations
|
||||||
|
sparse_switch_declarations
|
||||||
statements[totalMethodRegisters, methodParameterRegisters]
|
statements[totalMethodRegisters, methodParameterRegisters]
|
||||||
catches
|
catches
|
||||||
parameters
|
parameters
|
||||||
@ -525,6 +534,34 @@ label_def
|
|||||||
$method::labels.put(labelName, $address.address);
|
$method::labels.put(labelName, $address.address);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
packed_switch_declarations
|
||||||
|
: ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*);
|
||||||
|
packed_switch_declaration
|
||||||
|
: ^(I_PACKED_SWITCH_DECLARATION address offset_or_label_absolute[$address.address])
|
||||||
|
{
|
||||||
|
int switchDataAddress = $offset_or_label_absolute.address;
|
||||||
|
if ((switchDataAddress \% 2) != 0) {
|
||||||
|
switchDataAddress++;
|
||||||
|
}
|
||||||
|
if (!$method::packedSwitchDeclarations.containsKey(switchDataAddress)) {
|
||||||
|
$method::packedSwitchDeclarations.put(switchDataAddress, $address.address);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sparse_switch_declarations
|
||||||
|
: ^(I_SPARSE_SWITCH_DECLARATIONS sparse_switch_declaration*);
|
||||||
|
sparse_switch_declaration
|
||||||
|
: ^(I_SPARSE_SWITCH_DECLARATION address offset_or_label_absolute[$address.address])
|
||||||
|
{
|
||||||
|
int switchDataAddress = $offset_or_label_absolute.address;
|
||||||
|
if ((switchDataAddress \% 2) != 0) {
|
||||||
|
switchDataAddress++;
|
||||||
|
}
|
||||||
|
if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) {
|
||||||
|
$method::sparseSwitchDeclarations.put(switchDataAddress, $address.address);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
catches : ^(I_CATCHES catch_directive*);
|
catches : ^(I_CATCHES catch_directive*);
|
||||||
|
|
||||||
catch_directive
|
catch_directive
|
||||||
@ -1032,7 +1069,15 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
}
|
}
|
||||||
|
|
|
|
||||||
|
|
||||||
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_BASE_OFFSET base_offset=offset_or_label) ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) packed_switch_targets[$base_offset.offsetValue])
|
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
|
||||||
|
{
|
||||||
|
int currentAddress = $method::currentAddress;
|
||||||
|
Integer baseAddress = $method::packedSwitchDeclarations.get(currentAddress);
|
||||||
|
if (baseAddress == null) {
|
||||||
|
baseAddress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packed_switch_targets[baseAddress])
|
||||||
{
|
{
|
||||||
int startKey = $fixed_32bit_literal.value;
|
int startKey = $fixed_32bit_literal.value;
|
||||||
int[] targets = $packed_switch_targets.targets;
|
int[] targets = $packed_switch_targets.targets;
|
||||||
@ -1040,7 +1085,16 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
$instruction = new InstructionField(dexFile, new PackedSwitchDataPseudoInstruction(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])
|
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount]
|
||||||
|
{
|
||||||
|
int currentAddress = $method::currentAddress;
|
||||||
|
Integer baseAddress = $method::sparseSwitchDeclarations.get(currentAddress);
|
||||||
|
if (baseAddress == null) {
|
||||||
|
baseAddress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount])
|
||||||
{
|
{
|
||||||
int[] keys = $sparse_switch_keys.keys;
|
int[] keys = $sparse_switch_keys.keys;
|
||||||
int[] targets = $sparse_switch_targets.targets;
|
int[] targets = $sparse_switch_targets.targets;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user