InstrUtils.h revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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 */
37typedef unsigned char InstructionFormat;
38enum 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 */
75typedef 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 */
87typedef signed char InstructionWidth;
88
89/*
90 * Instruction flags, used by the verifier to determine where control
91 * can flow to next.
92 */
93typedef unsigned char InstructionFlags;
94enum 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 */
107InstructionWidth* dexCreateInstrWidthTable(void);
108
109/*
110 * Returns the width of the specified instruction, or 0 if not defined.
111 * Optimized instructions use negative values.
112 */
113DEX_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 */
122DEX_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 */
138int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns);
139
140
141/*
142 * Allocate and populate a 256-element array with instruction flags.
143 */
144InstructionFlags* dexCreateInstrFlagsTable(void);
145
146/*
147 * Returns the flags for the specified opcode.
148 */
149DEX_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 */
159InstructionFormat* dexCreateInstrFormatTable(void);
160
161/*
162 * Return the instruction format for the specified opcode.
163 */
164DEX_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 */
174void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
175    DecodedInstruction* pDec);
176
177#endif /*_LIBDEX_INSTRUTILS*/
178