1 /* 2 * Copyright 2012, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.dexlib2.util; 33 34 import org.jf.dexlib2.iface.instruction.Instruction; 35 import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; 36 import org.jf.dexlib2.iface.instruction.WideLiteralInstruction; 37 38 import java.util.List; 39 40 public class SyntheticAccessorFSM { 41 %% machine SyntheticAccessorFSM; 42 %% write data; 43 44 // math type constants 45 public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT; 46 public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT; 47 public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT; 48 public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT; 49 public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT; 50 public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT; 51 public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT; 52 public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT; 53 public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT; 54 public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT; 55 public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT; 56 57 public static final int INT = 0; 58 public static final int LONG = 1; 59 public static final int FLOAT = 2; 60 public static final int DOUBLE = 3; 61 62 public static final int POSITIVE_ONE = 1; 63 public static final int NEGATIVE_ONE = -1; 64 public static final int OTHER = 0; 65 66 public static int test(List<? extends Instruction> instructions) { 67 int accessorType = -1; 68 int cs, p = 0; 69 int pe = instructions.size(); 70 71 // one of the math type constants representing the type of math operation being performed 72 int mathOp = -1; 73 74 // for increments an decrements, the type of value the math operation is on 75 int mathType = -1; 76 77 // for increments and decrements, the value of the constant that is used 78 long constantValue = 0; 79 80 // The source register for the put instruction 81 int putRegister = -1; 82 // The return register; 83 int returnRegister = -1; 84 85 %%{ 86 import "Opcodes.rl"; 87 alphtype short; 88 getkey instructions.get(p).getOpcode().value; 89 90 get = (0x52 .. 0x58) | (0x60 .. 0x66); # all igets/sgets 91 92 # all iputs/sputs 93 put = ((0x59 .. 0x5f) | (0x67 .. 0x6d)) @ { 94 putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); 95 }; 96 97 invoke = (0x6e .. 0x72) | (0x74 .. 0x78); # all invokes 98 99 # all numeric const instructions 100 const_literal = (0x12 .. 0x19) @ { 101 constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); 102 }; 103 104 add_const = (add_int_lit8 | add_int_lit16) @ { 105 mathType = INT; 106 mathOp = ADD; 107 constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); 108 }; 109 110 arbitrary_add = (((add_int | add_int_2addr) @ { mathType = INT; }) | 111 ((add_long | add_long_2addr) @ { mathType = LONG; }) | 112 ((add_float | add_float_2addr) @ { mathType = FLOAT; }) | 113 ((add_double | add_double_2addr) @ {mathType = DOUBLE; })) @ { 114 mathOp = ADD; 115 }; 116 arbitrary_sub = (((sub_int | sub_int_2addr) @ { mathType = INT; }) | 117 ((sub_long | sub_long_2addr) @ { mathType = LONG; }) | 118 ((sub_float | sub_float_2addr) @ { mathType = FLOAT; }) | 119 ((sub_double | sub_double_2addr) @ {mathType = DOUBLE; })) @ { 120 mathOp = SUB; 121 }; 122 arbitrary_mul = (mul_int | mul_int_2addr | mul_long | mul_long_2addr | 123 mul_float | mul_float_2addr | mul_double | mul_double_2addr) @ { 124 mathOp = MUL; 125 }; 126 arbitrary_div = (div_int | div_int_2addr | div_long | div_long_2addr | 127 div_float | div_float_2addr | div_double | div_double_2addr) @ { 128 mathOp = DIV; 129 }; 130 arbitrary_rem = (rem_int | rem_int_2addr | rem_long | rem_long_2addr | 131 rem_float | rem_float_2addr | rem_double | rem_double_2addr) @ { 132 mathOp = REM; 133 }; 134 arbitrary_and = (and_int | and_int_2addr | and_long | and_long_2addr) @ { 135 mathOp = AND; 136 }; 137 arbitrary_or = (or_int | or_int_2addr | or_long | or_long_2addr) @ { 138 mathOp = OR; 139 }; 140 arbitrary_xor = (xor_int | xor_int_2addr | xor_long | xor_long_2addr) @ { 141 mathOp = XOR; 142 }; 143 arbitrary_shl = (shl_int | shl_int_2addr | shl_long | shl_long_2addr) @ { 144 mathOp = SHL; 145 }; 146 arbitrary_shr = (shr_int | shr_int_2addr | shr_long | shr_long_2addr) @ { 147 mathOp = SHR; 148 }; 149 arbitrary_ushr = (ushr_int | ushr_int_2addr | ushr_long | ushr_long_2addr) @ { 150 mathOp = USHR; 151 }; 152 153 type_conversion = 0x81 .. 0x8f; # all type-conversion opcodes 154 155 return_something = (return | return_wide | return_object) @ { 156 returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); 157 }; 158 159 any_move_result = move_result | move_result_wide | move_result_object; 160 161 get_accessor = get return_something @ { 162 accessorType = SyntheticAccessorResolver.GETTER; fbreak; 163 }; 164 165 put_accessor = put return_something @ { 166 accessorType = SyntheticAccessorResolver.SETTER; fbreak; 167 }; 168 169 invoke_accessor = invoke (return_void | (any_move_result return_something)) @ { 170 accessorType = SyntheticAccessorResolver.METHOD; fbreak; 171 }; 172 173 increment_accessor = get add_const type_conversion? put return_something @ { 174 accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); 175 }; 176 177 alt_increment_accessor = get const_literal (arbitrary_add | arbitrary_sub) put return_something @ { 178 accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); 179 }; 180 181 math_assignment_accessor = get type_conversion? 182 (arbitrary_add | arbitrary_sub | arbitrary_mul | arbitrary_div | arbitrary_rem | 183 arbitrary_and | arbitrary_or | arbitrary_xor | arbitrary_shl | arbitrary_shr | 184 arbitrary_ushr) 185 type_conversion{0,2} put return_something @ { 186 accessorType = mathOp; fbreak; 187 }; 188 189 main := get_accessor | 190 put_accessor | 191 invoke_accessor | 192 increment_accessor | 193 alt_increment_accessor | 194 math_assignment_accessor; 195 196 write init; 197 write exec; 198 }%% 199 200 return accessorType; 201 } 202 203 private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister, 204 int returnRegister) { 205 boolean isPrefix = putRegister == returnRegister; 206 207 boolean negativeConstant = false; 208 209 switch (mathType) { 210 case INT: 211 case LONG: { 212 if (constantValue == 1) { 213 negativeConstant = false; 214 } else if (constantValue == -1) { 215 negativeConstant = true; 216 } else { 217 return -1; 218 } 219 break; 220 } 221 case FLOAT: { 222 float val = Float.intBitsToFloat((int)constantValue); 223 if (val == 1) { 224 negativeConstant = false; 225 } else if (val == -1) { 226 negativeConstant = true; 227 } else { 228 return -1; 229 } 230 break; 231 } 232 case DOUBLE: { 233 double val = Double.longBitsToDouble(constantValue); 234 if (val == 1) { 235 negativeConstant = false; 236 } else if (val == -1) { 237 negativeConstant = true; 238 } else { 239 return -1; 240 } 241 break; 242 } 243 } 244 245 boolean isAdd = ((mathOp == ADD) && !negativeConstant) || 246 ((mathOp == SUB) && negativeConstant); 247 248 if (isPrefix) { 249 if (isAdd) { 250 return SyntheticAccessorResolver.PREFIX_INCREMENT; 251 } else { 252 return SyntheticAccessorResolver.PREFIX_DECREMENT; 253 } 254 } else { 255 if (isAdd) { 256 return SyntheticAccessorResolver.POSTFIX_INCREMENT; 257 } else { 258 return SyntheticAccessorResolver.POSTFIX_DECREMENT; 259 } 260 } 261 } 262 }