blob: c6d81abf06392cf19b92da6a40c9b28e576382dd [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"
Dan Bornsteindf4daaf2010-12-01 14:23:44 -080024#include "DexOpcodes.h"
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080025
26/*
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080027 * Possible instruction formats associated with Dalvik opcodes.
Carl Shapirode750892010-06-08 16:37:12 -070028 *
Dan Bornstein758a6732010-11-30 10:45:02 -080029 * See the file opcode-gen/README.txt for information about updating
30 * opcodes and instruction formats.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080031 */
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080032typedef enum {
Dan Bornstein84244322010-11-17 12:05:04 -080033 kFmt00x = 0, // unknown format (also used for "breakpoint" opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080034 kFmt10x, // op
35 kFmt12x, // op vA, vB
36 kFmt11n, // op vA, #+B
37 kFmt11x, // op vAA
38 kFmt10t, // op +AA
Andy McFaddend3250112010-11-03 14:32:42 -070039 kFmt20bc, // [opt] op AA, thing@BBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080040 kFmt20t, // op +AAAA
41 kFmt22x, // op vAA, vBBBB
42 kFmt21t, // op vAA, +BBBB
43 kFmt21s, // op vAA, #+BBBB
44 kFmt21h, // op vAA, #+BBBB00000[00000000]
45 kFmt21c, // op vAA, thing@BBBB
46 kFmt23x, // op vAA, vBB, vCC
47 kFmt22b, // op vAA, vBB, #+CC
48 kFmt22t, // op vA, vB, +CCCC
49 kFmt22s, // op vA, vB, #+CCCC
50 kFmt22c, // op vA, vB, thing@CCCC
51 kFmt22cs, // [opt] op vA, vB, field offset CCCC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080052 kFmt30t, // op +AAAAAAAA
Andy McFaddend3250112010-11-03 14:32:42 -070053 kFmt32x, // op vAAAA, vBBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080054 kFmt31i, // op vAA, #+BBBBBBBB
Andy McFaddend3250112010-11-03 14:32:42 -070055 kFmt31t, // op vAA, +BBBBBBBB
56 kFmt31c, // op vAA, string@BBBBBBBB
Dan Bornstein7b3e9b02010-11-09 17:15:10 -080057 kFmt35c, // op {vC,vD,vE,vF,vG}, thing@BBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080058 kFmt35ms, // [opt] invoke-virtual+super
Dan Bornstein4a6b4822010-11-11 12:26:58 -080059 kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080060 kFmt3rms, // [opt] invoke-virtual+super/range
Andy McFaddend3250112010-11-03 14:32:42 -070061 kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB
Dan Bornstein7b3e9b02010-11-09 17:15:10 -080062 kFmt35mi, // [opt] inline invoke
63 kFmt3rmi, // [opt] inline invoke/range
Dan Bornstein7b3e9b02010-11-09 17:15:10 -080064 kFmt33x, // exop vAA, vBB, vCCCC
65 kFmt32s, // exop vAA, vBB, #+CCCC
66 kFmt41c, // exop vAAAA, thing@BBBBBBBB
Dan Bornstein44a38f42010-11-10 17:34:32 -080067 kFmt52c, // exop vAAAA, vBBBB, thing@CCCCCCCC
Dan Bornstein4a6b4822010-11-11 12:26:58 -080068 kFmt5rc, // exop {vCCCC .. v(CCCC+AAAA-1)}, thing@BBBBBBBB
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080069} InstructionFormat;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080070
71/*
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080072 * Types of indexed reference that are associated with opcodes whose
73 * formats include such an indexed reference (e.g., 21c and 35c).
Dan Bornstein44a38f42010-11-10 17:34:32 -080074 */
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080075typedef enum InstructionIndexType {
Dan Bornstein44a38f42010-11-10 17:34:32 -080076 kIndexUnknown = 0,
77 kIndexNone, // has no index
78 kIndexVaries, // "It depends." Used for throw-verification-error
Dan Bornstein1530c3e2010-11-12 12:51:35 -080079 kIndexTypeRef, // type reference index
Dan Bornstein44a38f42010-11-10 17:34:32 -080080 kIndexStringRef, // string reference index
81 kIndexMethodRef, // method reference index
82 kIndexFieldRef, // field reference index
83 kIndexInlineMethod, // inline method index (for inline linked methods)
84 kIndexVtableOffset, // vtable offset (for static linked methods)
85 kIndexFieldOffset // field offset (for static linked fields)
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080086} InstructionIndexType;
87
88/*
89 * Instruction width implied by an opcode; a value in the range 0 to
90 * 5. Note that there are special "pseudo-instructions" which are used
91 * to encode switch and data tables, and these don't have a fixed width.
92 * See dexGetInstrOrTableWidth(), below.
93 */
94typedef u1 InstructionWidth;
95
96/*
97 * Opcode control flow flags, used by the verifier and JIT.
98 */
99typedef u1 InstructionFlags;
100enum InstructionFlagsBits {
101 kInstrCanBranch = 1, // conditional or unconditional branch
102 kInstrCanContinue = 1 << 1, // flow can continue to next statement
103 kInstrCanSwitch = 1 << 2, // switch statement
104 kInstrCanThrow = 1 << 3, // could cause an exception to be thrown
105 kInstrCanReturn = 1 << 4, // returns, no additional statements
106 kInstrInvoke = 1 << 5, // a flavor of invoke
Dan Bornstein44a38f42010-11-10 17:34:32 -0800107};
108
109/*
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800110 * Struct that includes a pointer to each of the opcode information
111 * tables.
112 *
113 * Note: We use "u1*" here instead of the names of the enumerated
114 * types to guarantee that elements don't use much space. We hold out
115 * hope for a standard way to indicate the size of an enumerated type
116 * that works for both C and C++, but in the mean time, this will
117 * suffice.
118 */
119typedef struct InstructionInfoTables {
120 u1* formats; /* InstructionFormat elements */
121 u1* indexTypes; /* InstructionIndexType elements */
122 InstructionFlags* flags;
123 InstructionWidth* widths;
124} InstructionInfoTables;
125
126/*
127 * Global InstructionInfoTables struct.
128 */
129extern InstructionInfoTables gDexOpcodeInfo;
130
131/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800132 * Holds the contents of a decoded instruction.
133 */
134typedef struct DecodedInstruction {
135 u4 vA;
136 u4 vB;
137 u8 vB_wide; /* for kFmt51l */
138 u4 vC;
139 u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800140 Opcode opcode;
Dan Bornstein44a38f42010-11-10 17:34:32 -0800141 InstructionIndexType indexType;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800142} DecodedInstruction;
143
144/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800145 * Return the width of the specified instruction, or 0 if not defined.
146 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800147DEX_INLINE size_t dexGetInstrWidth(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800148{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800149 //assert(/*opcode >= 0 &&*/ opcode < kNumDalvikInstructions);
150 return gDexOpcodeInfo.widths[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800151}
152
153/*
154 * Return the width of the specified instruction, or 0 if not defined. Also
155 * works for special OP_NOP entries, including switch statement data tables
156 * and array data.
157 */
Dan Bornstein54322392010-11-17 14:16:56 -0800158size_t dexGetInstrOrTableWidth(const u2* insns);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800159
160/*
161 * Returns the flags for the specified opcode.
162 */
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800163DEX_INLINE InstructionFlags dexGetInstrFlags(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800164{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800165 //assert(/*opcode >= 0 &&*/ opcode < kNumDalvikInstructions);
166 return gDexOpcodeInfo.flags[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800167}
168
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800169/*
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800170 * Returns true if the given flags represent a goto (unconditional branch).
171 */
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800172DEX_INLINE bool dexIsGoto(InstructionFlags flags)
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800173{
174 return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch;
175}
176
177/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800178 * Return the instruction format for the specified opcode.
179 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800180DEX_INLINE InstructionFormat dexGetInstrFormat(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800181{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800182 //assert(/*opcode >= 0 &&*/ opcode < kNumDalvikInstructions);
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800183 return (InstructionFormat) gDexOpcodeInfo.formats[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800184}
185
186/*
Dan Bornstein44a38f42010-11-10 17:34:32 -0800187 * Return the instruction index type for the specified opcode.
188 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800189DEX_INLINE InstructionIndexType dexGetInstrIndexType(Opcode opcode)
Dan Bornstein44a38f42010-11-10 17:34:32 -0800190{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800191 //assert(/*opcode >= 0 &&*/ opcode < kNumDalvikInstructions);
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800192 return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode];
Dan Bornstein44a38f42010-11-10 17:34:32 -0800193}
194
195/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800196 * Decode the instruction pointed to by "insns".
197 */
Dan Bornstein54322392010-11-17 14:16:56 -0800198void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800199
200#endif /*_LIBDEX_INSTRUTILS*/