blob: 76993a52946a8fc5f13d1629dabaef241d27fbb5 [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 */
Carl Shapiro375fb112011-06-14 20:31:24 -070020#ifndef LIBDEX_INSTRUTILS_H_
21#define LIBDEX_INSTRUTILS_H_
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080022
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 */
Carl Shapirobfc97992011-04-27 14:16:08 -070032enum InstructionFormat {
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
Carl Shapirobfc97992011-04-27 14:16:08 -070064};
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080065
66/*
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080067 * Types of indexed reference that are associated with opcodes whose
68 * formats include such an indexed reference (e.g., 21c and 35c).
Dan Bornstein44a38f42010-11-10 17:34:32 -080069 */
Carl Shapirobfc97992011-04-27 14:16:08 -070070enum InstructionIndexType {
Dan Bornstein44a38f42010-11-10 17:34:32 -080071 kIndexUnknown = 0,
72 kIndexNone, // has no index
73 kIndexVaries, // "It depends." Used for throw-verification-error
Dan Bornstein1530c3e2010-11-12 12:51:35 -080074 kIndexTypeRef, // type reference index
Dan Bornstein44a38f42010-11-10 17:34:32 -080075 kIndexStringRef, // string reference index
76 kIndexMethodRef, // method reference index
77 kIndexFieldRef, // field reference index
78 kIndexInlineMethod, // inline method index (for inline linked methods)
79 kIndexVtableOffset, // vtable offset (for static linked methods)
80 kIndexFieldOffset // field offset (for static linked fields)
Carl Shapirobfc97992011-04-27 14:16:08 -070081};
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080082
83/*
Dan Bornsteine4852762010-12-02 12:45:00 -080084 * Instruction width implied by an opcode's format; a value in the
85 * range 0 to 5. Note that there are special "pseudo-instructions"
86 * which are used to encode switch and data tables, and these don't
87 * have a fixed width. See dexGetWidthFromInstruction(), below.
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080088 */
89typedef u1 InstructionWidth;
90
91/*
92 * Opcode control flow flags, used by the verifier and JIT.
93 */
Dan Bornsteine4852762010-12-02 12:45:00 -080094typedef u1 OpcodeFlags;
95enum OpcodeFlagsBits {
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -080096 kInstrCanBranch = 1, // conditional or unconditional branch
97 kInstrCanContinue = 1 << 1, // flow can continue to next statement
98 kInstrCanSwitch = 1 << 2, // switch statement
99 kInstrCanThrow = 1 << 3, // could cause an exception to be thrown
100 kInstrCanReturn = 1 << 4, // returns, no additional statements
101 kInstrInvoke = 1 << 5, // a flavor of invoke
Dan Bornstein44a38f42010-11-10 17:34:32 -0800102};
103
104/*
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800105 * Struct that includes a pointer to each of the opcode information
106 * tables.
107 *
108 * Note: We use "u1*" here instead of the names of the enumerated
109 * types to guarantee that elements don't use much space. We hold out
110 * hope for a standard way to indicate the size of an enumerated type
111 * that works for both C and C++, but in the mean time, this will
112 * suffice.
113 */
Carl Shapirobfc97992011-04-27 14:16:08 -0700114struct InstructionInfoTables {
Dan Bornsteine4852762010-12-02 12:45:00 -0800115 u1* formats; /* InstructionFormat elements */
116 u1* indexTypes; /* InstructionIndexType elements */
117 OpcodeFlags* flags;
Dan Bornstein0f737c52010-12-02 15:15:21 -0800118 InstructionWidth* widths;
Carl Shapirobfc97992011-04-27 14:16:08 -0700119};
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800120
121/*
122 * Global InstructionInfoTables struct.
123 */
124extern InstructionInfoTables gDexOpcodeInfo;
125
126/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800127 * Holds the contents of a decoded instruction.
128 */
Carl Shapirobfc97992011-04-27 14:16:08 -0700129struct DecodedInstruction {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800130 u4 vA;
131 u4 vB;
132 u8 vB_wide; /* for kFmt51l */
133 u4 vC;
134 u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800135 Opcode opcode;
Dan Bornstein44a38f42010-11-10 17:34:32 -0800136 InstructionIndexType indexType;
Carl Shapirobfc97992011-04-27 14:16:08 -0700137};
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800138
139/*
Dan Bornsteine4852762010-12-02 12:45:00 -0800140 * Return the instruction width of the specified opcode, or 0 if not defined.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800141 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800142DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800143{
Dan Bornstein44209fa2010-12-03 17:24:34 -0800144 assert((u4) opcode < kNumPackedOpcodes);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800145 return gDexOpcodeInfo.widths[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800146}
147
148/*
149 * Return the width of the specified instruction, or 0 if not defined. Also
150 * works for special OP_NOP entries, including switch statement data tables
151 * and array data.
152 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800153size_t dexGetWidthFromInstruction(const u2* insns);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800154
155/*
156 * Returns the flags for the specified opcode.
157 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800158DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800159{
Dan Bornstein44209fa2010-12-03 17:24:34 -0800160 assert((u4) opcode < kNumPackedOpcodes);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800161 return gDexOpcodeInfo.flags[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800162}
163
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800164/*
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800165 * Returns true if the given flags represent a goto (unconditional branch).
166 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800167DEX_INLINE bool dexIsGoto(OpcodeFlags flags)
Dan Bornsteinc2b486f2010-11-12 16:07:16 -0800168{
169 return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch;
170}
171
172/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800173 * Return the instruction format for the specified opcode.
174 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800175DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800176{
Dan Bornstein44209fa2010-12-03 17:24:34 -0800177 assert((u4) opcode < kNumPackedOpcodes);
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800178 return (InstructionFormat) gDexOpcodeInfo.formats[opcode];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800179}
180
181/*
Dan Bornstein44a38f42010-11-10 17:34:32 -0800182 * Return the instruction index type for the specified opcode.
183 */
Dan Bornsteine4852762010-12-02 12:45:00 -0800184DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode)
Dan Bornstein44a38f42010-11-10 17:34:32 -0800185{
Dan Bornstein44209fa2010-12-03 17:24:34 -0800186 assert((u4) opcode < kNumPackedOpcodes);
Dan Bornstein4b6e9ba2010-12-02 10:35:48 -0800187 return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode];
Dan Bornstein44a38f42010-11-10 17:34:32 -0800188}
189
190/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800191 * Decode the instruction pointed to by "insns".
192 */
Dan Bornstein54322392010-11-17 14:16:56 -0800193void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800194
Carl Shapiro375fb112011-06-14 20:31:24 -0700195#endif // LIBDEX_INSTRUTILS_H_