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