Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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_DEX_FILE_INL_H_
     18 #define ART_RUNTIME_DEX_FILE_INL_H_
     19 
     20 #include "base/bit_utils.h"
     21 #include "base/logging.h"
     22 #include "base/stringpiece.h"
     23 #include "dex_file.h"
     24 #include "leb128.h"
     25 
     26 namespace art {
     27 
     28 inline int32_t DexFile::GetStringLength(const StringId& string_id) const {
     29   const uint8_t* ptr = begin_ + string_id.string_data_off_;
     30   return DecodeUnsignedLeb128(&ptr);
     31 }
     32 
     33 inline const char* DexFile::GetStringDataAndUtf16Length(const StringId& string_id,
     34                                                         uint32_t* utf16_length) const {
     35   DCHECK(utf16_length != nullptr) << GetLocation();
     36   const uint8_t* ptr = begin_ + string_id.string_data_off_;
     37   *utf16_length = DecodeUnsignedLeb128(&ptr);
     38   return reinterpret_cast<const char*>(ptr);
     39 }
     40 
     41 inline const char* DexFile::GetStringData(const StringId& string_id) const {
     42   uint32_t ignored;
     43   return GetStringDataAndUtf16Length(string_id, &ignored);
     44 }
     45 
     46 inline const char* DexFile::StringDataAndUtf16LengthByIdx(dex::StringIndex idx,
     47                                                           uint32_t* utf16_length) const {
     48   if (!idx.IsValid()) {
     49     *utf16_length = 0;
     50     return nullptr;
     51   }
     52   const StringId& string_id = GetStringId(idx);
     53   return GetStringDataAndUtf16Length(string_id, utf16_length);
     54 }
     55 
     56 inline const char* DexFile::StringDataByIdx(dex::StringIndex idx) const {
     57   uint32_t unicode_length;
     58   return StringDataAndUtf16LengthByIdx(idx, &unicode_length);
     59 }
     60 
     61 inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx, uint32_t* unicode_length) const {
     62   if (!idx.IsValid()) {
     63     return nullptr;
     64   }
     65   const TypeId& type_id = GetTypeId(idx);
     66   return StringDataAndUtf16LengthByIdx(type_id.descriptor_idx_, unicode_length);
     67 }
     68 
     69 inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx) const {
     70   if (!idx.IsValid()) {
     71     return nullptr;
     72   }
     73   const TypeId& type_id = GetTypeId(idx);
     74   return StringDataByIdx(type_id.descriptor_idx_);
     75 }
     76 
     77 inline const char* DexFile::GetTypeDescriptor(const TypeId& type_id) const {
     78   return StringDataByIdx(type_id.descriptor_idx_);
     79 }
     80 
     81 inline const char* DexFile::GetFieldTypeDescriptor(const FieldId& field_id) const {
     82   const DexFile::TypeId& type_id = GetTypeId(field_id.type_idx_);
     83   return GetTypeDescriptor(type_id);
     84 }
     85 
     86 inline const char* DexFile::GetFieldName(const FieldId& field_id) const {
     87   return StringDataByIdx(field_id.name_idx_);
     88 }
     89 
     90 inline const char* DexFile::GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
     91   const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
     92   return GetTypeDescriptor(type_id);
     93 }
     94 
     95 inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) const {
     96   return Signature(this, GetProtoId(method_id.proto_idx_));
     97 }
     98 
     99 inline const Signature DexFile::GetProtoSignature(const ProtoId& proto_id) const {
    100   return Signature(this, proto_id);
    101 }
    102 
    103 inline const char* DexFile::GetMethodName(const MethodId& method_id) const {
    104   return StringDataByIdx(method_id.name_idx_);
    105 }
    106 
    107 inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
    108   return StringDataByIdx(GetProtoId(GetMethodId(idx).proto_idx_).shorty_idx_);
    109 }
    110 
    111 inline const char* DexFile::GetMethodShorty(const MethodId& method_id) const {
    112   return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
    113 }
    114 
    115 inline const char* DexFile::GetMethodShorty(const MethodId& method_id, uint32_t* length) const {
    116   // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters.
    117   return StringDataAndUtf16LengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
    118 }
    119 
    120 inline const char* DexFile::GetClassDescriptor(const ClassDef& class_def) const {
    121   return StringByTypeIdx(class_def.class_idx_);
    122 }
    123 
    124 inline const char* DexFile::GetReturnTypeDescriptor(const ProtoId& proto_id) const {
    125   return StringByTypeIdx(proto_id.return_type_idx_);
    126 }
    127 
    128 inline const char* DexFile::GetShorty(uint32_t proto_idx) const {
    129   const ProtoId& proto_id = GetProtoId(proto_idx);
    130   return StringDataByIdx(proto_id.shorty_idx_);
    131 }
    132 
    133 inline const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) {
    134   const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
    135   return reinterpret_cast<const TryItem*>
    136       (RoundUp(reinterpret_cast<uintptr_t>(insns_end_), 4)) + offset;
    137 }
    138 
    139 static inline bool DexFileStringEquals(const DexFile* df1, dex::StringIndex sidx1,
    140                                        const DexFile* df2, dex::StringIndex sidx2) {
    141   uint32_t s1_len;  // Note: utf16 length != mutf8 length.
    142   const char* s1_data = df1->StringDataAndUtf16LengthByIdx(sidx1, &s1_len);
    143   uint32_t s2_len;
    144   const char* s2_data = df2->StringDataAndUtf16LengthByIdx(sidx2, &s2_len);
    145   return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
    146 }
    147 
    148 inline bool Signature::operator==(const Signature& rhs) const {
    149   if (dex_file_ == nullptr) {
    150     return rhs.dex_file_ == nullptr;
    151   }
    152   if (rhs.dex_file_ == nullptr) {
    153     return false;
    154   }
    155   if (dex_file_ == rhs.dex_file_) {
    156     return proto_id_ == rhs.proto_id_;
    157   }
    158   uint32_t lhs_shorty_len;  // For a shorty utf16 length == mutf8 length.
    159   const char* lhs_shorty_data = dex_file_->StringDataAndUtf16LengthByIdx(proto_id_->shorty_idx_,
    160                                                                          &lhs_shorty_len);
    161   StringPiece lhs_shorty(lhs_shorty_data, lhs_shorty_len);
    162   {
    163     uint32_t rhs_shorty_len;
    164     const char* rhs_shorty_data =
    165         rhs.dex_file_->StringDataAndUtf16LengthByIdx(rhs.proto_id_->shorty_idx_,
    166                                                      &rhs_shorty_len);
    167     StringPiece rhs_shorty(rhs_shorty_data, rhs_shorty_len);
    168     if (lhs_shorty != rhs_shorty) {
    169       return false;  // Shorty mismatch.
    170     }
    171   }
    172   if (lhs_shorty[0] == 'L') {
    173     const DexFile::TypeId& return_type_id = dex_file_->GetTypeId(proto_id_->return_type_idx_);
    174     const DexFile::TypeId& rhs_return_type_id =
    175         rhs.dex_file_->GetTypeId(rhs.proto_id_->return_type_idx_);
    176     if (!DexFileStringEquals(dex_file_, return_type_id.descriptor_idx_,
    177                              rhs.dex_file_, rhs_return_type_id.descriptor_idx_)) {
    178       return false;  // Return type mismatch.
    179     }
    180   }
    181   if (lhs_shorty.find('L', 1) != StringPiece::npos) {
    182     const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
    183     const DexFile::TypeList* rhs_params = rhs.dex_file_->GetProtoParameters(*rhs.proto_id_);
    184     // We found a reference parameter in the matching shorty, so both lists must be non-empty.
    185     DCHECK(params != nullptr);
    186     DCHECK(rhs_params != nullptr);
    187     uint32_t params_size = params->Size();
    188     DCHECK_EQ(params_size, rhs_params->Size());  // Parameter list size must match.
    189     for (uint32_t i = 0; i < params_size; ++i) {
    190       const DexFile::TypeId& param_id = dex_file_->GetTypeId(params->GetTypeItem(i).type_idx_);
    191       const DexFile::TypeId& rhs_param_id =
    192           rhs.dex_file_->GetTypeId(rhs_params->GetTypeItem(i).type_idx_);
    193       if (!DexFileStringEquals(dex_file_, param_id.descriptor_idx_,
    194                                rhs.dex_file_, rhs_param_id.descriptor_idx_)) {
    195         return false;  // Parameter type mismatch.
    196       }
    197     }
    198   }
    199   return true;
    200 }
    201 
    202 
    203 }  // namespace art
    204 
    205 #endif  // ART_RUNTIME_DEX_FILE_INL_H_
    206