Home | History | Annotate | Download | only in dex
      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_LIBDEXFILE_DEX_DEX_FILE_INL_H_
     18 #define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
     19 
     20 #include "base/casts.h"
     21 #include "base/leb128.h"
     22 #include "base/stringpiece.h"
     23 #include "compact_dex_file.h"
     24 #include "dex_file.h"
     25 #include "invoke_type.h"
     26 #include "standard_dex_file.h"
     27 
     28 namespace art {
     29 
     30 inline int32_t DexFile::GetStringLength(const StringId& string_id) const {
     31   const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
     32   return DecodeUnsignedLeb128(&ptr);
     33 }
     34 
     35 inline const char* DexFile::GetStringDataAndUtf16Length(const StringId& string_id,
     36                                                         uint32_t* utf16_length) const {
     37   DCHECK(utf16_length != nullptr) << GetLocation();
     38   const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
     39   *utf16_length = DecodeUnsignedLeb128(&ptr);
     40   return reinterpret_cast<const char*>(ptr);
     41 }
     42 
     43 inline const char* DexFile::GetStringData(const StringId& string_id) const {
     44   uint32_t ignored;
     45   return GetStringDataAndUtf16Length(string_id, &ignored);
     46 }
     47 
     48 inline const char* DexFile::StringDataAndUtf16LengthByIdx(dex::StringIndex idx,
     49                                                           uint32_t* utf16_length) const {
     50   if (!idx.IsValid()) {
     51     *utf16_length = 0;
     52     return nullptr;
     53   }
     54   const StringId& string_id = GetStringId(idx);
     55   return GetStringDataAndUtf16Length(string_id, utf16_length);
     56 }
     57 
     58 inline const char* DexFile::StringDataByIdx(dex::StringIndex idx) const {
     59   uint32_t unicode_length;
     60   return StringDataAndUtf16LengthByIdx(idx, &unicode_length);
     61 }
     62 
     63 inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx, uint32_t* unicode_length) const {
     64   if (!idx.IsValid()) {
     65     return nullptr;
     66   }
     67   const TypeId& type_id = GetTypeId(idx);
     68   return StringDataAndUtf16LengthByIdx(type_id.descriptor_idx_, unicode_length);
     69 }
     70 
     71 inline const char* DexFile::StringByTypeIdx(dex::TypeIndex idx) const {
     72   if (!idx.IsValid()) {
     73     return nullptr;
     74   }
     75   const TypeId& type_id = GetTypeId(idx);
     76   return StringDataByIdx(type_id.descriptor_idx_);
     77 }
     78 
     79 inline const char* DexFile::GetTypeDescriptor(const TypeId& type_id) const {
     80   return StringDataByIdx(type_id.descriptor_idx_);
     81 }
     82 
     83 inline const char* DexFile::GetFieldTypeDescriptor(const FieldId& field_id) const {
     84   const DexFile::TypeId& type_id = GetTypeId(field_id.type_idx_);
     85   return GetTypeDescriptor(type_id);
     86 }
     87 
     88 inline const char* DexFile::GetFieldName(const FieldId& field_id) const {
     89   return StringDataByIdx(field_id.name_idx_);
     90 }
     91 
     92 inline const char* DexFile::GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
     93   const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
     94   return GetTypeDescriptor(type_id);
     95 }
     96 
     97 inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) const {
     98   return Signature(this, GetProtoId(method_id.proto_idx_));
     99 }
    100 
    101 inline const Signature DexFile::GetProtoSignature(const ProtoId& proto_id) const {
    102   return Signature(this, proto_id);
    103 }
    104 
    105 inline const char* DexFile::GetMethodName(const MethodId& method_id) const {
    106   return StringDataByIdx(method_id.name_idx_);
    107 }
    108 
    109 inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
    110   return StringDataByIdx(GetProtoId(GetMethodId(idx).proto_idx_).shorty_idx_);
    111 }
    112 
    113 inline const char* DexFile::GetMethodShorty(const MethodId& method_id) const {
    114   return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
    115 }
    116 
    117 inline const char* DexFile::GetMethodShorty(const MethodId& method_id, uint32_t* length) const {
    118   // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters.
    119   return StringDataAndUtf16LengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
    120 }
    121 
    122 inline const char* DexFile::GetClassDescriptor(const ClassDef& class_def) const {
    123   return StringByTypeIdx(class_def.class_idx_);
    124 }
    125 
    126 inline const char* DexFile::GetReturnTypeDescriptor(const ProtoId& proto_id) const {
    127   return StringByTypeIdx(proto_id.return_type_idx_);
    128 }
    129 
    130 inline const char* DexFile::GetShorty(uint32_t proto_idx) const {
    131   const ProtoId& proto_id = GetProtoId(proto_idx);
    132   return StringDataByIdx(proto_id.shorty_idx_);
    133 }
    134 
    135 inline const DexFile::TryItem* DexFile::GetTryItems(const DexInstructionIterator& code_item_end,
    136                                                     uint32_t offset) {
    137   return reinterpret_cast<const TryItem*>
    138       (RoundUp(reinterpret_cast<uintptr_t>(&code_item_end.Inst()), TryItem::kAlignment)) + offset;
    139 }
    140 
    141 static inline bool DexFileStringEquals(const DexFile* df1, dex::StringIndex sidx1,
    142                                        const DexFile* df2, dex::StringIndex sidx2) {
    143   uint32_t s1_len;  // Note: utf16 length != mutf8 length.
    144   const char* s1_data = df1->StringDataAndUtf16LengthByIdx(sidx1, &s1_len);
    145   uint32_t s2_len;
    146   const char* s2_data = df2->StringDataAndUtf16LengthByIdx(sidx2, &s2_len);
    147   return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
    148 }
    149 
    150 inline bool Signature::operator==(const Signature& rhs) const {
    151   if (dex_file_ == nullptr) {
    152     return rhs.dex_file_ == nullptr;
    153   }
    154   if (rhs.dex_file_ == nullptr) {
    155     return false;
    156   }
    157   if (dex_file_ == rhs.dex_file_) {
    158     return proto_id_ == rhs.proto_id_;
    159   }
    160   uint32_t lhs_shorty_len;  // For a shorty utf16 length == mutf8 length.
    161   const char* lhs_shorty_data = dex_file_->StringDataAndUtf16LengthByIdx(proto_id_->shorty_idx_,
    162                                                                          &lhs_shorty_len);
    163   StringPiece lhs_shorty(lhs_shorty_data, lhs_shorty_len);
    164   {
    165     uint32_t rhs_shorty_len;
    166     const char* rhs_shorty_data =
    167         rhs.dex_file_->StringDataAndUtf16LengthByIdx(rhs.proto_id_->shorty_idx_,
    168                                                      &rhs_shorty_len);
    169     StringPiece rhs_shorty(rhs_shorty_data, rhs_shorty_len);
    170     if (lhs_shorty != rhs_shorty) {
    171       return false;  // Shorty mismatch.
    172     }
    173   }
    174   if (lhs_shorty[0] == 'L') {
    175     const DexFile::TypeId& return_type_id = dex_file_->GetTypeId(proto_id_->return_type_idx_);
    176     const DexFile::TypeId& rhs_return_type_id =
    177         rhs.dex_file_->GetTypeId(rhs.proto_id_->return_type_idx_);
    178     if (!DexFileStringEquals(dex_file_, return_type_id.descriptor_idx_,
    179                              rhs.dex_file_, rhs_return_type_id.descriptor_idx_)) {
    180       return false;  // Return type mismatch.
    181     }
    182   }
    183   if (lhs_shorty.find('L', 1) != StringPiece::npos) {
    184     const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
    185     const DexFile::TypeList* rhs_params = rhs.dex_file_->GetProtoParameters(*rhs.proto_id_);
    186     // We found a reference parameter in the matching shorty, so both lists must be non-empty.
    187     DCHECK(params != nullptr);
    188     DCHECK(rhs_params != nullptr);
    189     uint32_t params_size = params->Size();
    190     DCHECK_EQ(params_size, rhs_params->Size());  // Parameter list size must match.
    191     for (uint32_t i = 0; i < params_size; ++i) {
    192       const DexFile::TypeId& param_id = dex_file_->GetTypeId(params->GetTypeItem(i).type_idx_);
    193       const DexFile::TypeId& rhs_param_id =
    194           rhs.dex_file_->GetTypeId(rhs_params->GetTypeItem(i).type_idx_);
    195       if (!DexFileStringEquals(dex_file_, param_id.descriptor_idx_,
    196                                rhs.dex_file_, rhs_param_id.descriptor_idx_)) {
    197         return false;  // Parameter type mismatch.
    198       }
    199     }
    200   }
    201   return true;
    202 }
    203 
    204 inline
    205 InvokeType ClassDataItemIterator::GetMethodInvokeType(const DexFile::ClassDef& class_def) const {
    206   if (HasNextDirectMethod()) {
    207     if ((GetRawMemberAccessFlags() & kAccStatic) != 0) {
    208       return kStatic;
    209     } else {
    210       return kDirect;
    211     }
    212   } else {
    213     DCHECK_EQ(GetRawMemberAccessFlags() & kAccStatic, 0U);
    214     if ((class_def.access_flags_ & kAccInterface) != 0) {
    215       return kInterface;
    216     } else if ((GetRawMemberAccessFlags() & kAccConstructor) != 0) {
    217       return kSuper;
    218     } else {
    219       return kVirtual;
    220     }
    221   }
    222 }
    223 
    224 template<typename NewLocalCallback, typename IndexToStringData, typename TypeIndexToStringData>
    225 bool DexFile::DecodeDebugLocalInfo(const uint8_t* stream,
    226                                    const std::string& location,
    227                                    const char* declaring_class_descriptor,
    228                                    const std::vector<const char*>& arg_descriptors,
    229                                    const std::string& method_name,
    230                                    bool is_static,
    231                                    uint16_t registers_size,
    232                                    uint16_t ins_size,
    233                                    uint16_t insns_size_in_code_units,
    234                                    IndexToStringData index_to_string_data,
    235                                    TypeIndexToStringData type_index_to_string_data,
    236                                    NewLocalCallback new_local_callback,
    237                                    void* context) {
    238   if (stream == nullptr) {
    239     return false;
    240   }
    241   std::vector<LocalInfo> local_in_reg(registers_size);
    242 
    243   uint16_t arg_reg = registers_size - ins_size;
    244   if (!is_static) {
    245     const char* descriptor = declaring_class_descriptor;
    246     local_in_reg[arg_reg].name_ = "this";
    247     local_in_reg[arg_reg].descriptor_ = descriptor;
    248     local_in_reg[arg_reg].signature_ = nullptr;
    249     local_in_reg[arg_reg].start_address_ = 0;
    250     local_in_reg[arg_reg].reg_ = arg_reg;
    251     local_in_reg[arg_reg].is_live_ = true;
    252     arg_reg++;
    253   }
    254 
    255   DecodeUnsignedLeb128(&stream);  // Line.
    256   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
    257   uint32_t i;
    258   if (parameters_size != arg_descriptors.size()) {
    259     LOG(ERROR) << "invalid stream - problem with parameter iterator in " << location
    260                << " for method " << method_name;
    261     return false;
    262   }
    263   for (i = 0; i < parameters_size && i < arg_descriptors.size(); ++i) {
    264     if (arg_reg >= registers_size) {
    265       LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
    266                  << " >= " << registers_size << ") in " << location;
    267       return false;
    268     }
    269     uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
    270     const char* descriptor = arg_descriptors[i];
    271     local_in_reg[arg_reg].name_ = index_to_string_data(name_idx);
    272     local_in_reg[arg_reg].descriptor_ = descriptor;
    273     local_in_reg[arg_reg].signature_ = nullptr;
    274     local_in_reg[arg_reg].start_address_ = 0;
    275     local_in_reg[arg_reg].reg_ = arg_reg;
    276     local_in_reg[arg_reg].is_live_ = true;
    277     switch (*descriptor) {
    278       case 'D':
    279       case 'J':
    280         arg_reg += 2;
    281         break;
    282       default:
    283         arg_reg += 1;
    284         break;
    285     }
    286   }
    287 
    288   uint32_t address = 0;
    289   for (;;)  {
    290     uint8_t opcode = *stream++;
    291     switch (opcode) {
    292       case DBG_END_SEQUENCE:
    293         // Emit all variables which are still alive at the end of the method.
    294         for (uint16_t reg = 0; reg < registers_size; reg++) {
    295           if (local_in_reg[reg].is_live_) {
    296             local_in_reg[reg].end_address_ = insns_size_in_code_units;
    297             new_local_callback(context, local_in_reg[reg]);
    298           }
    299         }
    300         return true;
    301       case DBG_ADVANCE_PC:
    302         address += DecodeUnsignedLeb128(&stream);
    303         break;
    304       case DBG_ADVANCE_LINE:
    305         DecodeSignedLeb128(&stream);  // Line.
    306         break;
    307       case DBG_START_LOCAL:
    308       case DBG_START_LOCAL_EXTENDED: {
    309         uint16_t reg = DecodeUnsignedLeb128(&stream);
    310         if (reg >= registers_size) {
    311           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
    312                      << registers_size << ") in " << location;
    313           return false;
    314         }
    315 
    316         uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
    317         uint16_t descriptor_idx = DecodeUnsignedLeb128P1(&stream);
    318         uint32_t signature_idx = dex::kDexNoIndex;
    319         if (opcode == DBG_START_LOCAL_EXTENDED) {
    320           signature_idx = DecodeUnsignedLeb128P1(&stream);
    321         }
    322 
    323         // Emit what was previously there, if anything
    324         if (local_in_reg[reg].is_live_) {
    325           local_in_reg[reg].end_address_ = address;
    326           new_local_callback(context, local_in_reg[reg]);
    327         }
    328 
    329         local_in_reg[reg].name_ = index_to_string_data(name_idx);
    330         local_in_reg[reg].descriptor_ = type_index_to_string_data(descriptor_idx);;
    331         local_in_reg[reg].signature_ = index_to_string_data(signature_idx);
    332         local_in_reg[reg].start_address_ = address;
    333         local_in_reg[reg].reg_ = reg;
    334         local_in_reg[reg].is_live_ = true;
    335         break;
    336       }
    337       case DBG_END_LOCAL: {
    338         uint16_t reg = DecodeUnsignedLeb128(&stream);
    339         if (reg >= registers_size) {
    340           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
    341                      << registers_size << ") in " << location;
    342           return false;
    343         }
    344         // If the register is live, close it properly. Otherwise, closing an already
    345         // closed register is sloppy, but harmless if no further action is taken.
    346         if (local_in_reg[reg].is_live_) {
    347           local_in_reg[reg].end_address_ = address;
    348           new_local_callback(context, local_in_reg[reg]);
    349           local_in_reg[reg].is_live_ = false;
    350         }
    351         break;
    352       }
    353       case DBG_RESTART_LOCAL: {
    354         uint16_t reg = DecodeUnsignedLeb128(&stream);
    355         if (reg >= registers_size) {
    356           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
    357                      << registers_size << ") in " << location;
    358           return false;
    359         }
    360         // If the register is live, the "restart" is superfluous,
    361         // and we don't want to mess with the existing start address.
    362         if (!local_in_reg[reg].is_live_) {
    363           local_in_reg[reg].start_address_ = address;
    364           local_in_reg[reg].is_live_ = true;
    365         }
    366         break;
    367       }
    368       case DBG_SET_PROLOGUE_END:
    369       case DBG_SET_EPILOGUE_BEGIN:
    370         break;
    371       case DBG_SET_FILE:
    372         DecodeUnsignedLeb128P1(&stream);  // name.
    373         break;
    374       default:
    375         address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE;
    376         break;
    377     }
    378   }
    379 }
    380 
    381 template<typename NewLocalCallback>
    382 bool DexFile::DecodeDebugLocalInfo(uint32_t registers_size,
    383                                    uint32_t ins_size,
    384                                    uint32_t insns_size_in_code_units,
    385                                    uint32_t debug_info_offset,
    386                                    bool is_static,
    387                                    uint32_t method_idx,
    388                                    NewLocalCallback new_local_callback,
    389                                    void* context) const {
    390   const uint8_t* const stream = GetDebugInfoStream(debug_info_offset);
    391   if (stream == nullptr) {
    392     return false;
    393   }
    394   std::vector<const char*> arg_descriptors;
    395   DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
    396   for (; it.HasNext(); it.Next()) {
    397     arg_descriptors.push_back(it.GetDescriptor());
    398   }
    399   return DecodeDebugLocalInfo(stream,
    400                               GetLocation(),
    401                               GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)),
    402                               arg_descriptors,
    403                               this->PrettyMethod(method_idx),
    404                               is_static,
    405                               registers_size,
    406                               ins_size,
    407                               insns_size_in_code_units,
    408                               [this](uint32_t idx) {
    409                                 return StringDataByIdx(dex::StringIndex(idx));
    410                               },
    411                               [this](uint32_t idx) {
    412                                 return StringByTypeIdx(dex::TypeIndex(
    413                                     dchecked_integral_cast<uint16_t>(idx)));
    414                               },
    415                               new_local_callback,
    416                               context);
    417 }
    418 
    419 template<typename DexDebugNewPosition, typename IndexToStringData>
    420 bool DexFile::DecodeDebugPositionInfo(const uint8_t* stream,
    421                                       IndexToStringData index_to_string_data,
    422                                       DexDebugNewPosition position_functor,
    423                                       void* context) {
    424   if (stream == nullptr) {
    425     return false;
    426   }
    427 
    428   PositionInfo entry = PositionInfo();
    429   entry.line_ = DecodeUnsignedLeb128(&stream);
    430   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
    431   for (uint32_t i = 0; i < parameters_size; ++i) {
    432     DecodeUnsignedLeb128P1(&stream);  // Parameter name.
    433   }
    434 
    435   for (;;)  {
    436     uint8_t opcode = *stream++;
    437     switch (opcode) {
    438       case DBG_END_SEQUENCE:
    439         return true;  // end of stream.
    440       case DBG_ADVANCE_PC:
    441         entry.address_ += DecodeUnsignedLeb128(&stream);
    442         break;
    443       case DBG_ADVANCE_LINE:
    444         entry.line_ += DecodeSignedLeb128(&stream);
    445         break;
    446       case DBG_START_LOCAL:
    447         DecodeUnsignedLeb128(&stream);  // reg.
    448         DecodeUnsignedLeb128P1(&stream);  // name.
    449         DecodeUnsignedLeb128P1(&stream);  // descriptor.
    450         break;
    451       case DBG_START_LOCAL_EXTENDED:
    452         DecodeUnsignedLeb128(&stream);  // reg.
    453         DecodeUnsignedLeb128P1(&stream);  // name.
    454         DecodeUnsignedLeb128P1(&stream);  // descriptor.
    455         DecodeUnsignedLeb128P1(&stream);  // signature.
    456         break;
    457       case DBG_END_LOCAL:
    458       case DBG_RESTART_LOCAL:
    459         DecodeUnsignedLeb128(&stream);  // reg.
    460         break;
    461       case DBG_SET_PROLOGUE_END:
    462         entry.prologue_end_ = true;
    463         break;
    464       case DBG_SET_EPILOGUE_BEGIN:
    465         entry.epilogue_begin_ = true;
    466         break;
    467       case DBG_SET_FILE: {
    468         uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
    469         entry.source_file_ = index_to_string_data(name_idx);
    470         break;
    471       }
    472       default: {
    473         int adjopcode = opcode - DBG_FIRST_SPECIAL;
    474         entry.address_ += adjopcode / DBG_LINE_RANGE;
    475         entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
    476         if (position_functor(context, entry)) {
    477           return true;  // early exit.
    478         }
    479         entry.prologue_end_ = false;
    480         entry.epilogue_begin_ = false;
    481         break;
    482       }
    483     }
    484   }
    485 }
    486 
    487 template<typename DexDebugNewPosition>
    488 bool DexFile::DecodeDebugPositionInfo(uint32_t debug_info_offset,
    489                                       DexDebugNewPosition position_functor,
    490                                       void* context) const {
    491   return DecodeDebugPositionInfo(GetDebugInfoStream(debug_info_offset),
    492                                  [this](uint32_t idx) {
    493                                    return StringDataByIdx(dex::StringIndex(idx));
    494                                  },
    495                                  position_functor,
    496                                  context);
    497 }
    498 
    499 inline const CompactDexFile* DexFile::AsCompactDexFile() const {
    500   DCHECK(IsCompactDexFile());
    501   return down_cast<const CompactDexFile*>(this);
    502 }
    503 
    504 inline const StandardDexFile* DexFile::AsStandardDexFile() const {
    505   DCHECK(IsStandardDexFile());
    506   return down_cast<const StandardDexFile*>(this);
    507 }
    508 
    509 // Get the base of the encoded data for the given DexCode.
    510 inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator& code_item_end,
    511                                                    uint32_t tries_size,
    512                                                    uint32_t offset) {
    513   const uint8_t* handler_data =
    514       reinterpret_cast<const uint8_t*>(GetTryItems(code_item_end, tries_size));
    515   return handler_data + offset;
    516 }
    517 
    518 template <typename Visitor>
    519 inline void DexFile::ClassDef::VisitMethods(const DexFile* dex_file, const Visitor& visitor) const {
    520   const uint8_t* class_data = dex_file->GetClassData(*this);
    521   if (class_data != nullptr) {
    522     ClassDataItemIterator it(*dex_file, class_data);
    523     it.SkipAllFields();
    524     for (; it.HasNext(); it.Next()) {
    525       visitor(it);
    526     }
    527   }
    528 }
    529 
    530 }  // namespace art
    531 
    532 #endif  // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
    533