1 /* 2 * Copyright (C) 2013 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_RUNTIME_MAPPING_TABLE_H_ 18 #define ART_RUNTIME_MAPPING_TABLE_H_ 19 20 #include "base/logging.h" 21 #include "leb128.h" 22 23 namespace art { 24 25 // A utility for processing the raw uleb128 encoded mapping table created by the quick compiler. 26 class MappingTable { 27 public: MappingTable(const uint8_t * encoded_map)28 explicit MappingTable(const uint8_t* encoded_map) : encoded_table_(encoded_map) { 29 } 30 TotalSize()31 uint32_t TotalSize() const PURE { 32 const uint8_t* table = encoded_table_; 33 if (table == nullptr) { 34 return 0; 35 } else { 36 return DecodeUnsignedLeb128(&table); 37 } 38 } 39 DexToPcSize()40 uint32_t DexToPcSize() const PURE { 41 const uint8_t* table = encoded_table_; 42 if (table == nullptr) { 43 return 0; 44 } else { 45 uint32_t total_size = DecodeUnsignedLeb128(&table); 46 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); 47 return total_size - pc_to_dex_size; 48 } 49 } 50 FirstDexToPcPtr()51 const uint8_t* FirstDexToPcPtr() const { 52 const uint8_t* table = encoded_table_; 53 if (table != nullptr) { 54 uint32_t total_size = DecodeUnsignedLeb128(&table); 55 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); 56 // We must have dex to pc entries or else the loop will go beyond the end of the table. 57 DCHECK_GT(total_size, pc_to_dex_size); 58 for (uint32_t i = 0; i < pc_to_dex_size; ++i) { 59 DecodeUnsignedLeb128(&table); // Move ptr past native PC delta. 60 DecodeSignedLeb128(&table); // Move ptr past dex PC delta. 61 } 62 } 63 return table; 64 } 65 66 class DexToPcIterator { 67 public: DexToPcIterator(const MappingTable * table,uint32_t element)68 DexToPcIterator(const MappingTable* table, uint32_t element) : 69 table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(nullptr), 70 native_pc_offset_(0), dex_pc_(0) { 71 if (element == 0) { // An iterator wanted from the start. 72 if (end_ > 0) { 73 encoded_table_ptr_ = table_->FirstDexToPcPtr(); 74 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); 75 // First delta is always positive. 76 dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_)); 77 } 78 } else { // An iterator wanted from the end. 79 DCHECK_EQ(table_->DexToPcSize(), element); 80 } 81 } NativePcOffset()82 uint32_t NativePcOffset() const { 83 return native_pc_offset_; 84 } DexPc()85 uint32_t DexPc() const { 86 return dex_pc_; 87 } 88 void operator++() { 89 ++element_; 90 if (element_ != end_) { // Avoid reading beyond the end of the table. 91 native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_); 92 // For negative delta, unsigned overflow after static_cast does exactly what we need. 93 dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_)); 94 } 95 } 96 bool operator==(const DexToPcIterator& rhs) const { 97 CHECK(table_ == rhs.table_); 98 return element_ == rhs.element_; 99 } 100 bool operator!=(const DexToPcIterator& rhs) const { 101 CHECK(table_ == rhs.table_); 102 return element_ != rhs.element_; 103 } 104 105 private: 106 const MappingTable* const table_; // The original table. 107 uint32_t element_; // A value in the range 0 to end_. 108 const uint32_t end_; // Equal to table_->DexToPcSize(). 109 const uint8_t* encoded_table_ptr_; // Either nullptr or points to encoded data after this entry. 110 uint32_t native_pc_offset_; // The current value of native pc offset. 111 uint32_t dex_pc_; // The current value of dex pc. 112 }; 113 DexToPcBegin()114 DexToPcIterator DexToPcBegin() const { 115 return DexToPcIterator(this, 0); 116 } 117 DexToPcEnd()118 DexToPcIterator DexToPcEnd() const { 119 uint32_t size = DexToPcSize(); 120 return DexToPcIterator(this, size); 121 } 122 PcToDexSize()123 uint32_t PcToDexSize() const PURE { 124 const uint8_t* table = encoded_table_; 125 if (table == nullptr) { 126 return 0; 127 } else { 128 DecodeUnsignedLeb128(&table); // Total_size, unused. 129 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); 130 return pc_to_dex_size; 131 } 132 } 133 FirstPcToDexPtr()134 const uint8_t* FirstPcToDexPtr() const { 135 const uint8_t* table = encoded_table_; 136 if (table != nullptr) { 137 DecodeUnsignedLeb128(&table); // Total_size, unused. 138 DecodeUnsignedLeb128(&table); // PC to Dex size, unused. 139 } 140 return table; 141 } 142 143 class PcToDexIterator { 144 public: PcToDexIterator(const MappingTable * table,uint32_t element)145 PcToDexIterator(const MappingTable* table, uint32_t element) : 146 table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(nullptr), 147 native_pc_offset_(0), dex_pc_(0) { 148 if (element == 0) { // An iterator wanted from the start. 149 if (end_ > 0) { 150 encoded_table_ptr_ = table_->FirstPcToDexPtr(); 151 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); 152 // First delta is always positive. 153 dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_)); 154 } 155 } else { // An iterator wanted from the end. 156 DCHECK_EQ(table_->PcToDexSize(), element); 157 } 158 } NativePcOffset()159 uint32_t NativePcOffset() const { 160 return native_pc_offset_; 161 } DexPc()162 uint32_t DexPc() const { 163 return dex_pc_; 164 } 165 void operator++() { 166 ++element_; 167 if (element_ != end_) { // Avoid reading beyond the end of the table. 168 native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_); 169 // For negative delta, unsigned overflow after static_cast does exactly what we need. 170 dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_)); 171 } 172 } 173 bool operator==(const PcToDexIterator& rhs) const { 174 CHECK(table_ == rhs.table_); 175 return element_ == rhs.element_; 176 } 177 bool operator!=(const PcToDexIterator& rhs) const { 178 CHECK(table_ == rhs.table_); 179 return element_ != rhs.element_; 180 } 181 182 private: 183 const MappingTable* const table_; // The original table. 184 uint32_t element_; // A value in the range 0 to PcToDexSize. 185 const uint32_t end_; // Equal to table_->PcToDexSize(). 186 const uint8_t* encoded_table_ptr_; // Either null or points to encoded data after this entry. 187 uint32_t native_pc_offset_; // The current value of native pc offset. 188 uint32_t dex_pc_; // The current value of dex pc. 189 }; 190 PcToDexBegin()191 PcToDexIterator PcToDexBegin() const { 192 return PcToDexIterator(this, 0); 193 } 194 PcToDexEnd()195 PcToDexIterator PcToDexEnd() const { 196 uint32_t size = PcToDexSize(); 197 return PcToDexIterator(this, size); 198 } 199 200 private: 201 const uint8_t* const encoded_table_; 202 }; 203 204 } // namespace art 205 206 #endif // ART_RUNTIME_MAPPING_TABLE_H_ 207