Home | History | Annotate | Download | only in analysis
      1 /*
      2  * Copyright 2013, 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.analysis;
     33 
     34 import org.jf.dexlib2.Opcode;
     35 
     36 import javax.annotation.Nonnull;
     37 
     38 public class OdexedFieldInstructionMapper {
     39     private static Opcode[][][][] opcodeMap = new Opcode[][][][] {
     40             //get opcodes
     41             new Opcode[][][] {
     42                     //iget quick
     43                     new Opcode[][] {
     44                             //odexed
     45                             new Opcode[] {
     46                                 /*Z*/   Opcode.IGET_QUICK,
     47                                 /*B*/   Opcode.IGET_QUICK,
     48                                 /*S*/   Opcode.IGET_QUICK,
     49                                 /*C*/   Opcode.IGET_QUICK,
     50                                 /*I,F*/ Opcode.IGET_QUICK,
     51                                 /*J,D*/ Opcode.IGET_WIDE_QUICK,
     52                                 /*L,[*/ Opcode.IGET_OBJECT_QUICK
     53                             },
     54                             //deodexed
     55                             new Opcode[] {
     56                                 /*Z*/   Opcode.IGET_BOOLEAN,
     57                                 /*B*/   Opcode.IGET_BYTE,
     58                                 /*S*/   Opcode.IGET_SHORT,
     59                                 /*C*/   Opcode.IGET_CHAR,
     60                                 /*I,F*/ Opcode.IGET,
     61                                 /*J,D*/ Opcode.IGET_WIDE,
     62                                 /*L,[*/ Opcode.IGET_OBJECT
     63                             }
     64                     },
     65                     //iget volatile
     66                     new Opcode[][] {
     67                             //odexed
     68                             new Opcode[] {
     69                                 /*Z*/   Opcode.IGET_VOLATILE,
     70                                 /*B*/   Opcode.IGET_VOLATILE,
     71                                 /*S*/   Opcode.IGET_VOLATILE,
     72                                 /*C*/   Opcode.IGET_VOLATILE,
     73                                 /*I,F*/ Opcode.IGET_VOLATILE,
     74                                 /*J,D*/ Opcode.IGET_WIDE_VOLATILE,
     75                                 /*L,[*/ Opcode.IGET_OBJECT_VOLATILE
     76                             },
     77                             //deodexed
     78                             new Opcode[] {
     79                                 /*Z*/   Opcode.IGET_BOOLEAN,
     80                                 /*B*/   Opcode.IGET_BYTE,
     81                                 /*S*/   Opcode.IGET_SHORT,
     82                                 /*C*/   Opcode.IGET_CHAR,
     83                                 /*I,F*/ Opcode.IGET,
     84                                 /*J,D*/ Opcode.IGET_WIDE,
     85                                 /*L,[*/ Opcode.IGET_OBJECT
     86                             }
     87                     },
     88                     //sget volatile
     89                     new Opcode[][] {
     90                             //odexed
     91                             new Opcode[] {
     92                                 /*Z*/   Opcode.SGET_VOLATILE,
     93                                 /*B*/   Opcode.SGET_VOLATILE,
     94                                 /*S*/   Opcode.SGET_VOLATILE,
     95                                 /*C*/   Opcode.SGET_VOLATILE,
     96                                 /*I,F*/ Opcode.SGET_VOLATILE,
     97                                 /*J,D*/ Opcode.SGET_WIDE_VOLATILE,
     98                                 /*L,[*/ Opcode.SGET_OBJECT_VOLATILE
     99                             },
    100                             //deodexed
    101                             new Opcode[] {
    102                                 /*Z*/   Opcode.SGET_BOOLEAN,
    103                                 /*B*/   Opcode.SGET_BYTE,
    104                                 /*S*/   Opcode.SGET_SHORT,
    105                                 /*C*/   Opcode.SGET_CHAR,
    106                                 /*I,F*/ Opcode.SGET,
    107                                 /*J,D*/ Opcode.SGET_WIDE,
    108                                 /*L,[*/ Opcode.SGET_OBJECT
    109                             }
    110                     }
    111             },
    112             //put opcodes
    113             new Opcode[][][] {
    114                     //iput quick
    115                     new Opcode[][] {
    116                             //odexed
    117                             new Opcode[] {
    118                                 /*Z*/   Opcode.IPUT_QUICK,
    119                                 /*B*/   Opcode.IPUT_QUICK,
    120                                 /*S*/   Opcode.IPUT_QUICK,
    121                                 /*C*/   Opcode.IPUT_QUICK,
    122                                 /*I,F*/ Opcode.IPUT_QUICK,
    123                                 /*J,D*/ Opcode.IPUT_WIDE_QUICK,
    124                                 /*L,[*/ Opcode.IPUT_OBJECT_QUICK
    125                             },
    126                             //deodexed
    127                             new Opcode[] {
    128                                 /*Z*/   Opcode.IPUT_BOOLEAN,
    129                                 /*B*/   Opcode.IPUT_BYTE,
    130                                 /*S*/   Opcode.IPUT_SHORT,
    131                                 /*C*/   Opcode.IPUT_CHAR,
    132                                 /*I,F*/ Opcode.IPUT,
    133                                 /*J,D*/ Opcode.IPUT_WIDE,
    134                                 /*L,[*/ Opcode.IPUT_OBJECT
    135                             }
    136                     },
    137                     //iput volatile
    138                     new Opcode[][] {
    139                             //odexed
    140                             new Opcode[] {
    141                                 /*Z*/   Opcode.IPUT_VOLATILE,
    142                                 /*B*/   Opcode.IPUT_VOLATILE,
    143                                 /*S*/   Opcode.IPUT_VOLATILE,
    144                                 /*C*/   Opcode.IPUT_VOLATILE,
    145                                 /*I,F*/ Opcode.IPUT_VOLATILE,
    146                                 /*J,D*/ Opcode.IPUT_WIDE_VOLATILE,
    147                                 /*L,[*/ Opcode.IPUT_OBJECT_VOLATILE
    148                             },
    149                             //deodexed
    150                             new Opcode[] {
    151                                 /*Z*/   Opcode.IPUT_BOOLEAN,
    152                                 /*B*/   Opcode.IPUT_BYTE,
    153                                 /*S*/   Opcode.IPUT_SHORT,
    154                                 /*C*/   Opcode.IPUT_CHAR,
    155                                 /*I,F*/ Opcode.IPUT,
    156                                 /*J,D*/ Opcode.IPUT_WIDE,
    157                                 /*L,[*/ Opcode.IPUT_OBJECT
    158                             }
    159                     },
    160                     //sput volatile
    161                     new Opcode[][] {
    162                             //odexed
    163                             new Opcode[] {
    164                                 /*Z*/   Opcode.SPUT_VOLATILE,
    165                                 /*B*/   Opcode.SPUT_VOLATILE,
    166                                 /*S*/   Opcode.SPUT_VOLATILE,
    167                                 /*C*/   Opcode.SPUT_VOLATILE,
    168                                 /*I,F*/ Opcode.SPUT_VOLATILE,
    169                                 /*J,D*/ Opcode.SPUT_WIDE_VOLATILE,
    170                                 /*L,[*/ Opcode.SPUT_OBJECT_VOLATILE
    171                             },
    172                             //deodexed
    173                             new Opcode[] {
    174                                 /*Z*/   Opcode.SPUT_BOOLEAN,
    175                                 /*B*/   Opcode.SPUT_BYTE,
    176                                 /*S*/   Opcode.SPUT_SHORT,
    177                                 /*C*/   Opcode.SPUT_CHAR,
    178                                 /*I,F*/ Opcode.SPUT,
    179                                 /*J,D*/ Opcode.SPUT_WIDE,
    180                                 /*L,[*/ Opcode.SPUT_OBJECT
    181                             }
    182                     }
    183             }
    184     };
    185 
    186     private static int getTypeIndex(char type) {
    187         switch (type) {
    188             case 'Z':
    189                 return 0;
    190             case 'B':
    191                 return 1;
    192             case 'S':
    193                 return 2;
    194             case 'C':
    195                 return 3;
    196             case 'I':
    197             case 'F':
    198                 return 4;
    199             case 'J':
    200             case 'D':
    201                 return 5;
    202             case 'L':
    203             case '[':
    204                 return 6;
    205             default:
    206         }
    207         throw new RuntimeException(String.format("Unknown type %s: ", type));
    208     }
    209 
    210     private static int getOpcodeSubtype(@Nonnull Opcode opcode) {
    211         if (opcode.isOdexedInstanceQuick()) {
    212             return 0;
    213         } else if (opcode.isOdexedInstanceVolatile()) {
    214             return 1;
    215         } else if (opcode.isOdexedStaticVolatile()) {
    216             return 2;
    217         }
    218         throw new RuntimeException(String.format("Not an odexed field access opcode: %s", opcode.name));
    219     }
    220 
    221     @Nonnull
    222     static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(@Nonnull String fieldType, @Nonnull Opcode odexedOpcode) {
    223         int opcodeType = odexedOpcode.setsRegister()?0:1;
    224         int opcodeSubType = getOpcodeSubtype(odexedOpcode);
    225         int typeIndex = getTypeIndex(fieldType.charAt(0));
    226 
    227         Opcode correctOdexedOpcode, deodexedOpcode;
    228 
    229         correctOdexedOpcode = opcodeMap[opcodeType][opcodeSubType][0][typeIndex];
    230         deodexedOpcode = opcodeMap[opcodeType][opcodeSubType][1][typeIndex];
    231 
    232         if (correctOdexedOpcode != odexedOpcode) {
    233             throw new AnalysisException(String.format("Incorrect field type \"%s\" for %s", fieldType,
    234                     odexedOpcode.name));
    235         }
    236 
    237         return deodexedOpcode;
    238     }
    239 }
    240 
    241 
    242