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_H_
21 #define LIBDEX_INSTRUTILS_H_
22 
23 #include "DexFile.h"
24 #include "DexOpcodes.h"
25 
26 /*
27  * Possible instruction formats associated with Dalvik opcodes.
28  *
29  * See the file opcode-gen/README.txt for information about updating
30  * opcodes and instruction formats.
31  */
32 enum InstructionFormat {
33     kFmt00x = 0,    // unknown format (also used for "breakpoint" opcode)
34     kFmt10x,        // op
35     kFmt12x,        // op vA, vB
36     kFmt11n,        // op vA, #+B
37     kFmt11x,        // op vAA
38     kFmt10t,        // op +AA
39     kFmt20bc,       // [opt] op AA, thing@BBBB
40     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
52     kFmt30t,        // op +AAAAAAAA
53     kFmt32x,        // op vAAAA, vBBBB
54     kFmt31i,        // op vAA, #+BBBBBBBB
55     kFmt31t,        // op vAA, +BBBBBBBB
56     kFmt31c,        // op vAA, string@BBBBBBBB
57     kFmt35c,        // op {vC,vD,vE,vF,vG}, thing@BBBB
58     kFmt35ms,       // [opt] invoke-virtual+super
59     kFmt3rc,        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
60     kFmt3rms,       // [opt] invoke-virtual+super/range
61     kFmt51l,        // op vAA, #+BBBBBBBBBBBBBBBB
62     kFmt35mi,       // [opt] inline invoke
63     kFmt3rmi,       // [opt] inline invoke/range
64     kFmt45cc,       // op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH
65     kFmt4rcc,       // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH
66 };
67 
68 /*
69  * Types of indexed reference that are associated with opcodes whose
70  * formats include such an indexed reference (e.g., 21c and 35c).
71  */
72 enum InstructionIndexType {
73     kIndexUnknown = 0,
74     kIndexNone,              // has no index
75     kIndexVaries,            // "It depends." Used for throw-verification-error
76     kIndexTypeRef,           // type reference index
77     kIndexStringRef,         // string reference index
78     kIndexMethodRef,         // method reference index
79     kIndexFieldRef,          // field reference index
80     kIndexInlineMethod,      // inline method index (for inline linked methods)
81     kIndexVtableOffset,      // vtable offset (for static linked methods)
82     kIndexFieldOffset,       // field offset (for static linked fields)
83     kIndexMethodAndProtoRef, // method index and proto index
84     kIndexCallSiteRef,       // call site index
85     kIndexMethodHandleRef,   // constant method handle reference index
86     kIndexProtoRef,          // constant prototype reference index
87 };
88 
89 /*
90  * Instruction width implied by an opcode's format; a value in the
91  * range 0 to 5. Note that there are special "pseudo-instructions"
92  * which are used to encode switch and data tables, and these don't
93  * have a fixed width. See dexGetWidthFromInstruction(), below.
94  */
95 typedef u1 InstructionWidth;
96 
97 /*
98  * Opcode control flow flags, used by the verifier and JIT.
99  */
100 typedef u1 OpcodeFlags;
101 enum OpcodeFlagsBits {
102     kInstrCanBranch     = 1,        // conditional or unconditional branch
103     kInstrCanContinue   = 1 << 1,   // flow can continue to next statement
104     kInstrCanSwitch     = 1 << 2,   // switch statement
105     kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
106     kInstrCanReturn     = 1 << 4,   // returns, no additional statements
107     kInstrInvoke        = 1 << 5,   // a flavor of invoke
108 };
109 
110 /*
111  * Struct that includes a pointer to each of the opcode information
112  * tables.
113  *
114  * Note: We use "u1*" here instead of the names of the enumerated
115  * types to guarantee that elements don't use much space. We hold out
116  * hope for a standard way to indicate the size of an enumerated type
117  * that works for both C and C++, but in the mean time, this will
118  * suffice.
119  */
120 struct InstructionInfoTables {
121     u1*                formats;    /* InstructionFormat elements */
122     u1*                indexTypes; /* InstructionIndexType elements */
123     OpcodeFlags*       flags;
124     InstructionWidth*  widths;
125 };
126 
127 /*
128  * Global InstructionInfoTables struct.
129  */
130 extern InstructionInfoTables gDexOpcodeInfo;
131 
132 /*
133  * Holds the contents of a decoded instruction.
134  */
135 struct DecodedInstruction {
136     u4      vA;
137     u4      vB;
138     u8      vB_wide;        /* for kFmt51l */
139     u4      vC;
140     u4      arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
141     Opcode  opcode;
142     InstructionIndexType indexType;
143 };
144 
145 /*
146  * Return the instruction width of the specified opcode, or 0 if not defined.
147  */
dexGetWidthFromOpcode(Opcode opcode)148 DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode)
149 {
150     assert((u4) opcode < kNumPackedOpcodes);
151     return gDexOpcodeInfo.widths[opcode];
152 }
153 
154 /*
155  * Return the width of the specified instruction, or 0 if not defined.  Also
156  * works for special OP_NOP entries, including switch statement data tables
157  * and array data.
158  */
159 size_t dexGetWidthFromInstruction(const u2* insns);
160 
161 /*
162  * Returns the flags for the specified opcode.
163  */
dexGetFlagsFromOpcode(Opcode opcode)164 DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode)
165 {
166     assert((u4) opcode < kNumPackedOpcodes);
167     return gDexOpcodeInfo.flags[opcode];
168 }
169 
170 /*
171  * Returns true if the given flags represent a goto (unconditional branch).
172  */
dexIsGoto(OpcodeFlags flags)173 DEX_INLINE bool dexIsGoto(OpcodeFlags flags)
174 {
175     return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch;
176 }
177 
178 /*
179  * Return the instruction format for the specified opcode.
180  */
dexGetFormatFromOpcode(Opcode opcode)181 DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode)
182 {
183     assert((u4) opcode < kNumPackedOpcodes);
184     return (InstructionFormat) gDexOpcodeInfo.formats[opcode];
185 }
186 
187 /*
188  * Return the instruction index type for the specified opcode.
189  */
dexGetIndexTypeFromOpcode(Opcode opcode)190 DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode)
191 {
192     assert((u4) opcode < kNumPackedOpcodes);
193     return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode];
194 }
195 
196 /*
197  * Decode the instruction pointed to by "insns".
198  */
199 void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
200 
201 #endif  // LIBDEX_INSTRUTILS_H_
202