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 to determine where control
     94  * can flow to next.
     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 /*
    115  * Returns the width of the specified instruction, or 0 if not defined.
    116  * Optimized instructions use negative values.
    117  */
    118 DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode)
    119 {
    120    // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    121     return widths[opCode];
    122 }
    123 
    124 /*
    125  * Return the width of the specified instruction, or 0 if not defined.
    126  */
    127 DEX_INLINE int dexGetInstrWidthAbs(const InstructionWidth* widths,OpCode opCode)
    128 {
    129     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    130 
    131     int val = dexGetInstrWidth(widths, opCode);
    132     if (val < 0)
    133         val = -val;
    134     /* XXX - the no-compare trick may be a cycle slower on ARM */
    135     return val;
    136 }
    137 
    138 /*
    139  * Return the width of the specified instruction, or 0 if not defined.  Also
    140  * works for special OP_NOP entries, including switch statement data tables
    141  * and array data.
    142  */
    143 int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns);
    144 
    145 
    146 /*
    147  * Allocate and populate a 256-element array with instruction flags.
    148  */
    149 InstructionFlags* dexCreateInstrFlagsTable(void);
    150 
    151 /*
    152  * Returns the flags for the specified opcode.
    153  */
    154 DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode)
    155 {
    156     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    157     return flags[opCode];
    158 }
    159 
    160 
    161 /*
    162  * Allocate and populate a 256-element array with instruction formats.
    163  */
    164 InstructionFormat* dexCreateInstrFormatTable(void);
    165 
    166 /*
    167  * Return the instruction format for the specified opcode.
    168  */
    169 DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
    170     OpCode opCode)
    171 {
    172     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
    173     return fmts[opCode];
    174 }
    175 
    176 /*
    177  * Decode the instruction pointed to by "insns".
    178  */
    179 void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
    180     DecodedInstruction* pDec);
    181 
    182 #endif /*_LIBDEX_INSTRUTILS*/
    183