• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      kFmt51l,        // op vAA, #+BBBBBBBBBBBBBBBB
72  };
73  
74  /*
75   * Holds the contents of a decoded instruction.
76   */
77  typedef struct DecodedInstruction {
78      u4      vA;
79      u4      vB;
80      u8      vB_wide;        /* for kFmt51l */
81      u4      vC;
82      u4      arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
83      OpCode  opCode;
84  } DecodedInstruction;
85  
86  /*
87   * Instruction width, a value in the range -3 to 5.
88   */
89  typedef signed char InstructionWidth;
90  
91  /*
92   * Instruction flags, used by the verifier to determine where control
93   * can flow to next.
94   */
95  typedef unsigned char InstructionFlags;
96  enum InstructionFlags {
97      kInstrCanBranch     = 1,        // conditional or unconditional branch
98      kInstrCanContinue   = 1 << 1,   // flow can continue to next statement
99      kInstrCanSwitch     = 1 << 2,   // switch statement
100      kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
101      kInstrCanReturn     = 1 << 4,   // returns, no additional statements
102      kInstrInvoke        = 1 << 5,   // a flavor of invoke
103      kInstrUnconditional = 1 << 6,   // unconditional branch
104  };
105  
106  
107  /*
108   * Allocate and populate a 256-element array with instruction widths.  A
109   * width of zero means the entry does not exist.
110   */
111  InstructionWidth* dexCreateInstrWidthTable(void);
112  
113  /*
114   * Returns the width of the specified instruction, or 0 if not defined.
115   * Optimized instructions use negative values.
116   */
dexGetInstrWidth(const InstructionWidth * widths,OpCode opCode)117  DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode)
118  {
119     // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
120      return widths[opCode];
121  }
122  
123  /*
124   * Return the width of the specified instruction, or 0 if not defined.
125   */
dexGetInstrWidthAbs(const InstructionWidth * widths,OpCode opCode)126  DEX_INLINE int dexGetInstrWidthAbs(const InstructionWidth* widths,OpCode opCode)
127  {
128      //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
129  
130      int val = dexGetInstrWidth(widths, opCode);
131      if (val < 0)
132          val = -val;
133      /* XXX - the no-compare trick may be a cycle slower on ARM */
134      return val;
135  }
136  
137  /*
138   * Return the width of the specified instruction, or 0 if not defined.  Also
139   * works for special OP_NOP entries, including switch statement data tables
140   * and array data.
141   */
142  int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns);
143  
144  
145  /*
146   * Allocate and populate a 256-element array with instruction flags.
147   */
148  InstructionFlags* dexCreateInstrFlagsTable(void);
149  
150  /*
151   * Returns the flags for the specified opcode.
152   */
dexGetInstrFlags(const InstructionFlags * flags,OpCode opCode)153  DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode)
154  {
155      //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
156      return flags[opCode];
157  }
158  
159  
160  /*
161   * Allocate and populate a 256-element array with instruction formats.
162   */
163  InstructionFormat* dexCreateInstrFormatTable(void);
164  
165  /*
166   * Return the instruction format for the specified opcode.
167   */
dexGetInstrFormat(const InstructionFormat * fmts,OpCode opCode)168  DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
169      OpCode opCode)
170  {
171      //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
172      return fmts[opCode];
173  }
174  
175  /*
176   * Decode the instruction pointed to by "insns".
177   */
178  void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
179      DecodedInstruction* pDec);
180  
181  #endif /*_LIBDEX_INSTRUTILS*/
182