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