Home | History | Annotate | Download | only in dex
      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 #ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
     18 #define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
     19 
     20 #include "code_item_accessors.h"
     21 
     22 #include "base/iteration_range.h"
     23 #include "compact_dex_file.h"
     24 #include "dex_file-inl.h"
     25 #include "standard_dex_file.h"
     26 
     27 // The no ART version is used by binaries that don't include the whole runtime.
     28 namespace art {
     29 
     30 inline void CodeItemInstructionAccessor::Init(uint32_t insns_size_in_code_units,
     31                                               const uint16_t* insns) {
     32   insns_size_in_code_units_ = insns_size_in_code_units;
     33   insns_ = insns;
     34 }
     35 
     36 template <>
     37 inline void CodeItemInstructionAccessor::Init<CompactDexFile::CodeItem>(
     38     const CompactDexFile::CodeItem& code_item) {
     39   uint32_t insns_size_in_code_units;
     40   code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ true>(
     41       &insns_size_in_code_units,
     42       /*registers_size*/ nullptr,
     43       /*ins_size*/ nullptr,
     44       /*outs_size*/ nullptr,
     45       /*tries_size*/ nullptr);
     46   Init(insns_size_in_code_units, code_item.insns_);
     47 }
     48 
     49 template <>
     50 inline void CodeItemInstructionAccessor::Init<StandardDexFile::CodeItem>(
     51     const StandardDexFile::CodeItem& code_item) {
     52   Init(code_item.insns_size_in_code_units_, code_item.insns_);
     53 }
     54 
     55 inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file,
     56                                               const dex::CodeItem* code_item) {
     57   if (code_item != nullptr) {
     58     DCHECK(dex_file.IsInDataSection(code_item));
     59     if (dex_file.IsCompactDexFile()) {
     60       Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
     61     } else {
     62       DCHECK(dex_file.IsStandardDexFile());
     63       Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
     64     }
     65   }
     66 }
     67 
     68 inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
     69     const DexFile& dex_file,
     70     const dex::CodeItem* code_item) {
     71   Init(dex_file, code_item);
     72 }
     73 
     74 inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
     75   return DexInstructionIterator(insns_, 0u);
     76 }
     77 
     78 inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
     79   return DexInstructionIterator(insns_, insns_size_in_code_units_);
     80 }
     81 
     82 inline IterationRange<DexInstructionIterator> CodeItemInstructionAccessor::InstructionsFrom(
     83     uint32_t start_dex_pc) const {
     84   DCHECK_LT(start_dex_pc, InsnsSizeInCodeUnits());
     85   return {
     86       DexInstructionIterator(insns_, start_dex_pc),
     87       DexInstructionIterator(insns_, insns_size_in_code_units_) };
     88 }
     89 
     90 template <>
     91 inline void CodeItemDataAccessor::Init<CompactDexFile::CodeItem>(
     92     const CompactDexFile::CodeItem& code_item) {
     93   uint32_t insns_size_in_code_units;
     94   code_item.DecodeFields</*kDecodeOnlyInstructionCount*/ false>(&insns_size_in_code_units,
     95                                                                 &registers_size_,
     96                                                                 &ins_size_,
     97                                                                 &outs_size_,
     98                                                                 &tries_size_);
     99   CodeItemInstructionAccessor::Init(insns_size_in_code_units, code_item.insns_);
    100 }
    101 
    102 template <>
    103 inline void CodeItemDataAccessor::Init<StandardDexFile::CodeItem>(
    104     const StandardDexFile::CodeItem& code_item) {
    105   CodeItemInstructionAccessor::Init(code_item);
    106   registers_size_ = code_item.registers_size_;
    107   ins_size_ = code_item.ins_size_;
    108   outs_size_ = code_item.outs_size_;
    109   tries_size_ = code_item.tries_size_;
    110 }
    111 
    112 inline void CodeItemDataAccessor::Init(const DexFile& dex_file,
    113                                        const dex::CodeItem* code_item) {
    114   if (code_item != nullptr) {
    115     if (dex_file.IsCompactDexFile()) {
    116       Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
    117     } else {
    118       DCHECK(dex_file.IsStandardDexFile());
    119       Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
    120     }
    121   }
    122 }
    123 
    124 inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile& dex_file,
    125                                                   const dex::CodeItem* code_item) {
    126   Init(dex_file, code_item);
    127 }
    128 
    129 inline IterationRange<const dex::TryItem*> CodeItemDataAccessor::TryItems() const {
    130   const dex::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
    131   return {
    132     try_items,
    133     try_items + TriesSize() };
    134 }
    135 
    136 inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const {
    137   return DexFile::GetCatchHandlerData(end(), TriesSize(), offset);
    138 }
    139 
    140 inline const dex::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const {
    141   IterationRange<const dex::TryItem*> try_items(TryItems());
    142   int32_t index = DexFile::FindTryItem(try_items.begin(),
    143                                        try_items.end() - try_items.begin(),
    144                                        try_dex_pc);
    145   return index != -1 ? &try_items.begin()[index] : nullptr;
    146 }
    147 
    148 inline const void* CodeItemDataAccessor::CodeItemDataEnd() const {
    149   const uint8_t* handler_data = GetCatchHandlerData();
    150 
    151   if (TriesSize() == 0 || handler_data == nullptr) {
    152     return &end().Inst();
    153   }
    154   // Get the start of the handler data.
    155   const uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data);
    156   // Manually read each handler.
    157   for (uint32_t i = 0; i < handlers_size; ++i) {
    158     int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2;
    159     if (uleb128_count <= 0) {
    160       uleb128_count = -uleb128_count + 1;
    161     }
    162     for (int32_t j = 0; j < uleb128_count; ++j) {
    163       DecodeUnsignedLeb128(&handler_data);
    164     }
    165   }
    166   return reinterpret_cast<const void*>(handler_data);
    167 }
    168 
    169 template <>
    170 inline void CodeItemDebugInfoAccessor::Init<CompactDexFile::CodeItem>(
    171     const CompactDexFile::CodeItem& code_item,
    172     uint32_t dex_method_index) {
    173   debug_info_offset_ = down_cast<const CompactDexFile*>(dex_file_)->GetDebugInfoOffset(
    174       dex_method_index);
    175   CodeItemDataAccessor::Init(code_item);
    176 }
    177 
    178 template <>
    179 inline void CodeItemDebugInfoAccessor::Init<StandardDexFile::CodeItem>(
    180     const StandardDexFile::CodeItem& code_item,
    181     uint32_t dex_method_index ATTRIBUTE_UNUSED) {
    182   debug_info_offset_ = code_item.debug_info_off_;
    183   CodeItemDataAccessor::Init(code_item);
    184 }
    185 
    186 inline void CodeItemDebugInfoAccessor::Init(const DexFile& dex_file,
    187                                             const dex::CodeItem* code_item,
    188                                             uint32_t dex_method_index) {
    189   if (code_item == nullptr) {
    190     return;
    191   }
    192   dex_file_ = &dex_file;
    193   if (dex_file.IsCompactDexFile()) {
    194     Init(down_cast<const CompactDexFile::CodeItem&>(*code_item), dex_method_index);
    195   } else {
    196     DCHECK(dex_file.IsStandardDexFile());
    197     Init(down_cast<const StandardDexFile::CodeItem&>(*code_item), dex_method_index);
    198   }
    199 }
    200 
    201 template<typename NewLocalVisitor>
    202 inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(
    203     bool is_static,
    204     uint32_t method_idx,
    205     const NewLocalVisitor& new_local) const {
    206   return dex_file_->DecodeDebugLocalInfo(RegistersSize(),
    207                                          InsSize(),
    208                                          InsnsSizeInCodeUnits(),
    209                                          DebugInfoOffset(),
    210                                          is_static,
    211                                          method_idx,
    212                                          new_local);
    213 }
    214 
    215 template <typename Visitor>
    216 inline uint32_t CodeItemDebugInfoAccessor::VisitParameterNames(const Visitor& visitor) const {
    217   const uint8_t* stream = dex_file_->GetDebugInfoStream(DebugInfoOffset());
    218   return (stream != nullptr) ? DexFile::DecodeDebugInfoParameterNames(&stream, visitor) : 0u;
    219 }
    220 
    221 inline bool CodeItemDebugInfoAccessor::GetLineNumForPc(const uint32_t address,
    222                                                        uint32_t* line_num) const {
    223   return DecodeDebugPositionInfo([&](const DexFile::PositionInfo& entry) {
    224     // We know that this callback will be called in ascending address order, so keep going until we
    225     // find a match or we've just gone past it.
    226     if (entry.address_ > address) {
    227       // The line number from the previous positions callback will be the final result.
    228       return true;
    229     }
    230     *line_num = entry.line_;
    231     return entry.address_ == address;
    232   });
    233 }
    234 
    235 template <typename Visitor>
    236 inline bool CodeItemDebugInfoAccessor::DecodeDebugPositionInfo(const Visitor& visitor) const {
    237   return dex_file_->DecodeDebugPositionInfo(
    238       dex_file_->GetDebugInfoStream(DebugInfoOffset()),
    239       [this](uint32_t idx) {
    240         return dex_file_->StringDataByIdx(dex::StringIndex(idx));
    241       },
    242       visitor);
    243 }
    244 
    245 }  // namespace art
    246 
    247 #endif  // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
    248