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 104 public static DopInfo get(String name) { 105 return (DopInfo) dopsTable.get(name); 106 } 107 108 public static boolean contains(String name) { 109 return dopsTable.get(name) != null; 110 } 111 112 /** 113 * Adds new opcode to table 114 */ 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 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); 234 add(dop.getName(), dop, getArgsFormat(dop)); 235 } catch (Exception e) { 236 237 } 238 } 239 } 240 241 }; 242