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