• 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     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  */
dexGetInstrWidthAbs(const InstructionWidth * widths,OpCode opCode)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  */
dexGetInstrFlags(const InstructionFlags * flags,OpCode opCode)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  */
dexGetInstrFormat(const InstructionFormat * fmts,OpCode opCode)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