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