Home | History | Annotate | Download | only in runtime
      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/leb128.h"
     21 #include "base/logging.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:
     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 == nullptr) {
     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 == 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 
     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:
     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     }
     82     uint32_t NativePcOffset() const {
     83       return native_pc_offset_;
     84     }
     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 null 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 
    114   DexToPcIterator DexToPcBegin() const {
    115     return DexToPcIterator(this, 0);
    116   }
    117 
    118   DexToPcIterator DexToPcEnd() const {
    119     uint32_t size = DexToPcSize();
    120     return DexToPcIterator(this, size);
    121   }
    122 
    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 
    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:
    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     }
    159     uint32_t NativePcOffset() const {
    160       return native_pc_offset_;
    161     }
    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 
    191   PcToDexIterator PcToDexBegin() const {
    192     return PcToDexIterator(this, 0);
    193   }
    194 
    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