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 #include "dex_file.h"
     18 
     19 #include <limits.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <zlib.h>
     24 
     25 #include <memory>
     26 #include <sstream>
     27 #include <type_traits>
     28 
     29 #include "android-base/stringprintf.h"
     30 
     31 #include "base/enums.h"
     32 #include "base/leb128.h"
     33 #include "base/stl_util.h"
     34 #include "descriptors_names.h"
     35 #include "dex_file-inl.h"
     36 #include "standard_dex_file.h"
     37 #include "utf-inl.h"
     38 
     39 namespace art {
     40 
     41 using android::base::StringPrintf;
     42 
     43 static_assert(sizeof(dex::StringIndex) == sizeof(uint32_t), "StringIndex size is wrong");
     44 static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex not trivial");
     45 static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
     46 static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
     47 
     48 void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
     49   uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
     50   uint32_t new_flag = class_it.GetMemberAccessFlags();
     51   bool is_method = class_it.IsAtMethod();
     52   // Go back 1 uleb to start.
     53   data = ReverseSearchUnsignedLeb128(data);
     54   if (is_method) {
     55     // Methods have another uleb field before the access flags
     56     data = ReverseSearchUnsignedLeb128(data);
     57   }
     58   DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
     59             new_flag);
     60   UpdateUnsignedLeb128(data, new_flag);
     61 }
     62 
     63 uint32_t DexFile::CalculateChecksum() const {
     64   return CalculateChecksum(Begin(), Size());
     65 }
     66 
     67 uint32_t DexFile::CalculateChecksum(const uint8_t* begin, size_t size) {
     68   const uint32_t non_sum_bytes = OFFSETOF_MEMBER(DexFile::Header, signature_);
     69   return ChecksumMemoryRange(begin + non_sum_bytes, size - non_sum_bytes);
     70 }
     71 
     72 uint32_t DexFile::ChecksumMemoryRange(const uint8_t* begin, size_t size) {
     73   return adler32(adler32(0L, Z_NULL, 0), begin, size);
     74 }
     75 
     76 int DexFile::GetPermissions() const {
     77   CHECK(container_.get() != nullptr);
     78   return container_->GetPermissions();
     79 }
     80 
     81 bool DexFile::IsReadOnly() const {
     82   CHECK(container_.get() != nullptr);
     83   return container_->IsReadOnly();
     84 }
     85 
     86 bool DexFile::EnableWrite() const {
     87   CHECK(container_.get() != nullptr);
     88   return container_->EnableWrite();
     89 }
     90 
     91 bool DexFile::DisableWrite() const {
     92   CHECK(container_.get() != nullptr);
     93   return container_->DisableWrite();
     94 }
     95 
     96 DexFile::DexFile(const uint8_t* base,
     97                  size_t size,
     98                  const uint8_t* data_begin,
     99                  size_t data_size,
    100                  const std::string& location,
    101                  uint32_t location_checksum,
    102                  const OatDexFile* oat_dex_file,
    103                  std::unique_ptr<DexFileContainer> container,
    104                  bool is_compact_dex)
    105     : begin_(base),
    106       size_(size),
    107       data_begin_(data_begin),
    108       data_size_(data_size),
    109       location_(location),
    110       location_checksum_(location_checksum),
    111       header_(reinterpret_cast<const Header*>(base)),
    112       string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
    113       type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
    114       field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)),
    115       method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
    116       proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
    117       class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
    118       method_handles_(nullptr),
    119       num_method_handles_(0),
    120       call_site_ids_(nullptr),
    121       num_call_site_ids_(0),
    122       oat_dex_file_(oat_dex_file),
    123       container_(std::move(container)),
    124       is_compact_dex_(is_compact_dex),
    125       is_platform_dex_(false) {
    126   CHECK(begin_ != nullptr) << GetLocation();
    127   CHECK_GT(size_, 0U) << GetLocation();
    128   // Check base (=header) alignment.
    129   // Must be 4-byte aligned to avoid undefined behavior when accessing
    130   // any of the sections via a pointer.
    131   CHECK_ALIGNED(begin_, alignof(Header));
    132 
    133   InitializeSectionsFromMapList();
    134 }
    135 
    136 DexFile::~DexFile() {
    137   // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
    138   // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
    139   // re-attach, but cleaning up these global references is not obviously useful. It's not as if
    140   // the global reference table is otherwise empty!
    141 }
    142 
    143 bool DexFile::Init(std::string* error_msg) {
    144   if (!CheckMagicAndVersion(error_msg)) {
    145     return false;
    146   }
    147   return true;
    148 }
    149 
    150 bool DexFile::CheckMagicAndVersion(std::string* error_msg) const {
    151   if (!IsMagicValid()) {
    152     std::ostringstream oss;
    153     oss << "Unrecognized magic number in "  << GetLocation() << ":"
    154             << " " << header_->magic_[0]
    155             << " " << header_->magic_[1]
    156             << " " << header_->magic_[2]
    157             << " " << header_->magic_[3];
    158     *error_msg = oss.str();
    159     return false;
    160   }
    161   if (!IsVersionValid()) {
    162     std::ostringstream oss;
    163     oss << "Unrecognized version number in "  << GetLocation() << ":"
    164             << " " << header_->magic_[4]
    165             << " " << header_->magic_[5]
    166             << " " << header_->magic_[6]
    167             << " " << header_->magic_[7];
    168     *error_msg = oss.str();
    169     return false;
    170   }
    171   return true;
    172 }
    173 
    174 void DexFile::InitializeSectionsFromMapList() {
    175   const MapList* map_list = reinterpret_cast<const MapList*>(DataBegin() + header_->map_off_);
    176   if (header_->map_off_ == 0 || header_->map_off_ > DataSize()) {
    177     // Bad offset. The dex file verifier runs after this method and will reject the file.
    178     return;
    179   }
    180   const size_t count = map_list->size_;
    181 
    182   size_t map_limit = header_->map_off_ + count * sizeof(MapItem);
    183   if (header_->map_off_ >= map_limit || map_limit > DataSize()) {
    184     // Overflow or out out of bounds. The dex file verifier runs after
    185     // this method and will reject the file as it is malformed.
    186     return;
    187   }
    188 
    189   for (size_t i = 0; i < count; ++i) {
    190     const MapItem& map_item = map_list->list_[i];
    191     if (map_item.type_ == kDexTypeMethodHandleItem) {
    192       method_handles_ = reinterpret_cast<const MethodHandleItem*>(Begin() + map_item.offset_);
    193       num_method_handles_ = map_item.size_;
    194     } else if (map_item.type_ == kDexTypeCallSiteIdItem) {
    195       call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(Begin() + map_item.offset_);
    196       num_call_site_ids_ = map_item.size_;
    197     }
    198   }
    199 }
    200 
    201 uint32_t DexFile::Header::GetVersion() const {
    202   const char* version = reinterpret_cast<const char*>(&magic_[kDexMagicSize]);
    203   return atoi(version);
    204 }
    205 
    206 const DexFile::ClassDef* DexFile::FindClassDef(dex::TypeIndex type_idx) const {
    207   size_t num_class_defs = NumClassDefs();
    208   // Fast path for rare no class defs case.
    209   if (num_class_defs == 0) {
    210     return nullptr;
    211   }
    212   for (size_t i = 0; i < num_class_defs; ++i) {
    213     const ClassDef& class_def = GetClassDef(i);
    214     if (class_def.class_idx_ == type_idx) {
    215       return &class_def;
    216     }
    217   }
    218   return nullptr;
    219 }
    220 
    221 uint32_t DexFile::FindCodeItemOffset(const DexFile::ClassDef& class_def,
    222                                      uint32_t method_idx) const {
    223   const uint8_t* class_data = GetClassData(class_def);
    224   CHECK(class_data != nullptr);
    225   ClassDataItemIterator it(*this, class_data);
    226   it.SkipAllFields();
    227   while (it.HasNextDirectMethod()) {
    228     if (it.GetMemberIndex() == method_idx) {
    229       return it.GetMethodCodeItemOffset();
    230     }
    231     it.Next();
    232   }
    233   while (it.HasNextVirtualMethod()) {
    234     if (it.GetMemberIndex() == method_idx) {
    235       return it.GetMethodCodeItemOffset();
    236     }
    237     it.Next();
    238   }
    239   LOG(FATAL) << "Unable to find method " << method_idx;
    240   UNREACHABLE();
    241 }
    242 
    243 const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
    244                                              const DexFile::StringId& name,
    245                                              const DexFile::TypeId& type) const {
    246   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
    247   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
    248   const dex::StringIndex name_idx = GetIndexForStringId(name);
    249   const dex::TypeIndex type_idx = GetIndexForTypeId(type);
    250   int32_t lo = 0;
    251   int32_t hi = NumFieldIds() - 1;
    252   while (hi >= lo) {
    253     int32_t mid = (hi + lo) / 2;
    254     const DexFile::FieldId& field = GetFieldId(mid);
    255     if (class_idx > field.class_idx_) {
    256       lo = mid + 1;
    257     } else if (class_idx < field.class_idx_) {
    258       hi = mid - 1;
    259     } else {
    260       if (name_idx > field.name_idx_) {
    261         lo = mid + 1;
    262       } else if (name_idx < field.name_idx_) {
    263         hi = mid - 1;
    264       } else {
    265         if (type_idx > field.type_idx_) {
    266           lo = mid + 1;
    267         } else if (type_idx < field.type_idx_) {
    268           hi = mid - 1;
    269         } else {
    270           return &field;
    271         }
    272       }
    273     }
    274   }
    275   return nullptr;
    276 }
    277 
    278 const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
    279                                                const DexFile::StringId& name,
    280                                                const DexFile::ProtoId& signature) const {
    281   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
    282   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
    283   const dex::StringIndex name_idx = GetIndexForStringId(name);
    284   const uint16_t proto_idx = GetIndexForProtoId(signature);
    285   int32_t lo = 0;
    286   int32_t hi = NumMethodIds() - 1;
    287   while (hi >= lo) {
    288     int32_t mid = (hi + lo) / 2;
    289     const DexFile::MethodId& method = GetMethodId(mid);
    290     if (class_idx > method.class_idx_) {
    291       lo = mid + 1;
    292     } else if (class_idx < method.class_idx_) {
    293       hi = mid - 1;
    294     } else {
    295       if (name_idx > method.name_idx_) {
    296         lo = mid + 1;
    297       } else if (name_idx < method.name_idx_) {
    298         hi = mid - 1;
    299       } else {
    300         if (proto_idx > method.proto_idx_) {
    301           lo = mid + 1;
    302         } else if (proto_idx < method.proto_idx_) {
    303           hi = mid - 1;
    304         } else {
    305           return &method;
    306         }
    307       }
    308     }
    309   }
    310   return nullptr;
    311 }
    312 
    313 const DexFile::StringId* DexFile::FindStringId(const char* string) const {
    314   int32_t lo = 0;
    315   int32_t hi = NumStringIds() - 1;
    316   while (hi >= lo) {
    317     int32_t mid = (hi + lo) / 2;
    318     const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid));
    319     const char* str = GetStringData(str_id);
    320     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
    321     if (compare > 0) {
    322       lo = mid + 1;
    323     } else if (compare < 0) {
    324       hi = mid - 1;
    325     } else {
    326       return &str_id;
    327     }
    328   }
    329   return nullptr;
    330 }
    331 
    332 const DexFile::TypeId* DexFile::FindTypeId(const char* string) const {
    333   int32_t lo = 0;
    334   int32_t hi = NumTypeIds() - 1;
    335   while (hi >= lo) {
    336     int32_t mid = (hi + lo) / 2;
    337     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid));
    338     const DexFile::StringId& str_id = GetStringId(type_id.descriptor_idx_);
    339     const char* str = GetStringData(str_id);
    340     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
    341     if (compare > 0) {
    342       lo = mid + 1;
    343     } else if (compare < 0) {
    344       hi = mid - 1;
    345     } else {
    346       return &type_id;
    347     }
    348   }
    349   return nullptr;
    350 }
    351 
    352 const DexFile::StringId* DexFile::FindStringId(const uint16_t* string, size_t length) const {
    353   int32_t lo = 0;
    354   int32_t hi = NumStringIds() - 1;
    355   while (hi >= lo) {
    356     int32_t mid = (hi + lo) / 2;
    357     const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid));
    358     const char* str = GetStringData(str_id);
    359     int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string, length);
    360     if (compare > 0) {
    361       lo = mid + 1;
    362     } else if (compare < 0) {
    363       hi = mid - 1;
    364     } else {
    365       return &str_id;
    366     }
    367   }
    368   return nullptr;
    369 }
    370 
    371 const DexFile::TypeId* DexFile::FindTypeId(dex::StringIndex string_idx) const {
    372   int32_t lo = 0;
    373   int32_t hi = NumTypeIds() - 1;
    374   while (hi >= lo) {
    375     int32_t mid = (hi + lo) / 2;
    376     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid));
    377     if (string_idx > type_id.descriptor_idx_) {
    378       lo = mid + 1;
    379     } else if (string_idx < type_id.descriptor_idx_) {
    380       hi = mid - 1;
    381     } else {
    382       return &type_id;
    383     }
    384   }
    385   return nullptr;
    386 }
    387 
    388 const DexFile::ProtoId* DexFile::FindProtoId(dex::TypeIndex return_type_idx,
    389                                              const dex::TypeIndex* signature_type_idxs,
    390                                              uint32_t signature_length) const {
    391   int32_t lo = 0;
    392   int32_t hi = NumProtoIds() - 1;
    393   while (hi >= lo) {
    394     int32_t mid = (hi + lo) / 2;
    395     const DexFile::ProtoId& proto = GetProtoId(mid);
    396     int compare = return_type_idx.index_ - proto.return_type_idx_.index_;
    397     if (compare == 0) {
    398       DexFileParameterIterator it(*this, proto);
    399       size_t i = 0;
    400       while (it.HasNext() && i < signature_length && compare == 0) {
    401         compare = signature_type_idxs[i].index_ - it.GetTypeIdx().index_;
    402         it.Next();
    403         i++;
    404       }
    405       if (compare == 0) {
    406         if (it.HasNext()) {
    407           compare = -1;
    408         } else if (i < signature_length) {
    409           compare = 1;
    410         }
    411       }
    412     }
    413     if (compare > 0) {
    414       lo = mid + 1;
    415     } else if (compare < 0) {
    416       hi = mid - 1;
    417     } else {
    418       return &proto;
    419     }
    420   }
    421   return nullptr;
    422 }
    423 
    424 // Given a signature place the type ids into the given vector
    425 bool DexFile::CreateTypeList(const StringPiece& signature,
    426                              dex::TypeIndex* return_type_idx,
    427                              std::vector<dex::TypeIndex>* param_type_idxs) const {
    428   if (signature[0] != '(') {
    429     return false;
    430   }
    431   size_t offset = 1;
    432   size_t end = signature.size();
    433   bool process_return = false;
    434   while (offset < end) {
    435     size_t start_offset = offset;
    436     char c = signature[offset];
    437     offset++;
    438     if (c == ')') {
    439       process_return = true;
    440       continue;
    441     }
    442     while (c == '[') {  // process array prefix
    443       if (offset >= end) {  // expect some descriptor following [
    444         return false;
    445       }
    446       c = signature[offset];
    447       offset++;
    448     }
    449     if (c == 'L') {  // process type descriptors
    450       do {
    451         if (offset >= end) {  // unexpected early termination of descriptor
    452           return false;
    453         }
    454         c = signature[offset];
    455         offset++;
    456       } while (c != ';');
    457     }
    458     // TODO: avoid creating a std::string just to get a 0-terminated char array
    459     std::string descriptor(signature.data() + start_offset, offset - start_offset);
    460     const DexFile::TypeId* type_id = FindTypeId(descriptor.c_str());
    461     if (type_id == nullptr) {
    462       return false;
    463     }
    464     dex::TypeIndex type_idx = GetIndexForTypeId(*type_id);
    465     if (!process_return) {
    466       param_type_idxs->push_back(type_idx);
    467     } else {
    468       *return_type_idx = type_idx;
    469       return offset == end;  // return true if the signature had reached a sensible end
    470     }
    471   }
    472   return false;  // failed to correctly parse return type
    473 }
    474 
    475 const Signature DexFile::CreateSignature(const StringPiece& signature) const {
    476   dex::TypeIndex return_type_idx;
    477   std::vector<dex::TypeIndex> param_type_indices;
    478   bool success = CreateTypeList(signature, &return_type_idx, &param_type_indices);
    479   if (!success) {
    480     return Signature::NoSignature();
    481   }
    482   const ProtoId* proto_id = FindProtoId(return_type_idx, param_type_indices);
    483   if (proto_id == nullptr) {
    484     return Signature::NoSignature();
    485   }
    486   return Signature(this, *proto_id);
    487 }
    488 
    489 int32_t DexFile::FindTryItem(const TryItem* try_items, uint32_t tries_size, uint32_t address) {
    490   uint32_t min = 0;
    491   uint32_t max = tries_size;
    492   while (min < max) {
    493     const uint32_t mid = (min + max) / 2;
    494 
    495     const art::DexFile::TryItem& ti = try_items[mid];
    496     const uint32_t start = ti.start_addr_;
    497     const uint32_t end = start + ti.insn_count_;
    498 
    499     if (address < start) {
    500       max = mid;
    501     } else if (address >= end) {
    502       min = mid + 1;
    503     } else {  // We have a winner!
    504       return mid;
    505     }
    506   }
    507   // No match.
    508   return -1;
    509 }
    510 
    511 bool DexFile::LineNumForPcCb(void* raw_context, const PositionInfo& entry) {
    512   LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
    513 
    514   // We know that this callback will be called in
    515   // ascending address order, so keep going until we find
    516   // a match or we've just gone past it.
    517   if (entry.address_ > context->address_) {
    518     // The line number from the previous positions callback
    519     // wil be the final result.
    520     return true;
    521   } else {
    522     context->line_num_ = entry.line_;
    523     return entry.address_ == context->address_;
    524   }
    525 }
    526 
    527 // Read a signed integer.  "zwidth" is the zero-based byte count.
    528 int32_t DexFile::ReadSignedInt(const uint8_t* ptr, int zwidth) {
    529   int32_t val = 0;
    530   for (int i = zwidth; i >= 0; --i) {
    531     val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
    532   }
    533   val >>= (3 - zwidth) * 8;
    534   return val;
    535 }
    536 
    537 // Read an unsigned integer.  "zwidth" is the zero-based byte count,
    538 // "fill_on_right" indicates which side we want to zero-fill from.
    539 uint32_t DexFile::ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) {
    540   uint32_t val = 0;
    541   for (int i = zwidth; i >= 0; --i) {
    542     val = (val >> 8) | (((uint32_t)*ptr++) << 24);
    543   }
    544   if (!fill_on_right) {
    545     val >>= (3 - zwidth) * 8;
    546   }
    547   return val;
    548 }
    549 
    550 // Read a signed long.  "zwidth" is the zero-based byte count.
    551 int64_t DexFile::ReadSignedLong(const uint8_t* ptr, int zwidth) {
    552   int64_t val = 0;
    553   for (int i = zwidth; i >= 0; --i) {
    554     val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
    555   }
    556   val >>= (7 - zwidth) * 8;
    557   return val;
    558 }
    559 
    560 // Read an unsigned long.  "zwidth" is the zero-based byte count,
    561 // "fill_on_right" indicates which side we want to zero-fill from.
    562 uint64_t DexFile::ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) {
    563   uint64_t val = 0;
    564   for (int i = zwidth; i >= 0; --i) {
    565     val = (val >> 8) | (((uint64_t)*ptr++) << 56);
    566   }
    567   if (!fill_on_right) {
    568     val >>= (7 - zwidth) * 8;
    569   }
    570   return val;
    571 }
    572 
    573 std::string DexFile::PrettyMethod(uint32_t method_idx, bool with_signature) const {
    574   if (method_idx >= NumMethodIds()) {
    575     return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
    576   }
    577   const DexFile::MethodId& method_id = GetMethodId(method_idx);
    578   std::string result;
    579   const DexFile::ProtoId* proto_id = with_signature ? &GetProtoId(method_id.proto_idx_) : nullptr;
    580   if (with_signature) {
    581     AppendPrettyDescriptor(StringByTypeIdx(proto_id->return_type_idx_), &result);
    582     result += ' ';
    583   }
    584   AppendPrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id), &result);
    585   result += '.';
    586   result += GetMethodName(method_id);
    587   if (with_signature) {
    588     result += '(';
    589     const DexFile::TypeList* params = GetProtoParameters(*proto_id);
    590     if (params != nullptr) {
    591       const char* separator = "";
    592       for (uint32_t i = 0u, size = params->Size(); i != size; ++i) {
    593         result += separator;
    594         separator = ", ";
    595         AppendPrettyDescriptor(StringByTypeIdx(params->GetTypeItem(i).type_idx_), &result);
    596       }
    597     }
    598     result += ')';
    599   }
    600   return result;
    601 }
    602 
    603 std::string DexFile::PrettyField(uint32_t field_idx, bool with_type) const {
    604   if (field_idx >= NumFieldIds()) {
    605     return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
    606   }
    607   const DexFile::FieldId& field_id = GetFieldId(field_idx);
    608   std::string result;
    609   if (with_type) {
    610     result += GetFieldTypeDescriptor(field_id);
    611     result += ' ';
    612   }
    613   AppendPrettyDescriptor(GetFieldDeclaringClassDescriptor(field_id), &result);
    614   result += '.';
    615   result += GetFieldName(field_id);
    616   return result;
    617 }
    618 
    619 std::string DexFile::PrettyType(dex::TypeIndex type_idx) const {
    620   if (type_idx.index_ >= NumTypeIds()) {
    621     return StringPrintf("<<invalid-type-idx-%d>>", type_idx.index_);
    622   }
    623   const DexFile::TypeId& type_id = GetTypeId(type_idx);
    624   return PrettyDescriptor(GetTypeDescriptor(type_id));
    625 }
    626 
    627 // Checks that visibility is as expected. Includes special behavior for M and
    628 // before to allow runtime and build visibility when expecting runtime.
    629 std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) {
    630   os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]",
    631                      dex_file.GetLocation().c_str(),
    632                      dex_file.GetHeader().checksum_, dex_file.GetLocationChecksum(),
    633                      dex_file.Begin(), dex_file.Begin() + dex_file.Size());
    634   return os;
    635 }
    636 
    637 std::string Signature::ToString() const {
    638   if (dex_file_ == nullptr) {
    639     CHECK(proto_id_ == nullptr);
    640     return "<no signature>";
    641   }
    642   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
    643   std::string result;
    644   if (params == nullptr) {
    645     result += "()";
    646   } else {
    647     result += "(";
    648     for (uint32_t i = 0; i < params->Size(); ++i) {
    649       result += dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_);
    650     }
    651     result += ")";
    652   }
    653   result += dex_file_->StringByTypeIdx(proto_id_->return_type_idx_);
    654   return result;
    655 }
    656 
    657 uint32_t Signature::GetNumberOfParameters() const {
    658   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
    659   return (params != nullptr) ? params->Size() : 0;
    660 }
    661 
    662 bool Signature::IsVoid() const {
    663   const char* return_type = dex_file_->GetReturnTypeDescriptor(*proto_id_);
    664   return strcmp(return_type, "V") == 0;
    665 }
    666 
    667 bool Signature::operator==(const StringPiece& rhs) const {
    668   if (dex_file_ == nullptr) {
    669     return false;
    670   }
    671   StringPiece tail(rhs);
    672   if (!tail.starts_with("(")) {
    673     return false;  // Invalid signature
    674   }
    675   tail.remove_prefix(1);  // "(";
    676   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
    677   if (params != nullptr) {
    678     for (uint32_t i = 0; i < params->Size(); ++i) {
    679       StringPiece param(dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_));
    680       if (!tail.starts_with(param)) {
    681         return false;
    682       }
    683       tail.remove_prefix(param.length());
    684     }
    685   }
    686   if (!tail.starts_with(")")) {
    687     return false;
    688   }
    689   tail.remove_prefix(1);  // ")";
    690   return tail == dex_file_->StringByTypeIdx(proto_id_->return_type_idx_);
    691 }
    692 
    693 std::ostream& operator<<(std::ostream& os, const Signature& sig) {
    694   return os << sig.ToString();
    695 }
    696 
    697 // Decodes the header section from the class data bytes.
    698 void ClassDataItemIterator::ReadClassDataHeader() {
    699   CHECK(ptr_pos_ != nullptr);
    700   header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
    701   header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
    702   header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
    703   header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
    704 }
    705 
    706 void ClassDataItemIterator::ReadClassDataField() {
    707   field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
    708   field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
    709   // The user of the iterator is responsible for checking if there
    710   // are unordered or duplicate indexes.
    711 }
    712 
    713 void ClassDataItemIterator::ReadClassDataMethod() {
    714   method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
    715   method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
    716   method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
    717   if (last_idx_ != 0 && method_.method_idx_delta_ == 0) {
    718     LOG(WARNING) << "Duplicate method in " << dex_file_.GetLocation();
    719   }
    720 }
    721 
    722 EncodedArrayValueIterator::EncodedArrayValueIterator(const DexFile& dex_file,
    723                                                      const uint8_t* array_data)
    724     : dex_file_(dex_file),
    725       array_size_(),
    726       pos_(-1),
    727       ptr_(array_data),
    728       type_(kByte) {
    729   array_size_ = (ptr_ != nullptr) ? DecodeUnsignedLeb128(&ptr_) : 0;
    730   if (array_size_ > 0) {
    731     Next();
    732   }
    733 }
    734 
    735 void EncodedArrayValueIterator::Next() {
    736   pos_++;
    737   if (pos_ >= array_size_) {
    738     return;
    739   }
    740   uint8_t value_type = *ptr_++;
    741   uint8_t value_arg = value_type >> kEncodedValueArgShift;
    742   size_t width = value_arg + 1;  // assume and correct later
    743   type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
    744   switch (type_) {
    745   case kBoolean:
    746     jval_.i = (value_arg != 0) ? 1 : 0;
    747     width = 0;
    748     break;
    749   case kByte:
    750     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
    751     CHECK(IsInt<8>(jval_.i));
    752     break;
    753   case kShort:
    754     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
    755     CHECK(IsInt<16>(jval_.i));
    756     break;
    757   case kChar:
    758     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
    759     CHECK(IsUint<16>(jval_.i));
    760     break;
    761   case kInt:
    762     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
    763     break;
    764   case kLong:
    765     jval_.j = DexFile::ReadSignedLong(ptr_, value_arg);
    766     break;
    767   case kFloat:
    768     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true);
    769     break;
    770   case kDouble:
    771     jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true);
    772     break;
    773   case kString:
    774   case kType:
    775   case kMethodType:
    776   case kMethodHandle:
    777     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
    778     break;
    779   case kField:
    780   case kMethod:
    781   case kEnum:
    782   case kArray:
    783   case kAnnotation:
    784     UNIMPLEMENTED(FATAL) << ": type " << type_;
    785     UNREACHABLE();
    786   case kNull:
    787     jval_.l = nullptr;
    788     width = 0;
    789     break;
    790   default:
    791     LOG(FATAL) << "Unreached";
    792     UNREACHABLE();
    793   }
    794   ptr_ += width;
    795 }
    796 
    797 namespace dex {
    798 
    799 std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
    800   os << "StringIndex[" << index.index_ << "]";
    801   return os;
    802 }
    803 
    804 std::ostream& operator<<(std::ostream& os, const TypeIndex& index) {
    805   os << "TypeIndex[" << index.index_ << "]";
    806   return os;
    807 }
    808 
    809 }  // namespace dex
    810 
    811 }  // namespace art
    812