Home | History | Annotate | Download | only in libdex
      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 /*
     18  * Dalvik instruction utility functions.
     19  */
     20 #ifndef LIBDEX_INSTRUTILS_H_
     21 #define LIBDEX_INSTRUTILS_H_
     22 
     23 #include "DexFile.h"
     24 #include "DexOpcodes.h"
     25 
     26 /*
     27  * Possible instruction formats associated with Dalvik opcodes.
     28  *
     29  * See the file opcode-gen/README.txt for information about updating
     30  * opcodes and instruction formats.
     31  */
     32 enum InstructionFormat {
     33     kFmt00x = 0,    // unknown format (also used for "breakpoint" opcode)
     34     kFmt10x,        // op
     35     kFmt12x,        // op vA, vB
     36     kFmt11n,        // op vA, #+B
     37     kFmt11x,        // op vAA
     38     kFmt10t,        // op +AA
     39     kFmt20bc,       // [opt] op AA, thing@BBBB
     40     kFmt20t,        // op +AAAA
     41     kFmt22x,        // op vAA, vBBBB
     42     kFmt21t,        // op vAA, +BBBB
     43     kFmt21s,        // op vAA, #+BBBB
     44     kFmt21h,        // op vAA, #+BBBB00000[00000000]
     45     kFmt21c,        // op vAA, thing@BBBB
     46     kFmt23x,        // op vAA, vBB, vCC
     47     kFmt22b,        // op vAA, vBB, #+CC
     48     kFmt22t,        // op vA, vB, +CCCC
     49     kFmt22s,        // op vA, vB, #+CCCC
     50     kFmt22c,        // op vA, vB, thing@CCCC
     51     kFmt22cs,       // [opt] op vA, vB, field offset CCCC
     52     kFmt30t,        // op +AAAAAAAA
     53     kFmt32x,        // op vAAAA, vBBBB
     54     kFmt31i,        // op vAA, #+BBBBBBBB
     55     kFmt31t,        // op vAA, +BBBBBBBB
     56     kFmt31c,        // op vAA, string@BBBBBBBB
     57     kFmt35c,        // op {vC,vD,vE,vF,vG}, thing@BBBB
     58     kFmt35ms,       // [opt] invoke-virtual+super
     59     kFmt3rc,        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
     60     kFmt3rms,       // [opt] invoke-virtual+super/range
     61     kFmt51l,        // op vAA, #+BBBBBBBBBBBBBBBB
     62     kFmt35mi,       // [opt] inline invoke
     63     kFmt3rmi,       // [opt] inline invoke/range
     64     kFmt33x,        // exop vAA, vBB, vCCCC
     65     kFmt32s,        // exop vAA, vBB, #+CCCC
     66     kFmt40sc,       // [opt] exop AAAA, thing@BBBBBBBB
     67     kFmt41c,        // exop vAAAA, thing@BBBBBBBB
     68     kFmt52c,        // exop vAAAA, vBBBB, thing@CCCCCCCC
     69     kFmt5rc,        // exop {vCCCC .. v(CCCC+AAAA-1)}, thing@BBBBBBBB
     70 };
     71 
     72 /*
     73  * Types of indexed reference that are associated with opcodes whose
     74  * formats include such an indexed reference (e.g., 21c and 35c).
     75  */
     76 enum InstructionIndexType {
     77     kIndexUnknown = 0,
     78     kIndexNone,         // has no index
     79     kIndexVaries,       // "It depends." Used for throw-verification-error
     80     kIndexTypeRef,      // type reference index
     81     kIndexStringRef,    // string reference index
     82     kIndexMethodRef,    // method reference index
     83     kIndexFieldRef,     // field reference index
     84     kIndexInlineMethod, // inline method index (for inline linked methods)
     85     kIndexVtableOffset, // vtable offset (for static linked methods)
     86     kIndexFieldOffset   // field offset (for static linked fields)
     87 };
     88 
     89 /*
     90  * Instruction width implied by an opcode's format; a value in the
     91  * range 0 to 5. Note that there are special "pseudo-instructions"
     92  * which are used to encode switch and data tables, and these don't
     93  * have a fixed width. See dexGetWidthFromInstruction(), below.
     94  */
     95 typedef u1 InstructionWidth;
     96 
     97 /*
     98  * Opcode control flow flags, used by the verifier and JIT.
     99  */
    100 typedef u1 OpcodeFlags;
    101 enum OpcodeFlagsBits {
    102     kInstrCanBranch     = 1,        // conditional or unconditional branch
    103     kInstrCanContinue   = 1 << 1,   // flow can continue to next statement
    104     kInstrCanSwitch     = 1 << 2,   // switch statement
    105     kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
    106     kInstrCanReturn     = 1 << 4,   // returns, no additional statements
    107     kInstrInvoke        = 1 << 5,   // a flavor of invoke
    108 };
    109 
    110 /*
    111  * Struct that includes a pointer to each of the opcode information
    112  * tables.
    113  *
    114  * Note: We use "u1*" here instead of the names of the enumerated
    115  * types to guarantee that elements don't use much space. We hold out
    116  * hope for a standard way to indicate the size of an enumerated type
    117  * that works for both C and C++, but in the mean time, this will
    118  * suffice.
    119  */
    120 struct InstructionInfoTables {
    121     u1*                formats;    /* InstructionFormat elements */
    122     u1*                indexTypes; /* InstructionIndexType elements */
    123     OpcodeFlags*       flags;
    124     InstructionWidth*  widths;
    125 };
    126 
    127 /*
    128  * Global InstructionInfoTables struct.
    129  */
    130 extern InstructionInfoTables gDexOpcodeInfo;
    131 
    132 /*
    133  * Holds the contents of a decoded instruction.
    134  */
    135 struct DecodedInstruction {
    136     u4      vA;
    137     u4      vB;
    138     u8      vB_wide;        /* for kFmt51l */
    139     u4      vC;
    140     u4      arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
    141     Opcode  opcode;
    142     InstructionIndexType indexType;
    143 };
    144 
    145 /*
    146  * Return the instruction width of the specified opcode, or 0 if not defined.
    147  */
    148 DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode)
    149 {
    150     assert((u4) opcode < kNumPackedOpcodes);
    151     return gDexOpcodeInfo.widths[opcode];
    152 }
    153 
    154 /*
    155  * Return the width of the specified instruction, or 0 if not defined.  Also
    156  * works for special OP_NOP entries, including switch statement data tables
    157  * and array data.
    158  */
    159 size_t dexGetWidthFromInstruction(const u2* insns);
    160 
    161 /*
    162  * Returns the flags for the specified opcode.
    163  */
    164 DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode)
    165 {
    166     assert((u4) opcode < kNumPackedOpcodes);
    167     return gDexOpcodeInfo.flags[opcode];
    168 }
    169 
    170 /*
    171  * Returns true if the given flags represent a goto (unconditional branch).
    172  */
    173 DEX_INLINE bool dexIsGoto(OpcodeFlags flags)
    174 {
    175     return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch;
    176 }
    177 
    178 /*
    179  * Return the instruction format for the specified opcode.
    180  */
    181 DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode)
    182 {
    183     assert((u4) opcode < kNumPackedOpcodes);
    184     return (InstructionFormat) gDexOpcodeInfo.formats[opcode];
    185 }
    186 
    187 /*
    188  * Return the instruction index type for the specified opcode.
    189  */
    190 DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode)
    191 {
    192     assert((u4) opcode < kNumPackedOpcodes);
    193     return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode];
    194 }
    195 
    196 /*
    197  * Decode the instruction pointed to by "insns".
    198  */
    199 void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
    200 
    201 #endif  // LIBDEX_INSTRUTILS_H_
    202