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, ¶m_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