Home | History | Annotate | Download | only in dasm
      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