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 #include "dex_file_exception_helpers.h"
18
19 #include "code_item_accessors-inl.h"
20 #include "dex_file_structs.h"
21
22 namespace art {
23
CatchHandlerIterator(const CodeItemDataAccessor & accessor,uint32_t address)24 CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor, uint32_t address) {
25 handler_.address_ = -1;
26 int32_t offset = -1;
27
28 // Short-circuit the overwhelmingly common cases.
29 switch (accessor.TriesSize()) {
30 case 0:
31 break;
32 case 1: {
33 const dex::TryItem* tries = accessor.TryItems().begin();
34 uint32_t start = tries->start_addr_;
35 if (address >= start) {
36 uint32_t end = start + tries->insn_count_;
37 if (address < end) {
38 offset = tries->handler_off_;
39 }
40 }
41 break;
42 }
43 default: {
44 const dex::TryItem* try_item = accessor.FindTryItem(address);
45 offset = try_item != nullptr ? try_item->handler_off_ : -1;
46 break;
47 }
48 }
49 Init(accessor, offset);
50 }
51
CatchHandlerIterator(const CodeItemDataAccessor & accessor,const dex::TryItem & try_item)52 CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor,
53 const dex::TryItem& try_item) {
54 handler_.address_ = -1;
55 Init(accessor, try_item.handler_off_);
56 }
57
Init(const CodeItemDataAccessor & accessor,int32_t offset)58 void CatchHandlerIterator::Init(const CodeItemDataAccessor& accessor, int32_t offset) {
59 if (offset >= 0) {
60 Init(accessor.GetCatchHandlerData(offset));
61 } else {
62 // Not found, initialize as empty
63 current_data_ = nullptr;
64 remaining_count_ = -1;
65 catch_all_ = false;
66 DCHECK(!HasNext());
67 }
68 }
69
Init(const uint8_t * handler_data)70 void CatchHandlerIterator::Init(const uint8_t* handler_data) {
71 current_data_ = handler_data;
72 remaining_count_ = DecodeSignedLeb128(¤t_data_);
73
74 // If remaining_count_ is non-positive, then it is the negative of
75 // the number of catch types, and the catches are followed by a
76 // catch-all handler.
77 if (remaining_count_ <= 0) {
78 catch_all_ = true;
79 remaining_count_ = -remaining_count_;
80 } else {
81 catch_all_ = false;
82 }
83 Next();
84 }
85
Next()86 void CatchHandlerIterator::Next() {
87 if (remaining_count_ > 0) {
88 handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(¤t_data_));
89 handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
90 remaining_count_--;
91 return;
92 }
93
94 if (catch_all_) {
95 handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16);
96 handler_.address_ = DecodeUnsignedLeb128(¤t_data_);
97 catch_all_ = false;
98 return;
99 }
100
101 // no more handler
102 remaining_count_ = -1;
103 }
104
105 } // namespace art
106