1 /* 2 * Copyright (C) 2017 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_CODE_ITEM_ACCESSORS_INL_H_ 18 #define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ 19 20 #include "code_item_accessors.h" 21 22 #include "base/iteration_range.h" 23 #include "compact_dex_file.h" 24 #include "dex_file-inl.h" 25 #include "standard_dex_file.h" 26 27 // The no ART version is used by binaries that don't include the whole runtime. 28 namespace art { 29 30 inline void CodeItemInstructionAccessor::Init(uint32_t insns_size_in_code_units, 31 const uint16_t* insns) { 32 insns_size_in_code_units_ = insns_size_in_code_units; 33 insns_ = insns; 34 } 35 36 template <> 37 inline void CodeItemInstructionAccessor::Init<CompactDexFile::CodeItem>( 38 const CompactDexFile::CodeItem& code_item) { 39 uint32_t insns_size_in_code_units; 40 code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ true>( 41 &insns_size_in_code_units, 42 /*registers_size*/ nullptr, 43 /*ins_size*/ nullptr, 44 /*outs_size*/ nullptr, 45 /*tries_size*/ nullptr); 46 Init(insns_size_in_code_units, code_item.insns_); 47 } 48 49 template <> 50 inline void CodeItemInstructionAccessor::Init<StandardDexFile::CodeItem>( 51 const StandardDexFile::CodeItem& code_item) { 52 Init(code_item.insns_size_in_code_units_, code_item.insns_); 53 } 54 55 inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file, 56 const dex::CodeItem* code_item) { 57 if (code_item != nullptr) { 58 DCHECK(dex_file.IsInDataSection(code_item)); 59 if (dex_file.IsCompactDexFile()) { 60 Init(down_cast<const CompactDexFile::CodeItem&>(*code_item)); 61 } else { 62 DCHECK(dex_file.IsStandardDexFile()); 63 Init(down_cast<const StandardDexFile::CodeItem&>(*code_item)); 64 } 65 } 66 } 67 68 inline CodeItemInstructionAccessor::CodeItemInstructionAccessor( 69 const DexFile& dex_file, 70 const dex::CodeItem* code_item) { 71 Init(dex_file, code_item); 72 } 73 74 inline DexInstructionIterator CodeItemInstructionAccessor::begin() const { 75 return DexInstructionIterator(insns_, 0u); 76 } 77 78 inline DexInstructionIterator CodeItemInstructionAccessor::end() const { 79 return DexInstructionIterator(insns_, insns_size_in_code_units_); 80 } 81 82 inline IterationRange<DexInstructionIterator> CodeItemInstructionAccessor::InstructionsFrom( 83 uint32_t start_dex_pc) const { 84 DCHECK_LT(start_dex_pc, InsnsSizeInCodeUnits()); 85 return { 86 DexInstructionIterator(insns_, start_dex_pc), 87 DexInstructionIterator(insns_, insns_size_in_code_units_) }; 88 } 89 90 template <> 91 inline void CodeItemDataAccessor::Init<CompactDexFile::CodeItem>( 92 const CompactDexFile::CodeItem& code_item) { 93 uint32_t insns_size_in_code_units; 94 code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ false>(&insns_size_in_code_units, 95 ®isters_size_, 96 &ins_size_, 97 &outs_size_, 98 &tries_size_); 99 CodeItemInstructionAccessor::Init(insns_size_in_code_units, code_item.insns_); 100 } 101 102 template <> 103 inline void CodeItemDataAccessor::Init<StandardDexFile::CodeItem>( 104 const StandardDexFile::CodeItem& code_item) { 105 CodeItemInstructionAccessor::Init(code_item); 106 registers_size_ = code_item.registers_size_; 107 ins_size_ = code_item.ins_size_; 108 outs_size_ = code_item.outs_size_; 109 tries_size_ = code_item.tries_size_; 110 } 111 112 inline void CodeItemDataAccessor::Init(const DexFile& dex_file, 113 const dex::CodeItem* code_item) { 114 if (code_item != nullptr) { 115 if (dex_file.IsCompactDexFile()) { 116 Init(down_cast<const CompactDexFile::CodeItem&>(*code_item)); 117 } else { 118 DCHECK(dex_file.IsStandardDexFile()); 119 Init(down_cast<const StandardDexFile::CodeItem&>(*code_item)); 120 } 121 } 122 } 123 124 inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile& dex_file, 125 const dex::CodeItem* code_item) { 126 Init(dex_file, code_item); 127 } 128 129 inline IterationRange<const dex::TryItem*> CodeItemDataAccessor::TryItems() const { 130 const dex::TryItem* try_items = DexFile::GetTryItems(end(), 0u); 131 return { 132 try_items, 133 try_items + TriesSize() }; 134 } 135 136 inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const { 137 return DexFile::GetCatchHandlerData(end(), TriesSize(), offset); 138 } 139 140 inline const dex::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const { 141 IterationRange<const dex::TryItem*> try_items(TryItems()); 142 int32_t index = DexFile::FindTryItem(try_items.begin(), 143 try_items.end() - try_items.begin(), 144 try_dex_pc); 145 return index != -1 ? &try_items.begin()[index] : nullptr; 146 } 147 148 inline const void* CodeItemDataAccessor::CodeItemDataEnd() const { 149 const uint8_t* handler_data = GetCatchHandlerData(); 150 151 if (TriesSize() == 0 || handler_data == nullptr) { 152 return &end().Inst(); 153 } 154 // Get the start of the handler data. 155 const uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data); 156 // Manually read each handler. 157 for (uint32_t i = 0; i < handlers_size; ++i) { 158 int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2; 159 if (uleb128_count <= 0) { 160 uleb128_count = -uleb128_count + 1; 161 } 162 for (int32_t j = 0; j < uleb128_count; ++j) { 163 DecodeUnsignedLeb128(&handler_data); 164 } 165 } 166 return reinterpret_cast<const void*>(handler_data); 167 } 168 169 template <> 170 inline void CodeItemDebugInfoAccessor::Init<CompactDexFile::CodeItem>( 171 const CompactDexFile::CodeItem& code_item, 172 uint32_t dex_method_index) { 173 debug_info_offset_ = down_cast<const CompactDexFile*>(dex_file_)->GetDebugInfoOffset( 174 dex_method_index); 175 CodeItemDataAccessor::Init(code_item); 176 } 177 178 template <> 179 inline void CodeItemDebugInfoAccessor::Init<StandardDexFile::CodeItem>( 180 const StandardDexFile::CodeItem& code_item, 181 uint32_t dex_method_index ATTRIBUTE_UNUSED) { 182 debug_info_offset_ = code_item.debug_info_off_; 183 CodeItemDataAccessor::Init(code_item); 184 } 185 186 inline void CodeItemDebugInfoAccessor::Init(const DexFile& dex_file, 187 const dex::CodeItem* code_item, 188 uint32_t dex_method_index) { 189 if (code_item == nullptr) { 190 return; 191 } 192 dex_file_ = &dex_file; 193 if (dex_file.IsCompactDexFile()) { 194 Init(down_cast<const CompactDexFile::CodeItem&>(*code_item), dex_method_index); 195 } else { 196 DCHECK(dex_file.IsStandardDexFile()); 197 Init(down_cast<const StandardDexFile::CodeItem&>(*code_item), dex_method_index); 198 } 199 } 200 201 template<typename NewLocalVisitor> 202 inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo( 203 bool is_static, 204 uint32_t method_idx, 205 const NewLocalVisitor& new_local) const { 206 return dex_file_->DecodeDebugLocalInfo(RegistersSize(), 207 InsSize(), 208 InsnsSizeInCodeUnits(), 209 DebugInfoOffset(), 210 is_static, 211 method_idx, 212 new_local); 213 } 214 215 template <typename Visitor> 216 inline uint32_t CodeItemDebugInfoAccessor::VisitParameterNames(const Visitor& visitor) const { 217 const uint8_t* stream = dex_file_->GetDebugInfoStream(DebugInfoOffset()); 218 return (stream != nullptr) ? DexFile::DecodeDebugInfoParameterNames(&stream, visitor) : 0u; 219 } 220 221 inline bool CodeItemDebugInfoAccessor::GetLineNumForPc(const uint32_t address, 222 uint32_t* line_num) const { 223 return DecodeDebugPositionInfo([&](const DexFile::PositionInfo& entry) { 224 // We know that this callback will be called in ascending address order, so keep going until we 225 // find a match or we've just gone past it. 226 if (entry.address_ > address) { 227 // The line number from the previous positions callback will be the final result. 228 return true; 229 } 230 *line_num = entry.line_; 231 return entry.address_ == address; 232 }); 233 } 234 235 template <typename Visitor> 236 inline bool CodeItemDebugInfoAccessor::DecodeDebugPositionInfo(const Visitor& visitor) const { 237 return dex_file_->DecodeDebugPositionInfo( 238 dex_file_->GetDebugInfoStream(DebugInfoOffset()), 239 [this](uint32_t idx) { 240 return dex_file_->StringDataByIdx(dex::StringIndex(idx)); 241 }, 242 visitor); 243 } 244 245 } // namespace art 246 247 #endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ 248