1 /* 2 * Copyright (C) 2014 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 #ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ 18 #define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ 19 20 #include "dex_instruction.h" 21 22 namespace art { 23 24 // Dex invoke type corresponds to the ordering of INVOKE instructions; 25 // this order is the same for range and non-range invokes. 26 enum DexInvokeType : uint8_t { 27 kDexInvokeVirtual = 0, // invoke-virtual, invoke-virtual-range 28 kDexInvokeSuper, // invoke-super, invoke-super-range 29 kDexInvokeDirect, // invoke-direct, invoke-direct-range 30 kDexInvokeStatic, // invoke-static, invoke-static-range 31 kDexInvokeInterface, // invoke-interface, invoke-interface-range 32 kDexInvokeTypeCount 33 }; 34 35 // Dex instruction memory access types correspond to the ordering of GET/PUT instructions; 36 // this order is the same for IGET, IPUT, SGET, SPUT, AGET and APUT. 37 enum DexMemAccessType : uint8_t { 38 kDexMemAccessWord = 0, // op 0; int or float, the actual type is not encoded. 39 kDexMemAccessWide, // op_WIDE 1; long or double, the actual type is not encoded. 40 kDexMemAccessObject, // op_OBJECT 2; the actual reference type is not encoded. 41 kDexMemAccessBoolean, // op_BOOLEAN 3 42 kDexMemAccessByte, // op_BYTE 4 43 kDexMemAccessChar, // op_CHAR 5 44 kDexMemAccessShort, // op_SHORT 6 45 kDexMemAccessTypeCount 46 }; 47 48 std::ostream& operator<<(std::ostream& os, DexMemAccessType type); 49 50 // NOTE: The following functions disregard quickened instructions. 51 52 // By "direct" const we mean to exclude const-string and const-class 53 // which load data from somewhere else, i.e. indirectly. IsInstructionDirectConst(Instruction::Code opcode)54 constexpr bool IsInstructionDirectConst(Instruction::Code opcode) { 55 return Instruction::CONST_4 <= opcode && opcode <= Instruction::CONST_WIDE_HIGH16; 56 } 57 IsInstructionConstWide(Instruction::Code opcode)58 constexpr bool IsInstructionConstWide(Instruction::Code opcode) { 59 return Instruction::CONST_WIDE_16 <= opcode && opcode <= Instruction::CONST_WIDE_HIGH16; 60 } 61 IsInstructionReturn(Instruction::Code opcode)62 constexpr bool IsInstructionReturn(Instruction::Code opcode) { 63 return Instruction::RETURN_VOID <= opcode && opcode <= Instruction::RETURN_OBJECT; 64 } 65 IsInstructionInvoke(Instruction::Code opcode)66 constexpr bool IsInstructionInvoke(Instruction::Code opcode) { 67 return Instruction::INVOKE_VIRTUAL <= opcode && opcode <= Instruction::INVOKE_INTERFACE_RANGE && 68 opcode != Instruction::UNUSED_73; 69 } 70 IsInstructionInvokeStatic(Instruction::Code opcode)71 constexpr bool IsInstructionInvokeStatic(Instruction::Code opcode) { 72 return opcode == Instruction::INVOKE_STATIC || opcode == Instruction::INVOKE_STATIC_RANGE; 73 } 74 IsInstructionGoto(Instruction::Code opcode)75 constexpr bool IsInstructionGoto(Instruction::Code opcode) { 76 return Instruction::GOTO <= opcode && opcode <= Instruction::GOTO_32; 77 } 78 IsInstructionIfCc(Instruction::Code opcode)79 constexpr bool IsInstructionIfCc(Instruction::Code opcode) { 80 return Instruction::IF_EQ <= opcode && opcode <= Instruction::IF_LE; 81 } 82 IsInstructionIfCcZ(Instruction::Code opcode)83 constexpr bool IsInstructionIfCcZ(Instruction::Code opcode) { 84 return Instruction::IF_EQZ <= opcode && opcode <= Instruction::IF_LEZ; 85 } 86 IsInstructionIGet(Instruction::Code code)87 constexpr bool IsInstructionIGet(Instruction::Code code) { 88 return Instruction::IGET <= code && code <= Instruction::IGET_SHORT; 89 } 90 IsInstructionIPut(Instruction::Code code)91 constexpr bool IsInstructionIPut(Instruction::Code code) { 92 return Instruction::IPUT <= code && code <= Instruction::IPUT_SHORT; 93 } 94 IsInstructionSGet(Instruction::Code code)95 constexpr bool IsInstructionSGet(Instruction::Code code) { 96 return Instruction::SGET <= code && code <= Instruction::SGET_SHORT; 97 } 98 IsInstructionSPut(Instruction::Code code)99 constexpr bool IsInstructionSPut(Instruction::Code code) { 100 return Instruction::SPUT <= code && code <= Instruction::SPUT_SHORT; 101 } 102 IsInstructionAGet(Instruction::Code code)103 constexpr bool IsInstructionAGet(Instruction::Code code) { 104 return Instruction::AGET <= code && code <= Instruction::AGET_SHORT; 105 } 106 IsInstructionAPut(Instruction::Code code)107 constexpr bool IsInstructionAPut(Instruction::Code code) { 108 return Instruction::APUT <= code && code <= Instruction::APUT_SHORT; 109 } 110 IsInstructionIGetOrIPut(Instruction::Code code)111 constexpr bool IsInstructionIGetOrIPut(Instruction::Code code) { 112 return Instruction::IGET <= code && code <= Instruction::IPUT_SHORT; 113 } 114 IsInstructionSGetOrSPut(Instruction::Code code)115 constexpr bool IsInstructionSGetOrSPut(Instruction::Code code) { 116 return Instruction::SGET <= code && code <= Instruction::SPUT_SHORT; 117 } 118 IsInstructionAGetOrAPut(Instruction::Code code)119 constexpr bool IsInstructionAGetOrAPut(Instruction::Code code) { 120 return Instruction::AGET <= code && code <= Instruction::APUT_SHORT; 121 } 122 IsInstructionBinOp2Addr(Instruction::Code code)123 constexpr bool IsInstructionBinOp2Addr(Instruction::Code code) { 124 return Instruction::ADD_INT_2ADDR <= code && code <= Instruction::REM_DOUBLE_2ADDR; 125 } 126 IsInvokeInstructionRange(Instruction::Code opcode)127 constexpr bool IsInvokeInstructionRange(Instruction::Code opcode) { 128 DCHECK(IsInstructionInvoke(opcode)); 129 return opcode >= Instruction::INVOKE_VIRTUAL_RANGE; 130 } 131 InvokeInstructionType(Instruction::Code opcode)132 constexpr DexInvokeType InvokeInstructionType(Instruction::Code opcode) { 133 DCHECK(IsInstructionInvoke(opcode)); 134 return static_cast<DexInvokeType>(IsInvokeInstructionRange(opcode) 135 ? (opcode - Instruction::INVOKE_VIRTUAL_RANGE) 136 : (opcode - Instruction::INVOKE_VIRTUAL)); 137 } 138 IGetMemAccessType(Instruction::Code code)139 constexpr DexMemAccessType IGetMemAccessType(Instruction::Code code) { 140 DCHECK(IsInstructionIGet(code)); 141 return static_cast<DexMemAccessType>(code - Instruction::IGET); 142 } 143 IPutMemAccessType(Instruction::Code code)144 constexpr DexMemAccessType IPutMemAccessType(Instruction::Code code) { 145 DCHECK(IsInstructionIPut(code)); 146 return static_cast<DexMemAccessType>(code - Instruction::IPUT); 147 } 148 SGetMemAccessType(Instruction::Code code)149 constexpr DexMemAccessType SGetMemAccessType(Instruction::Code code) { 150 DCHECK(IsInstructionSGet(code)); 151 return static_cast<DexMemAccessType>(code - Instruction::SGET); 152 } 153 SPutMemAccessType(Instruction::Code code)154 constexpr DexMemAccessType SPutMemAccessType(Instruction::Code code) { 155 DCHECK(IsInstructionSPut(code)); 156 return static_cast<DexMemAccessType>(code - Instruction::SPUT); 157 } 158 AGetMemAccessType(Instruction::Code code)159 constexpr DexMemAccessType AGetMemAccessType(Instruction::Code code) { 160 DCHECK(IsInstructionAGet(code)); 161 return static_cast<DexMemAccessType>(code - Instruction::AGET); 162 } 163 APutMemAccessType(Instruction::Code code)164 constexpr DexMemAccessType APutMemAccessType(Instruction::Code code) { 165 DCHECK(IsInstructionAPut(code)); 166 return static_cast<DexMemAccessType>(code - Instruction::APUT); 167 } 168 IGetOrIPutMemAccessType(Instruction::Code code)169 constexpr DexMemAccessType IGetOrIPutMemAccessType(Instruction::Code code) { 170 DCHECK(IsInstructionIGetOrIPut(code)); 171 return (code >= Instruction::IPUT) ? IPutMemAccessType(code) : IGetMemAccessType(code); 172 } 173 SGetOrSPutMemAccessType(Instruction::Code code)174 constexpr DexMemAccessType SGetOrSPutMemAccessType(Instruction::Code code) { 175 DCHECK(IsInstructionSGetOrSPut(code)); 176 return (code >= Instruction::SPUT) ? SPutMemAccessType(code) : SGetMemAccessType(code); 177 } 178 AGetOrAPutMemAccessType(Instruction::Code code)179 constexpr DexMemAccessType AGetOrAPutMemAccessType(Instruction::Code code) { 180 DCHECK(IsInstructionAGetOrAPut(code)); 181 return (code >= Instruction::APUT) ? APutMemAccessType(code) : AGetMemAccessType(code); 182 } 183 184 } // namespace art 185 186 #endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ 187