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