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
     21 #define _LIBDEX_INSTRUTILS
     22 
     23 #include "DexFile.h"
     24 #include "OpCode.h"
     25 
     26 /*
     27  * Dalvik-defined instruction formats.
     28  *
     29  * (This defines InstructionFormat as an unsigned char to reduce the size
     30  * of the table.  This isn't necessary with some compilers, which use an
     31  * integer width appropriate for the number of enum values.)
     32  *
     33  * If you add or delete a format, you have to change some or all of:
     34  *  - this enum
     35  *  - the switch inside dexDecodeInstruction() in InstrUtils.c
     36  *  - the switch inside dumpInstruction() in DexDump.c
     37  */
     38 typedef unsigned char InstructionFormat;
     39 enum InstructionFormat {
     40     kFmtUnknown = 0,
     41     kFmt10x,        // op
     42     kFmt12x,        // op vA, vB
     43     kFmt11n,        // op vA, #+B
     44     kFmt11x,        // op vAA
     45     kFmt10t,        // op +AA
     46     kFmt20bc,       // op AA, thing@BBBB
     47     kFmt20t,        // op +AAAA
     48     kFmt22x,        // op vAA, vBBBB
     49     kFmt21t,        // op vAA, +BBBB
     50     kFmt21s,        // op vAA, #+BBBB
     51     kFmt21h,        // op vAA, #+BBBB00000[00000000]
     52     kFmt21c,        // op vAA, thing@BBBB
     53     kFmt23x,        // op vAA, vBB, vCC
     54     kFmt22b,        // op vAA, vBB, #+CC
     55     kFmt22t,        // op vA, vB, +CCCC
     56     kFmt22s,        // op vA, vB, #+CCCC
     57     kFmt22c,        // op vA, vB, thing@CCCC
     58     kFmt22cs,       // [opt] op vA, vB, field offset CCCC
     59     kFmt32x,        // op vAAAA, vBBBB
     60     kFmt30t,        // op +AAAAAAAA
     61     kFmt31t,        // op vAA, +BBBBBBBB
     62     kFmt31i,        // op vAA, #+BBBBBBBB
     63     kFmt31c,        // op vAA, thing@BBBBBBBB
     64     kFmt35c,        // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
     65     kFmt35ms,       // [opt] invoke-virtual+super
     66     kFmt35fs,       // [opt] invoke-interface
     67     kFmt3rc,        // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
     68     kFmt3rms,       // [opt] invoke-virtual+super/range
     69     kFmt3rfs,       // [opt] invoke-interface/range
     70     kFmt3inline,    // [opt] inline invoke
     71     kFmt3rinline,   // [opt] inline invoke/range
     72     kFmt51l,        // op vAA, #+BBBBBBBBBBBBBBBB
     73 };
     74 
     75 /*
     76  * Holds the contents of a decoded instruction.
     77  */
     78 typedef struct DecodedInstruction {
     79     u4      vA;
     80     u4      vB;
     81     u8      vB_wide;        /* for kFmt51l */
     82     u4      vC;
     83     u4      arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
     84     OpCode  opCode;
     85 } DecodedInstruction;
     86 
     87 /*
     88  * Instruction width, a value in the range -3 to 5.
     89  */
     90 typedef signed char InstructionWidth;
     91 
     92 /*
     93  * Instruction flags, used by the verifier and JIT to determine where
     94  * control can flow to next.  Expected to fit in 8 bits.
     95  */
     96 typedef unsigned char InstructionFlags;
     97 enum InstructionFlags {
     98     kInstrCanBranch     = 1,        // conditional or unconditional branch
     99     kInstrCanContinue   = 1 << 1,   // flow can continue to next statement
    100     kInstrCanSwitch     = 1 << 2,   // switch statement
    101     kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
    102     kInstrCanReturn     = 1 << 4,   // returns, no additional statements
    103     kInstrInvoke        = 1 << 5,   // a flavor of invoke
    104     kInstrUnconditional = 1 << 6,   // unconditional branch
    105 };
    106 
    107 
    108 /*
    109  * Allocate and populate a 256-element array with instruction widths.  A
    110  * width of zero means the entry does not exist.
    111  */
    112 InstructionWidth* dexCreateInstrWidthTable(void);
    113 
    114 #if 0       // no longer used
    115 /*
    116  * Returns the width of the specified instruction, or 0 if not defined.
    117  * Optimized instructions use negative values.
    118  */
    119 DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode)
    120 {
    121    // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    122     return widths[opCode];
    123 }
    124 #endif
    125 
    126 /*
    127  * Return the width of the specified instruction, or 0 if not defined.
    128  */
    129 DEX_INLINE size_t dexGetInstrWidthAbs(const InstructionWidth* widths,
    130     OpCode opCode)
    131 {
    132     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    133 
    134     int val = widths[opCode];
    135     if (val < 0)
    136         val = -val;
    137     /* XXX - the no-compare trick may be a cycle slower on ARM */
    138     return val;
    139 }
    140 
    141 /*
    142  * Return the width of the specified instruction, or 0 if not defined.  Also
    143  * works for special OP_NOP entries, including switch statement data tables
    144  * and array data.
    145  */
    146 size_t dexGetInstrOrTableWidthAbs(const InstructionWidth* widths,
    147     const u2* insns);
    148 
    149 
    150 /*
    151  * Allocate and populate a 256-element array with instruction flags.
    152  */
    153 InstructionFlags* dexCreateInstrFlagsTable(void);
    154 
    155 /*
    156  * Returns the flags for the specified opcode.
    157  */
    158 DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode)
    159 {
    160     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    161     return flags[opCode];
    162 }
    163 
    164 
    165 /*
    166  * Allocate and populate a 256-element array with instruction formats.
    167  */
    168 InstructionFormat* dexCreateInstrFormatTable(void);
    169 
    170 /*
    171  * Return the instruction format for the specified opcode.
    172  */
    173 DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
    174     OpCode opCode)
    175 {
    176     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    177     return fmts[opCode];
    178 }
    179 
    180 /*
    181  * Decode the instruction pointed to by "insns".
    182  */
    183 void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
    184     DecodedInstruction* pDec);
    185 
    186 #endif /*_LIBDEX_INSTRUTILS*/
    187