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 "compact_dex_file.h"
23 #include "dex_file-inl.h"
24 #include "standard_dex_file.h"
25 
26 // The no ART version is used by binaries that don't include the whole runtime.
27 namespace art {
28 
Init(uint32_t insns_size_in_code_units,const uint16_t * insns)29 inline void CodeItemInstructionAccessor::Init(uint32_t insns_size_in_code_units,
30                                               const uint16_t* insns) {
31   insns_size_in_code_units_ = insns_size_in_code_units;
32   insns_ = insns;
33 }
34 
Init(const CompactDexFile::CodeItem & code_item)35 inline void CodeItemInstructionAccessor::Init(const CompactDexFile::CodeItem& code_item) {
36   uint32_t insns_size_in_code_units;
37   code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ true>(
38       &insns_size_in_code_units,
39       /*registers_size*/ nullptr,
40       /*ins_size*/ nullptr,
41       /*outs_size*/ nullptr,
42       /*tries_size*/ nullptr);
43   Init(insns_size_in_code_units, code_item.insns_);
44 }
45 
Init(const StandardDexFile::CodeItem & code_item)46 inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& code_item) {
47   Init(code_item.insns_size_in_code_units_, code_item.insns_);
48 }
49 
Init(const DexFile & dex_file,const DexFile::CodeItem * code_item)50 inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file,
51                                               const DexFile::CodeItem* code_item) {
52   if (code_item != nullptr) {
53     DCHECK(dex_file.IsInDataSection(code_item));
54     if (dex_file.IsCompactDexFile()) {
55       Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
56     } else {
57       DCHECK(dex_file.IsStandardDexFile());
58       Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
59     }
60   }
61 }
62 
CodeItemInstructionAccessor(const DexFile & dex_file,const DexFile::CodeItem * code_item)63 inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
64     const DexFile& dex_file,
65     const DexFile::CodeItem* code_item) {
66   Init(dex_file, code_item);
67 }
68 
begin()69 inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
70   return DexInstructionIterator(insns_, 0u);
71 }
72 
end()73 inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
74   return DexInstructionIterator(insns_, insns_size_in_code_units_);
75 }
76 
InstructionsFrom(uint32_t start_dex_pc)77 inline IterationRange<DexInstructionIterator> CodeItemInstructionAccessor::InstructionsFrom(
78     uint32_t start_dex_pc) const {
79   DCHECK_LT(start_dex_pc, InsnsSizeInCodeUnits());
80   return {
81       DexInstructionIterator(insns_, start_dex_pc),
82       DexInstructionIterator(insns_, insns_size_in_code_units_) };
83 }
84 
Init(const CompactDexFile::CodeItem & code_item)85 inline void CodeItemDataAccessor::Init(const CompactDexFile::CodeItem& code_item) {
86   uint32_t insns_size_in_code_units;
87   code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ false>(&insns_size_in_code_units,
88                                                                 &registers_size_,
89                                                                 &ins_size_,
90                                                                 &outs_size_,
91                                                                 &tries_size_);
92   CodeItemInstructionAccessor::Init(insns_size_in_code_units, code_item.insns_);
93 }
94 
Init(const StandardDexFile::CodeItem & code_item)95 inline void CodeItemDataAccessor::Init(const StandardDexFile::CodeItem& code_item) {
96   CodeItemInstructionAccessor::Init(code_item);
97   registers_size_ = code_item.registers_size_;
98   ins_size_ = code_item.ins_size_;
99   outs_size_ = code_item.outs_size_;
100   tries_size_ = code_item.tries_size_;
101 }
102 
Init(const DexFile & dex_file,const DexFile::CodeItem * code_item)103 inline void CodeItemDataAccessor::Init(const DexFile& dex_file,
104                                        const DexFile::CodeItem* code_item) {
105   if (code_item != nullptr) {
106     if (dex_file.IsCompactDexFile()) {
107       CodeItemDataAccessor::Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
108     } else {
109       DCHECK(dex_file.IsStandardDexFile());
110       CodeItemDataAccessor::Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
111     }
112   }
113 }
114 
CodeItemDataAccessor(const DexFile & dex_file,const DexFile::CodeItem * code_item)115 inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile& dex_file,
116                                                   const DexFile::CodeItem* code_item) {
117   Init(dex_file, code_item);
118 }
119 
TryItems()120 inline IterationRange<const DexFile::TryItem*> CodeItemDataAccessor::TryItems() const {
121   const DexFile::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
122   return {
123     try_items,
124     try_items + TriesSize() };
125 }
126 
GetCatchHandlerData(size_t offset)127 inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const {
128   return DexFile::GetCatchHandlerData(end(), TriesSize(), offset);
129 }
130 
FindTryItem(uint32_t try_dex_pc)131 inline const DexFile::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const {
132   IterationRange<const DexFile::TryItem*> try_items(TryItems());
133   int32_t index = DexFile::FindTryItem(try_items.begin(),
134                                        try_items.end() - try_items.begin(),
135                                        try_dex_pc);
136   return index != -1 ? &try_items.begin()[index] : nullptr;
137 }
138 
CodeItemDataEnd()139 inline const void* CodeItemDataAccessor::CodeItemDataEnd() const {
140   const uint8_t* handler_data = GetCatchHandlerData();
141 
142   if (TriesSize() == 0 || handler_data == nullptr) {
143     return &end().Inst();
144   }
145   // Get the start of the handler data.
146   const uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data);
147   // Manually read each handler.
148   for (uint32_t i = 0; i < handlers_size; ++i) {
149     int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2;
150     if (uleb128_count <= 0) {
151       uleb128_count = -uleb128_count + 1;
152     }
153     for (int32_t j = 0; j < uleb128_count; ++j) {
154       DecodeUnsignedLeb128(&handler_data);
155     }
156   }
157   return reinterpret_cast<const void*>(handler_data);
158 }
159 
Init(const DexFile & dex_file,const DexFile::CodeItem * code_item,uint32_t dex_method_index)160 inline void CodeItemDebugInfoAccessor::Init(const DexFile& dex_file,
161                                             const DexFile::CodeItem* code_item,
162                                             uint32_t dex_method_index) {
163   if (code_item == nullptr) {
164     return;
165   }
166   dex_file_ = &dex_file;
167   if (dex_file.IsCompactDexFile()) {
168     Init(down_cast<const CompactDexFile::CodeItem&>(*code_item), dex_method_index);
169   } else {
170     DCHECK(dex_file.IsStandardDexFile());
171     Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
172   }
173 }
174 
Init(const CompactDexFile::CodeItem & code_item,uint32_t dex_method_index)175 inline void CodeItemDebugInfoAccessor::Init(const CompactDexFile::CodeItem& code_item,
176                                             uint32_t dex_method_index) {
177   debug_info_offset_ = down_cast<const CompactDexFile*>(dex_file_)->GetDebugInfoOffset(
178       dex_method_index);
179   CodeItemDataAccessor::Init(code_item);
180 }
181 
Init(const StandardDexFile::CodeItem & code_item)182 inline void CodeItemDebugInfoAccessor::Init(const StandardDexFile::CodeItem& code_item) {
183   debug_info_offset_ = code_item.debug_info_off_;
184   CodeItemDataAccessor::Init(code_item);
185 }
186 
187 template<typename NewLocalCallback>
DecodeDebugLocalInfo(bool is_static,uint32_t method_idx,NewLocalCallback new_local,void * context)188 inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(bool is_static,
189                                                             uint32_t method_idx,
190                                                             NewLocalCallback new_local,
191                                                             void* context) const {
192   return dex_file_->DecodeDebugLocalInfo(RegistersSize(),
193                                          InsSize(),
194                                          InsnsSizeInCodeUnits(),
195                                          DebugInfoOffset(),
196                                          is_static,
197                                          method_idx,
198                                          new_local,
199                                          context);
200 }
201 
202 }  // namespace art
203 
204 #endif  // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
205