/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dasm; import com.android.dx.dex.code.Dop; import com.android.dx.dex.code.Dops; import com.android.dx.dex.code.InsnFormat; import com.android.dx.dex.code.form.Form10t; import com.android.dx.dex.code.form.Form10x; import com.android.dx.dex.code.form.Form11n; import com.android.dx.dex.code.form.Form11x; import com.android.dx.dex.code.form.Form12x; import com.android.dx.dex.code.form.Form20t; import com.android.dx.dex.code.form.Form21c; import com.android.dx.dex.code.form.Form21h; import com.android.dx.dex.code.form.Form21s; import com.android.dx.dex.code.form.Form21t; import com.android.dx.dex.code.form.Form22b; import com.android.dx.dex.code.form.Form22c; import com.android.dx.dex.code.form.Form22s; import com.android.dx.dex.code.form.Form22t; import com.android.dx.dex.code.form.Form22x; import com.android.dx.dex.code.form.Form23x; import com.android.dx.dex.code.form.Form30t; import com.android.dx.dex.code.form.Form31c; import com.android.dx.dex.code.form.Form31i; import com.android.dx.dex.code.form.Form31t; import com.android.dx.dex.code.form.Form32x; import com.android.dx.dex.code.form.Form35c; import com.android.dx.dex.code.form.Form3rc; import com.android.dx.dex.code.form.Form51l; import com.android.dx.io.Opcodes; import java.util.Hashtable; /** * Holds information about Dalvik opcodes and its parameters. */ class DopInfo { // maps instruction name -> DopInfo object static Hashtable dopsTable; // information maintained about each instruction: public String name; // opcode name public Dop opcode; // its opcode public String args; // the argument code public final static String ARG_REGISTER = "R"; public final static String ARG_TYPE = "T"; public final static String ARG_LITERAL = "I"; public final static String ARG_ADDRESS = "A"; public final static String ARG_FIELD = "F"; public final static String ARG_METHOD = "M"; public final static String ARG_INTFMETHOD = "Y"; public final static String ARG_STRING = "S"; public final static String ARG_REGLIST = "Z"; public final static String ARG_REGRANGE = "G"; /** * define type of parameters each instruction has */ public final static String ARG_REG_REG = ARG_REGISTER + ARG_REGISTER; public final static String ARG_REG_REG_REG = ARG_REGISTER + ARG_REGISTER + ARG_REGISTER; public final static String ARG_REG_LITERAL = ARG_REGISTER + ARG_LITERAL; public final static String ARG_REG_REG_LITERAL = ARG_REGISTER + ARG_REGISTER + ARG_LITERAL; public final static String ARG_REG_ADDRESS = ARG_REGISTER + ARG_ADDRESS; public final static String ARG_REG_REG_ADDRESS = ARG_REGISTER + ARG_REGISTER + ARG_ADDRESS; public final static String ARG_REG_TYPE = ARG_REGISTER + ARG_TYPE; public final static String ARG_REG_REG_TYPE = ARG_REGISTER + ARG_REGISTER + ARG_TYPE; public final static String ARG_REG_FIELD = ARG_REGISTER + ARG_FIELD; public final static String ARG_REG_REG_FIELD = ARG_REGISTER + ARG_REGISTER + ARG_FIELD; public final static String ARG_REG_STRING = ARG_REGISTER + ARG_STRING; public final static String ARG_REG_REG_STRING = ARG_REGISTER + ARG_REGISTER + ARG_STRING; public final static String ARG_REGLIST_TYPE = ARG_REGLIST + ARG_TYPE; public final static String ARG_REGLIST_METHOD = ARG_REGLIST + ARG_METHOD; public final static String ARG_REGLIST_INTFMETHOD = ARG_REGLIST + ARG_INTFMETHOD; public final static String ARG_REGRANGE_TYPE = ARG_REGRANGE + ARG_TYPE; public final static String ARG_REGRANGE_METHOD = ARG_REGRANGE + ARG_METHOD; public final static String ARG_REGRANGE_INTFMETHOD = ARG_REGRANGE + ARG_INTFMETHOD; public static DopInfo get(String name) { return (DopInfo) dopsTable.get(name); } public static boolean contains(String name) { return dopsTable.get(name) != null; } /** * Adds new opcode to table */ static private void add(String name, Dop opcode, String args) { DopInfo info = new DopInfo(); info.name = name; info.opcode = opcode; info.args = args; dopsTable.put(name, info); } static private String getArgsFormat(Dop dop) { InsnFormat format = dop.getFormat(); if (format instanceof Form10x) return ""; if (format instanceof Form12x) return ARG_REG_REG; if (format instanceof Form11n) return ARG_REG_LITERAL; if (format instanceof Form11x) return ARG_REGISTER; if (format instanceof Form10t || format instanceof Form20t) return ARG_ADDRESS; if (format instanceof Form22x) return ARG_REG_REG; if (format instanceof Form21t) return ARG_REG_ADDRESS; if (format instanceof Form21s) return ARG_REG_LITERAL; if (format instanceof Form21h) return ARG_REG_LITERAL; if (format instanceof Form21c) { switch (dop.getOpcode()) { case Opcodes.CONST_CLASS: case Opcodes.CHECK_CAST: case Opcodes.NEW_INSTANCE: return ARG_REG_TYPE; case Opcodes.SGET: case Opcodes.SGET_WIDE: case Opcodes.SGET_OBJECT: case Opcodes.SGET_BOOLEAN: case Opcodes.SGET_BYTE: case Opcodes.SGET_CHAR: case Opcodes.SGET_SHORT: case Opcodes.SPUT: case Opcodes.SPUT_WIDE: case Opcodes.SPUT_OBJECT: case Opcodes.SPUT_BOOLEAN: case Opcodes.SPUT_BYTE: case Opcodes.SPUT_CHAR: case Opcodes.SPUT_SHORT: return ARG_REG_FIELD; default: return ARG_REG_STRING; } } if (format instanceof Form23x) return ARG_REG_REG_REG; if (format instanceof Form22b) return ARG_REG_REG_LITERAL; if (format instanceof Form22t) return ARG_REG_REG_ADDRESS; if (format instanceof Form22s) return ARG_REG_REG_LITERAL; if (format instanceof Form22c) { switch (dop.getOpcode()) { case Opcodes.INSTANCE_OF: case Opcodes.NEW_ARRAY: return ARG_REG_REG_TYPE; case Opcodes.IGET: case Opcodes.IGET_WIDE: case Opcodes.IGET_OBJECT: case Opcodes.IGET_BOOLEAN: case Opcodes.IGET_BYTE: case Opcodes.IGET_CHAR: case Opcodes.IGET_SHORT: case Opcodes.IPUT: case Opcodes.IPUT_WIDE: case Opcodes.IPUT_OBJECT: case Opcodes.IPUT_BOOLEAN: case Opcodes.IPUT_BYTE: case Opcodes.IPUT_CHAR: case Opcodes.IPUT_SHORT: return ARG_REG_REG_FIELD; default: return ARG_REG_REG_STRING; } } if (format instanceof Form30t) return ARG_ADDRESS; if (format instanceof Form32x) return ARG_REG_REG; if (format instanceof Form31i) return ARG_REG_LITERAL; if (format instanceof Form31t) return ARG_REG_ADDRESS; if (format instanceof Form31c) return ARG_REG_STRING; if (format instanceof Form35c) { switch (dop.getOpcode()) { case Opcodes.INVOKE_VIRTUAL: case Opcodes.INVOKE_SUPER: case Opcodes.INVOKE_DIRECT: case Opcodes.INVOKE_STATIC: return ARG_REGLIST_METHOD; case Opcodes.INVOKE_INTERFACE: return ARG_REGLIST_INTFMETHOD; default: return ARG_REGLIST_TYPE; } } if (format instanceof Form3rc) { switch (dop.getOpcode()) { case Opcodes.FILLED_NEW_ARRAY_RANGE: return ARG_REGRANGE_TYPE; case Opcodes.INVOKE_INTERFACE_RANGE: return ARG_REGRANGE_INTFMETHOD; default: return ARG_REGRANGE_METHOD; } } if (format instanceof Form51l) return ARG_REG_LITERAL; // not "RL" since // it is // processed as // Number return ""; } /** * dopsTable initialization */ static { dopsTable = new Hashtable(); for (int i = 0; i < Opcodes.MAX_VALUE - Opcodes.MIN_VALUE + 1; i++) { try { Dop dop = Dops.get(i); add(dop.getName(), dop, getArgsFormat(dop)); } catch (Exception e) { } } } };