Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 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 | |
David Sehr | 334b9d7 | 2018-02-12 18:27:56 -0800 | [diff] [blame] | 17 | #ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ |
| 18 | #define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 19 | |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 20 | #include "code_item_accessors.h" |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 21 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 22 | #include "base/iteration_range.h" |
David Sehr | 9e734c7 | 2018-01-04 17:56:19 -0800 | [diff] [blame] | 23 | #include "compact_dex_file.h" |
Mathieu Chartier | 3da1d0f | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 24 | #include "dex_file-inl.h" |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 25 | #include "standard_dex_file.h" |
| 26 | |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 27 | // The no ART version is used by binaries that don't include the whole runtime. |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 28 | namespace art { |
| 29 | |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | } |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 35 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 36 | template <> |
| 37 | inline void CodeItemInstructionAccessor::Init<CompactDexFile::CodeItem>( |
| 38 | const CompactDexFile::CodeItem& code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | } |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 48 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 49 | template <> |
| 50 | inline void CodeItemInstructionAccessor::Init<StandardDexFile::CodeItem>( |
| 51 | const StandardDexFile::CodeItem& code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 52 | Init(code_item.insns_size_in_code_units_, code_item.insns_); |
| 53 | } |
| 54 | |
| 55 | inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file, |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 56 | const dex::CodeItem* code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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, |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 70 | const dex::CodeItem* code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 90 | template <> |
| 91 | inline void CodeItemDataAccessor::Init<CompactDexFile::CodeItem>( |
| 92 | const CompactDexFile::CodeItem& code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 102 | template <> |
| 103 | inline void CodeItemDataAccessor::Init<StandardDexFile::CodeItem>( |
| 104 | const StandardDexFile::CodeItem& code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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, |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 113 | const dex::CodeItem* code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 114 | if (code_item != nullptr) { |
| 115 | if (dex_file.IsCompactDexFile()) { |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 116 | Init(down_cast<const CompactDexFile::CodeItem&>(*code_item)); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 117 | } else { |
| 118 | DCHECK(dex_file.IsStandardDexFile()); |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 119 | Init(down_cast<const StandardDexFile::CodeItem&>(*code_item)); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile& dex_file, |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 125 | const dex::CodeItem* code_item) { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 126 | Init(dex_file, code_item); |
| 127 | } |
| 128 | |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 129 | inline IterationRange<const dex::TryItem*> CodeItemDataAccessor::TryItems() const { |
| 130 | const dex::TryItem* try_items = DexFile::GetTryItems(end(), 0u); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 140 | inline const dex::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const { |
| 141 | IterationRange<const dex::TryItem*> try_items(TryItems()); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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 | |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 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 | |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 186 | inline void CodeItemDebugInfoAccessor::Init(const DexFile& dex_file, |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 187 | const dex::CodeItem* code_item, |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 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()); |
Andreas Gampe | 7458a7a | 2019-01-02 10:32:11 -0800 | [diff] [blame] | 197 | Init(down_cast<const StandardDexFile::CodeItem&>(*code_item), dex_method_index); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 198 | } |
| 199 | } |
| 200 | |
Mathieu Chartier | e5afbf3 | 2018-09-12 17:51:54 -0700 | [diff] [blame] | 201 | template<typename NewLocalVisitor> |
| 202 | inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo( |
| 203 | bool is_static, |
| 204 | uint32_t method_idx, |
| 205 | const NewLocalVisitor& new_local) const { |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 206 | return dex_file_->DecodeDebugLocalInfo(RegistersSize(), |
| 207 | InsSize(), |
| 208 | InsnsSizeInCodeUnits(), |
| 209 | DebugInfoOffset(), |
| 210 | is_static, |
| 211 | method_idx, |
Mathieu Chartier | e5afbf3 | 2018-09-12 17:51:54 -0700 | [diff] [blame] | 212 | new_local); |
David Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 213 | } |
Mathieu Chartier | 31f4c9f | 2017-12-08 15:46:11 -0800 | [diff] [blame] | 214 | |
Mathieu Chartier | 3e2e123 | 2018-09-11 12:35:30 -0700 | [diff] [blame] | 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 | |
Mathieu Chartier | 69147f1 | 2017-11-06 20:02:24 -0800 | [diff] [blame] | 245 | } // namespace art |
| 246 | |
David Sehr | 334b9d7 | 2018-02-12 18:27:56 -0800 | [diff] [blame] | 247 | #endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ |