blob: 632a787618f5b69ef9cbb8b0f34d2b12de83f0db [file] [log] [blame]
Mathieu Chartier69147f12017-11-06 20:02:24 -08001/*
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 Sehr334b9d72018-02-12 18:27:56 -080017#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
18#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
Mathieu Chartier69147f12017-11-06 20:02:24 -080019
David Sehr0225f8e2018-01-31 08:52:24 +000020#include "code_item_accessors.h"
Mathieu Chartier69147f12017-11-06 20:02:24 -080021
Andreas Gampe7458a7a2019-01-02 10:32:11 -080022#include "base/iteration_range.h"
David Sehr9e734c72018-01-04 17:56:19 -080023#include "compact_dex_file.h"
Mathieu Chartier3da1d0f2017-11-06 20:02:24 -080024#include "dex_file-inl.h"
Mathieu Chartier69147f12017-11-06 20:02:24 -080025#include "standard_dex_file.h"
26
David Sehr0225f8e2018-01-31 08:52:24 +000027// The no ART version is used by binaries that don't include the whole runtime.
Mathieu Chartier69147f12017-11-06 20:02:24 -080028namespace art {
29
David Sehr0225f8e2018-01-31 08:52:24 +000030inline 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 Chartier69147f12017-11-06 20:02:24 -080035
Andreas Gampe7458a7a2019-01-02 10:32:11 -080036template <>
37inline void CodeItemInstructionAccessor::Init<CompactDexFile::CodeItem>(
38 const CompactDexFile::CodeItem& code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +000039 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 Chartier69147f12017-11-06 20:02:24 -080048
Andreas Gampe7458a7a2019-01-02 10:32:11 -080049template <>
50inline void CodeItemInstructionAccessor::Init<StandardDexFile::CodeItem>(
51 const StandardDexFile::CodeItem& code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +000052 Init(code_item.insns_size_in_code_units_, code_item.insns_);
53}
54
55inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -080056 const dex::CodeItem* code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +000057 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
68inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
69 const DexFile& dex_file,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -080070 const dex::CodeItem* code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +000071 Init(dex_file, code_item);
72}
73
74inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
75 return DexInstructionIterator(insns_, 0u);
76}
77
78inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
79 return DexInstructionIterator(insns_, insns_size_in_code_units_);
80}
81
82inline 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 Gampe7458a7a2019-01-02 10:32:11 -080090template <>
91inline void CodeItemDataAccessor::Init<CompactDexFile::CodeItem>(
92 const CompactDexFile::CodeItem& code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +000093 uint32_t insns_size_in_code_units;
94 code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ false>(&insns_size_in_code_units,
95 &registers_size_,
96 &ins_size_,
97 &outs_size_,
98 &tries_size_);
99 CodeItemInstructionAccessor::Init(insns_size_in_code_units, code_item.insns_);
100}
101
Andreas Gampe7458a7a2019-01-02 10:32:11 -0800102template <>
103inline void CodeItemDataAccessor::Init<StandardDexFile::CodeItem>(
104 const StandardDexFile::CodeItem& code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +0000105 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
112inline void CodeItemDataAccessor::Init(const DexFile& dex_file,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800113 const dex::CodeItem* code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +0000114 if (code_item != nullptr) {
115 if (dex_file.IsCompactDexFile()) {
Andreas Gampe7458a7a2019-01-02 10:32:11 -0800116 Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
David Sehr0225f8e2018-01-31 08:52:24 +0000117 } else {
118 DCHECK(dex_file.IsStandardDexFile());
Andreas Gampe7458a7a2019-01-02 10:32:11 -0800119 Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
David Sehr0225f8e2018-01-31 08:52:24 +0000120 }
121 }
122}
123
124inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile& dex_file,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800125 const dex::CodeItem* code_item) {
David Sehr0225f8e2018-01-31 08:52:24 +0000126 Init(dex_file, code_item);
127}
128
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800129inline IterationRange<const dex::TryItem*> CodeItemDataAccessor::TryItems() const {
130 const dex::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
David Sehr0225f8e2018-01-31 08:52:24 +0000131 return {
132 try_items,
133 try_items + TriesSize() };
134}
135
136inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const {
137 return DexFile::GetCatchHandlerData(end(), TriesSize(), offset);
138}
139
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800140inline const dex::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const {
141 IterationRange<const dex::TryItem*> try_items(TryItems());
David Sehr0225f8e2018-01-31 08:52:24 +0000142 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
148inline 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 Gampe7458a7a2019-01-02 10:32:11 -0800169template <>
170inline 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
178template <>
179inline 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 Sehr0225f8e2018-01-31 08:52:24 +0000186inline void CodeItemDebugInfoAccessor::Init(const DexFile& dex_file,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800187 const dex::CodeItem* code_item,
David Sehr0225f8e2018-01-31 08:52:24 +0000188 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 Gampe7458a7a2019-01-02 10:32:11 -0800197 Init(down_cast<const StandardDexFile::CodeItem&>(*code_item), dex_method_index);
David Sehr0225f8e2018-01-31 08:52:24 +0000198 }
199}
200
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700201template<typename NewLocalVisitor>
202inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(
203 bool is_static,
204 uint32_t method_idx,
205 const NewLocalVisitor& new_local) const {
David Sehr0225f8e2018-01-31 08:52:24 +0000206 return dex_file_->DecodeDebugLocalInfo(RegistersSize(),
207 InsSize(),
208 InsnsSizeInCodeUnits(),
209 DebugInfoOffset(),
210 is_static,
211 method_idx,
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700212 new_local);
David Sehr0225f8e2018-01-31 08:52:24 +0000213}
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800214
Mathieu Chartier3e2e1232018-09-11 12:35:30 -0700215template <typename Visitor>
216inline 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
221inline 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
235template <typename Visitor>
236inline 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 Chartier69147f12017-11-06 20:02:24 -0800245} // namespace art
246
David Sehr334b9d72018-02-12 18:27:56 -0800247#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_