blob: 674d518016a19172949d85165fdbdaf7919eef62 [file] [log] [blame]
// line 1 "SyntheticAccessorFSM.rl"
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.util;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction;
import javax.annotation.Nonnull;
import java.util.List;
public class SyntheticAccessorFSM {
// line 43 "SyntheticAccessorFSM.rl"
// line 48 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
private static byte[] init__SyntheticAccessorFSM_actions_0()
{
return new byte [] {
0, 1, 0, 1, 1, 1, 2, 1, 13, 1, 14, 1,
15, 1, 16, 1, 17, 1, 18, 1, 19, 1, 20, 1,
21, 1, 25, 2, 3, 7, 2, 4, 7, 2, 5, 7,
2, 6, 7, 2, 8, 12, 2, 9, 12, 2, 10, 12,
2, 11, 12, 2, 22, 23, 2, 22, 24, 2, 22, 25,
2, 22, 26, 2, 22, 27, 2, 22, 28
};
}
private static final byte _SyntheticAccessorFSM_actions[] = init__SyntheticAccessorFSM_actions_0();
private static short[] init__SyntheticAccessorFSM_key_offsets_0()
{
return new short [] {
0, 0, 12, 82, 98, 102, 104, 166, 172, 174, 180, 184,
190, 192, 196, 198, 201, 203
};
}
private static final short _SyntheticAccessorFSM_key_offsets[] = init__SyntheticAccessorFSM_key_offsets_0();
private static short[] init__SyntheticAccessorFSM_trans_keys_0()
{
return new short [] {
82, 88, 89, 95, 96, 102, 103, 109, 110, 114, 116, 120,
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
169, 170, 171, 172, 173, 174, 175, 177, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195,
196, 197, 198, 199, 201, 202, 203, 204, 206, 207, 208, 216,
15, 17, 18, 25, 129, 143, 144, 176, 178, 205, 144, 145,
155, 156, 166, 167, 171, 172, 176, 177, 187, 188, 198, 199,
203, 204, 89, 95, 103, 109, 15, 17, 145, 146, 147, 148,
149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
173, 174, 175, 177, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
201, 202, 203, 204, 206, 207, 144, 176, 178, 205, 89, 95,
103, 109, 129, 143, 15, 17, 89, 95, 103, 109, 129, 143,
89, 95, 103, 109, 89, 95, 103, 109, 129, 143, 15, 17,
89, 95, 103, 109, 15, 17, 14, 10, 12, 15, 17, 0
};
}
private static final short _SyntheticAccessorFSM_trans_keys[] = init__SyntheticAccessorFSM_trans_keys_0();
private static byte[] init__SyntheticAccessorFSM_single_lengths_0()
{
return new byte [] {
0, 0, 60, 16, 0, 0, 58, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0
};
}
private static final byte _SyntheticAccessorFSM_single_lengths[] = init__SyntheticAccessorFSM_single_lengths_0();
private static byte[] init__SyntheticAccessorFSM_range_lengths_0()
{
return new byte [] {
0, 6, 5, 0, 2, 1, 2, 3, 1, 3, 2, 3,
1, 2, 1, 1, 1, 0
};
}
private static final byte _SyntheticAccessorFSM_range_lengths[] = init__SyntheticAccessorFSM_range_lengths_0();
private static short[] init__SyntheticAccessorFSM_index_offsets_0()
{
return new short [] {
0, 0, 7, 73, 90, 93, 95, 156, 160, 162, 166, 169,
173, 175, 178, 180, 183, 185
};
}
private static final short _SyntheticAccessorFSM_index_offsets[] = init__SyntheticAccessorFSM_index_offsets_0();
private static byte[] init__SyntheticAccessorFSM_indicies_0()
{
return new byte [] {
0, 2, 0, 2, 3, 3, 1, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 9, 10, 11, 12, 13,
14, 15, 16, 17, 20, 21, 9, 10, 11, 22, 23, 9,
10, 11, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 10,
11, 22, 23, 10, 11, 24, 24, 4, 5, 6, 7, 9,
1, 25, 26, 27, 28, 29, 30, 31, 32, 25, 26, 27,
28, 29, 30, 31, 32, 1, 33, 33, 1, 34, 1, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 9,
10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 9, 10,
11, 22, 23, 9, 10, 11, 8, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 10, 11, 12, 13, 14, 15, 16,
17, 20, 21, 10, 11, 22, 23, 10, 11, 7, 9, 1,
35, 35, 36, 1, 37, 1, 35, 35, 38, 1, 35, 35,
1, 39, 39, 40, 1, 41, 1, 39, 39, 1, 42, 1,
44, 43, 1, 45, 1, 1, 0
};
}
private static final byte _SyntheticAccessorFSM_indicies[] = init__SyntheticAccessorFSM_indicies_0();
private static byte[] init__SyntheticAccessorFSM_trans_targs_0()
{
return new byte [] {
2, 0, 14, 15, 17, 3, 6, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
11, 4, 4, 4, 4, 4, 4, 4, 4, 5, 17, 8,
9, 17, 10, 12, 13, 17, 17, 16, 17, 17
};
}
private static final byte _SyntheticAccessorFSM_trans_targs[] = init__SyntheticAccessorFSM_trans_targs_0();
private static byte[] init__SyntheticAccessorFSM_trans_actions_0()
{
return new byte [] {
0, 0, 1, 0, 51, 3, 0, 27, 39, 7, 9, 11,
13, 15, 17, 19, 21, 23, 30, 42, 33, 45, 36, 48,
5, 27, 39, 30, 42, 33, 45, 36, 48, 1, 63, 1,
0, 66, 0, 1, 0, 60, 54, 0, 25, 57
};
}
private static final byte _SyntheticAccessorFSM_trans_actions[] = init__SyntheticAccessorFSM_trans_actions_0();
static final int SyntheticAccessorFSM_start = 1;
static final int SyntheticAccessorFSM_first_final = 17;
static final int SyntheticAccessorFSM_error = 0;
static final int SyntheticAccessorFSM_en_main = 1;
// line 44 "SyntheticAccessorFSM.rl"
// math type constants
public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT;
public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT;
public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT;
public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT;
public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT;
public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT;
public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT;
public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT;
public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT;
public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT;
public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT;
public static final int INT = 0;
public static final int LONG = 1;
public static final int FLOAT = 2;
public static final int DOUBLE = 3;
public static final int POSITIVE_ONE = 1;
public static final int NEGATIVE_ONE = -1;
public static final int OTHER = 0;
@Nonnull private final Opcodes opcodes;
public SyntheticAccessorFSM(@Nonnull Opcodes opcodes) {
this.opcodes = opcodes;
}
public int test(List<? extends Instruction> instructions) {
int accessorType = -1;
int cs, p = 0;
int pe = instructions.size();
// one of the math type constants representing the type of math operation being performed
int mathOp = -1;
// for increments an decrements, the type of value the math operation is on
int mathType = -1;
// for increments and decrements, the value of the constant that is used
long constantValue = 0;
// The source register for the put instruction
int putRegister = -1;
// The return register;
int returnRegister = -1;
// line 242 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
{
cs = SyntheticAccessorFSM_start;
}
// line 247 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
{
int _klen;
int _trans = 0;
int _acts;
int _nacts;
int _keys;
int _goto_targ = 0;
_goto: while (true) {
switch ( _goto_targ ) {
case 0:
if ( p == pe ) {
_goto_targ = 4;
continue _goto;
}
if ( cs == 0 ) {
_goto_targ = 5;
continue _goto;
}
case 1:
_match: do {
_keys = _SyntheticAccessorFSM_key_offsets[cs];
_trans = _SyntheticAccessorFSM_index_offsets[cs];
_klen = _SyntheticAccessorFSM_single_lengths[cs];
if ( _klen > 0 ) {
int _lower = _keys;
int _mid;
int _upper = _keys + _klen - 1;
while (true) {
if ( _upper < _lower )
break;
_mid = _lower + ((_upper-_lower) >> 1);
if ( ( opcodes.getOpcodeValue(instructions.get(p).getOpcode())) < _SyntheticAccessorFSM_trans_keys[_mid] )
_upper = _mid - 1;
else if ( ( opcodes.getOpcodeValue(instructions.get(p).getOpcode())) > _SyntheticAccessorFSM_trans_keys[_mid] )
_lower = _mid + 1;
else {
_trans += (_mid - _keys);
break _match;
}
}
_keys += _klen;
_trans += _klen;
}
_klen = _SyntheticAccessorFSM_range_lengths[cs];
if ( _klen > 0 ) {
int _lower = _keys;
int _mid;
int _upper = _keys + (_klen<<1) - 2;
while (true) {
if ( _upper < _lower )
break;
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
if ( ( opcodes.getOpcodeValue(instructions.get(p).getOpcode())) < _SyntheticAccessorFSM_trans_keys[_mid] )
_upper = _mid - 2;
else if ( ( opcodes.getOpcodeValue(instructions.get(p).getOpcode())) > _SyntheticAccessorFSM_trans_keys[_mid+1] )
_lower = _mid + 2;
else {
_trans += ((_mid - _keys)>>1);
break _match;
}
}
_trans += _klen;
}
} while (false);
_trans = _SyntheticAccessorFSM_indicies[_trans];
cs = _SyntheticAccessorFSM_trans_targs[_trans];
if ( _SyntheticAccessorFSM_trans_actions[_trans] != 0 ) {
_acts = _SyntheticAccessorFSM_trans_actions[_trans];
_nacts = (int) _SyntheticAccessorFSM_actions[_acts++];
while ( _nacts-- > 0 )
{
switch ( _SyntheticAccessorFSM_actions[_acts++] )
{
case 0:
// line 100 "SyntheticAccessorFSM.rl"
{
putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
}
break;
case 1:
// line 107 "SyntheticAccessorFSM.rl"
{
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
}
break;
case 2:
// line 111 "SyntheticAccessorFSM.rl"
{
mathType = INT;
mathOp = ADD;
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
}
break;
case 3:
// line 117 "SyntheticAccessorFSM.rl"
{ mathType = INT; }
break;
case 4:
// line 118 "SyntheticAccessorFSM.rl"
{ mathType = LONG; }
break;
case 5:
// line 119 "SyntheticAccessorFSM.rl"
{ mathType = FLOAT; }
break;
case 6:
// line 120 "SyntheticAccessorFSM.rl"
{mathType = DOUBLE; }
break;
case 7:
// line 120 "SyntheticAccessorFSM.rl"
{
mathOp = ADD;
}
break;
case 8:
// line 123 "SyntheticAccessorFSM.rl"
{ mathType = INT; }
break;
case 9:
// line 124 "SyntheticAccessorFSM.rl"
{ mathType = LONG; }
break;
case 10:
// line 125 "SyntheticAccessorFSM.rl"
{ mathType = FLOAT; }
break;
case 11:
// line 126 "SyntheticAccessorFSM.rl"
{mathType = DOUBLE; }
break;
case 12:
// line 126 "SyntheticAccessorFSM.rl"
{
mathOp = SUB;
}
break;
case 13:
// line 130 "SyntheticAccessorFSM.rl"
{
mathOp = MUL;
}
break;
case 14:
// line 134 "SyntheticAccessorFSM.rl"
{
mathOp = DIV;
}
break;
case 15:
// line 138 "SyntheticAccessorFSM.rl"
{
mathOp = REM;
}
break;
case 16:
// line 141 "SyntheticAccessorFSM.rl"
{
mathOp = AND;
}
break;
case 17:
// line 144 "SyntheticAccessorFSM.rl"
{
mathOp = OR;
}
break;
case 18:
// line 147 "SyntheticAccessorFSM.rl"
{
mathOp = XOR;
}
break;
case 19:
// line 150 "SyntheticAccessorFSM.rl"
{
mathOp = SHL;
}
break;
case 20:
// line 153 "SyntheticAccessorFSM.rl"
{
mathOp = SHR;
}
break;
case 21:
// line 156 "SyntheticAccessorFSM.rl"
{
mathOp = USHR;
}
break;
case 22:
// line 162 "SyntheticAccessorFSM.rl"
{
returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
}
break;
case 23:
// line 168 "SyntheticAccessorFSM.rl"
{
accessorType = SyntheticAccessorResolver.GETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
case 24:
// line 172 "SyntheticAccessorFSM.rl"
{
accessorType = SyntheticAccessorResolver.SETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
case 25:
// line 176 "SyntheticAccessorFSM.rl"
{
accessorType = SyntheticAccessorResolver.METHOD; { p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
case 26:
// line 180 "SyntheticAccessorFSM.rl"
{
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
}
break;
case 27:
// line 184 "SyntheticAccessorFSM.rl"
{
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
}
break;
case 28:
// line 192 "SyntheticAccessorFSM.rl"
{
accessorType = mathOp; { p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
// line 487 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
}
}
}
case 2:
if ( cs == 0 ) {
_goto_targ = 5;
continue _goto;
}
if ( ++p != pe ) {
_goto_targ = 1;
continue _goto;
}
case 4:
case 5:
}
break; }
}
// line 205 "SyntheticAccessorFSM.rl"
return accessorType;
}
private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister,
int returnRegister) {
boolean isPrefix = putRegister == returnRegister;
boolean negativeConstant = false;
switch (mathType) {
case INT:
case LONG: {
if (constantValue == 1) {
negativeConstant = false;
} else if (constantValue == -1) {
negativeConstant = true;
} else {
return -1;
}
break;
}
case FLOAT: {
float val = Float.intBitsToFloat((int)constantValue);
if (val == 1) {
negativeConstant = false;
} else if (val == -1) {
negativeConstant = true;
} else {
return -1;
}
break;
}
case DOUBLE: {
double val = Double.longBitsToDouble(constantValue);
if (val == 1) {
negativeConstant = false;
} else if (val == -1) {
negativeConstant = true;
} else {
return -1;
}
break;
}
}
boolean isAdd = ((mathOp == ADD) && !negativeConstant) ||
((mathOp == SUB) && negativeConstant);
if (isPrefix) {
if (isAdd) {
return SyntheticAccessorResolver.PREFIX_INCREMENT;
} else {
return SyntheticAccessorResolver.PREFIX_DECREMENT;
}
} else {
if (isAdd) {
return SyntheticAccessorResolver.POSTFIX_INCREMENT;
} else {
return SyntheticAccessorResolver.POSTFIX_DECREMENT;
}
}
}
}