blob: 8449ae5e880f2cbbf79a9bee5a1a62f2597eb3aa [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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 */
Andy McFadden3a1aedb2009-05-07 13:30:23 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
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 */
38typedef unsigned char InstructionFormat;
39enum 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
Andy McFadden3a1aedb2009-05-07 13:30:23 -070046 kFmt20bc, // op AA, thing@BBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080047 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
Andy McFaddenb0a05412009-11-19 10:23:41 -080071 kFmt3rinline, // [opt] inline invoke/range
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080072 kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB
73};
74
75/*
76 * Holds the contents of a decoded instruction.
77 */
78typedef 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 */
90typedef signed char InstructionWidth;
91
92/*
93 * Instruction flags, used by the verifier to determine where control
94 * can flow to next.
95 */
96typedef unsigned char InstructionFlags;
97enum 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
Ben Chengba4fc8b2009-06-01 13:00:29 -0700103 kInstrInvoke = 1 << 5, // a flavor of invoke
104 kInstrUnconditional = 1 << 6, // unconditional branch
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800105};
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 */
112InstructionWidth* dexCreateInstrWidthTable(void);
113
114/*
115 * Returns the width of the specified instruction, or 0 if not defined.
116 * Optimized instructions use negative values.
117 */
118DEX_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 */
127DEX_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 */
143int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns);
144
145
146/*
147 * Allocate and populate a 256-element array with instruction flags.
148 */
149InstructionFlags* dexCreateInstrFlagsTable(void);
150
151/*
152 * Returns the flags for the specified opcode.
153 */
154DEX_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 */
164InstructionFormat* dexCreateInstrFormatTable(void);
165
166/*
167 * Return the instruction format for the specified opcode.
168 */
169DEX_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 */
179void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
180 DecodedInstruction* pDec);
181
182#endif /*_LIBDEX_INSTRUTILS*/