• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getTypeIndex(char type)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 
getOpcodeSubtype(@onnull Opcode opcode)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
getAndCheckDeodexedOpcodeForOdexedOpcode(@onnull String fieldType, @Nonnull Opcode odexedOpcode)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