1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dasm;
18 
19 import com.android.dx.dex.code.Dop;
20 import com.android.dx.dex.code.Dops;
21 import com.android.dx.dex.code.InsnFormat;
22 import com.android.dx.dex.code.form.Form10t;
23 import com.android.dx.dex.code.form.Form10x;
24 import com.android.dx.dex.code.form.Form11n;
25 import com.android.dx.dex.code.form.Form11x;
26 import com.android.dx.dex.code.form.Form12x;
27 import com.android.dx.dex.code.form.Form20t;
28 import com.android.dx.dex.code.form.Form21c;
29 import com.android.dx.dex.code.form.Form21h;
30 import com.android.dx.dex.code.form.Form21s;
31 import com.android.dx.dex.code.form.Form21t;
32 import com.android.dx.dex.code.form.Form22b;
33 import com.android.dx.dex.code.form.Form22c;
34 import com.android.dx.dex.code.form.Form22s;
35 import com.android.dx.dex.code.form.Form22t;
36 import com.android.dx.dex.code.form.Form22x;
37 import com.android.dx.dex.code.form.Form23x;
38 import com.android.dx.dex.code.form.Form30t;
39 import com.android.dx.dex.code.form.Form31c;
40 import com.android.dx.dex.code.form.Form31i;
41 import com.android.dx.dex.code.form.Form31t;
42 import com.android.dx.dex.code.form.Form32x;
43 import com.android.dx.dex.code.form.Form35c;
44 import com.android.dx.dex.code.form.Form3rc;
45 import com.android.dx.dex.code.form.Form51l;
46 import com.android.dx.io.Opcodes;
47 
48 import java.util.Hashtable;
49 
50 /**
51  * Holds information about Dalvik opcodes and its parameters.
52  */
53 class DopInfo {
54 
55     // maps instruction name -> DopInfo object
56     static Hashtable<String, DopInfo> dopsTable;
57 
58     // information maintained about each instruction:
59     public String name; // opcode name
60     public Dop opcode; // its opcode
61     public String args; // the argument code
62 
63     public final static String ARG_REGISTER = "R";
64     public final static String ARG_TYPE = "T";
65     public final static String ARG_LITERAL = "I";
66     public final static String ARG_ADDRESS = "A";
67     public final static String ARG_FIELD = "F";
68     public final static String ARG_METHOD = "M";
69     public final static String ARG_INTFMETHOD = "Y";
70     public final static String ARG_STRING = "S";
71     public final static String ARG_REGLIST = "Z";
72     public final static String ARG_REGRANGE = "G";
73 
74     /**
75      * define type of parameters each instruction has
76      */
77     public final static String ARG_REG_REG = ARG_REGISTER + ARG_REGISTER;
78     public final static String ARG_REG_REG_REG = ARG_REGISTER + ARG_REGISTER
79             + ARG_REGISTER;
80     public final static String ARG_REG_LITERAL = ARG_REGISTER + ARG_LITERAL;
81     public final static String ARG_REG_REG_LITERAL = ARG_REGISTER
82             + ARG_REGISTER + ARG_LITERAL;
83     public final static String ARG_REG_ADDRESS = ARG_REGISTER + ARG_ADDRESS;
84     public final static String ARG_REG_REG_ADDRESS = ARG_REGISTER
85             + ARG_REGISTER + ARG_ADDRESS;
86     public final static String ARG_REG_TYPE = ARG_REGISTER + ARG_TYPE;
87     public final static String ARG_REG_REG_TYPE = ARG_REGISTER + ARG_REGISTER
88             + ARG_TYPE;
89     public final static String ARG_REG_FIELD = ARG_REGISTER + ARG_FIELD;
90     public final static String ARG_REG_REG_FIELD = ARG_REGISTER + ARG_REGISTER
91             + ARG_FIELD;
92     public final static String ARG_REG_STRING = ARG_REGISTER + ARG_STRING;
93     public final static String ARG_REG_REG_STRING = ARG_REGISTER + ARG_REGISTER
94             + ARG_STRING;
95     public final static String ARG_REGLIST_TYPE = ARG_REGLIST + ARG_TYPE;
96     public final static String ARG_REGLIST_METHOD = ARG_REGLIST + ARG_METHOD;
97     public final static String ARG_REGLIST_INTFMETHOD = ARG_REGLIST
98             + ARG_INTFMETHOD;
99     public final static String ARG_REGRANGE_TYPE = ARG_REGRANGE + ARG_TYPE;
100     public final static String ARG_REGRANGE_METHOD = ARG_REGRANGE + ARG_METHOD;
101     public final static String ARG_REGRANGE_INTFMETHOD = ARG_REGRANGE
102             + ARG_INTFMETHOD;
103 
get(String name)104     public static DopInfo get(String name) {
105         return (DopInfo) dopsTable.get(name);
106     }
107 
contains(String name)108     public static boolean contains(String name) {
109         return dopsTable.get(name) != null;
110     }
111 
112     /**
113      * Adds new opcode to table
114      */
add(String name, Dop opcode, String args)115     static private void add(String name, Dop opcode, String args) {
116         DopInfo info = new DopInfo();
117         info.name = name;
118         info.opcode = opcode;
119         info.args = args;
120         dopsTable.put(name, info);
121     }
122 
getArgsFormat(Dop dop)123     static private String getArgsFormat(Dop dop) {
124         InsnFormat format = dop.getFormat();
125 
126         if (format instanceof Form10x) return "";
127         if (format instanceof Form12x) return ARG_REG_REG;
128         if (format instanceof Form11n) return ARG_REG_LITERAL;
129         if (format instanceof Form11x) return ARG_REGISTER;
130         if (format instanceof Form10t || format instanceof Form20t)
131             return ARG_ADDRESS;
132         if (format instanceof Form22x) return ARG_REG_REG;
133         if (format instanceof Form21t) return ARG_REG_ADDRESS;
134         if (format instanceof Form21s) return ARG_REG_LITERAL;
135         if (format instanceof Form21h) return ARG_REG_LITERAL;
136         if (format instanceof Form21c) {
137             switch (dop.getOpcode()) {
138             case Opcodes.CONST_CLASS:
139             case Opcodes.CHECK_CAST:
140             case Opcodes.NEW_INSTANCE:
141                 return ARG_REG_TYPE;
142             case Opcodes.SGET:
143             case Opcodes.SGET_WIDE:
144             case Opcodes.SGET_OBJECT:
145             case Opcodes.SGET_BOOLEAN:
146             case Opcodes.SGET_BYTE:
147             case Opcodes.SGET_CHAR:
148             case Opcodes.SGET_SHORT:
149             case Opcodes.SPUT:
150             case Opcodes.SPUT_WIDE:
151             case Opcodes.SPUT_OBJECT:
152             case Opcodes.SPUT_BOOLEAN:
153             case Opcodes.SPUT_BYTE:
154             case Opcodes.SPUT_CHAR:
155             case Opcodes.SPUT_SHORT:
156                 return ARG_REG_FIELD;
157             default:
158                 return ARG_REG_STRING;
159             }
160         }
161         if (format instanceof Form23x) return ARG_REG_REG_REG;
162         if (format instanceof Form22b) return ARG_REG_REG_LITERAL;
163         if (format instanceof Form22t) return ARG_REG_REG_ADDRESS;
164         if (format instanceof Form22s) return ARG_REG_REG_LITERAL;
165         if (format instanceof Form22c) {
166             switch (dop.getOpcode()) {
167             case Opcodes.INSTANCE_OF:
168             case Opcodes.NEW_ARRAY:
169                 return ARG_REG_REG_TYPE;
170             case Opcodes.IGET:
171             case Opcodes.IGET_WIDE:
172             case Opcodes.IGET_OBJECT:
173             case Opcodes.IGET_BOOLEAN:
174             case Opcodes.IGET_BYTE:
175             case Opcodes.IGET_CHAR:
176             case Opcodes.IGET_SHORT:
177             case Opcodes.IPUT:
178             case Opcodes.IPUT_WIDE:
179             case Opcodes.IPUT_OBJECT:
180             case Opcodes.IPUT_BOOLEAN:
181             case Opcodes.IPUT_BYTE:
182             case Opcodes.IPUT_CHAR:
183             case Opcodes.IPUT_SHORT:
184                 return ARG_REG_REG_FIELD;
185             default:
186                 return ARG_REG_REG_STRING;
187             }
188         }
189         if (format instanceof Form30t) return ARG_ADDRESS;
190         if (format instanceof Form32x) return ARG_REG_REG;
191         if (format instanceof Form31i) return ARG_REG_LITERAL;
192         if (format instanceof Form31t) return ARG_REG_ADDRESS;
193         if (format instanceof Form31c) return ARG_REG_STRING;
194         if (format instanceof Form35c) {
195             switch (dop.getOpcode()) {
196             case Opcodes.INVOKE_VIRTUAL:
197             case Opcodes.INVOKE_SUPER:
198             case Opcodes.INVOKE_DIRECT:
199             case Opcodes.INVOKE_STATIC:
200                 return ARG_REGLIST_METHOD;
201             case Opcodes.INVOKE_INTERFACE:
202                 return ARG_REGLIST_INTFMETHOD;
203             default:
204                 return ARG_REGLIST_TYPE;
205             }
206         }
207         if (format instanceof Form3rc) {
208             switch (dop.getOpcode()) {
209             case Opcodes.FILLED_NEW_ARRAY_RANGE:
210                 return ARG_REGRANGE_TYPE;
211             case Opcodes.INVOKE_INTERFACE_RANGE:
212                 return ARG_REGRANGE_INTFMETHOD;
213             default:
214                 return ARG_REGRANGE_METHOD;
215             }
216         }
217         if (format instanceof Form51l) return ARG_REG_LITERAL; // not "RL" since
218                                                                // it is
219                                                                // processed as
220                                                                // Number
221 
222         return "";
223     }
224 
225     /**
226      * dopsTable initialization
227      */
228     static {
229         dopsTable = new Hashtable<String, DopInfo>();
230 
231         for (int i = 0; i < Opcodes.MAX_VALUE - Opcodes.MIN_VALUE + 1; i++) {
232             try {
233                 Dop dop = Dops.get(i);
getArgsFormat(dop)234                 add(dop.getName(), dop, getArgsFormat(dop));
235             } catch (Exception e) {
236 
237             }
238         }
239     }
240 
241 };
242