dex_file.cc revision 07b3c2351bb527ea91c084dc19434600af9ae66b
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 <fcntl.h> 20#include <limits.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <sys/file.h> 25#include <sys/stat.h> 26 27#include <memory> 28#include <sstream> 29 30#include "base/logging.h" 31#include "base/stringprintf.h" 32#include "class_linker.h" 33#include "dex_file-inl.h" 34#include "dex_file_verifier.h" 35#include "globals.h" 36#include "leb128.h" 37#include "mirror/art_field-inl.h" 38#include "mirror/art_method-inl.h" 39#include "mirror/string.h" 40#include "os.h" 41#include "safe_map.h" 42#include "handle_scope-inl.h" 43#include "thread.h" 44#include "utf-inl.h" 45#include "utils.h" 46#include "well_known_classes.h" 47#include "zip_archive.h" 48 49#pragma GCC diagnostic push 50#pragma GCC diagnostic ignored "-Wshadow" 51#include "ScopedFd.h" 52#pragma GCC diagnostic pop 53 54namespace art { 55 56const uint8_t DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' }; 57const uint8_t DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' }; 58 59static int OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_msg) { 60 CHECK(magic != NULL); 61 ScopedFd fd(open(filename, O_RDONLY, 0)); 62 if (fd.get() == -1) { 63 *error_msg = StringPrintf("Unable to open '%s' : %s", filename, strerror(errno)); 64 return -1; 65 } 66 int n = TEMP_FAILURE_RETRY(read(fd.get(), magic, sizeof(*magic))); 67 if (n != sizeof(*magic)) { 68 *error_msg = StringPrintf("Failed to find magic in '%s'", filename); 69 return -1; 70 } 71 if (lseek(fd.get(), 0, SEEK_SET) != 0) { 72 *error_msg = StringPrintf("Failed to seek to beginning of file '%s' : %s", filename, 73 strerror(errno)); 74 return -1; 75 } 76 return fd.release(); 77} 78 79bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg) { 80 CHECK(checksum != NULL); 81 uint32_t magic; 82 83 // Strip ":...", which is the location 84 const char* zip_entry_name = kClassesDex; 85 const char* file_part = filename; 86 std::string file_part_storage; 87 88 if (DexFile::IsMultiDexLocation(filename)) { 89 file_part_storage = GetBaseLocation(filename); 90 file_part = file_part_storage.c_str(); 91 zip_entry_name = filename + file_part_storage.size() + 1; 92 DCHECK_EQ(zip_entry_name[-1], kMultiDexSeparator); 93 } 94 95 ScopedFd fd(OpenAndReadMagic(file_part, &magic, error_msg)); 96 if (fd.get() == -1) { 97 DCHECK(!error_msg->empty()); 98 return false; 99 } 100 if (IsZipMagic(magic)) { 101 std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd.release(), filename, error_msg)); 102 if (zip_archive.get() == NULL) { 103 *error_msg = StringPrintf("Failed to open zip archive '%s' (error msg: %s)", file_part, 104 error_msg->c_str()); 105 return false; 106 } 107 std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name, error_msg)); 108 if (zip_entry.get() == NULL) { 109 *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", file_part, 110 zip_entry_name, error_msg->c_str()); 111 return false; 112 } 113 *checksum = zip_entry->GetCrc32(); 114 return true; 115 } 116 if (IsDexMagic(magic)) { 117 std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), filename, false, error_msg)); 118 if (dex_file.get() == NULL) { 119 return false; 120 } 121 *checksum = dex_file->GetHeader().checksum_; 122 return true; 123 } 124 *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename); 125 return false; 126} 127 128bool DexFile::Open(const char* filename, const char* location, std::string* error_msg, 129 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 130 DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is NULL"; 131 uint32_t magic; 132 ScopedFd fd(OpenAndReadMagic(filename, &magic, error_msg)); 133 if (fd.get() == -1) { 134 DCHECK(!error_msg->empty()); 135 return false; 136 } 137 if (IsZipMagic(magic)) { 138 return DexFile::OpenZip(fd.release(), location, error_msg, dex_files); 139 } 140 if (IsDexMagic(magic)) { 141 std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), location, true, 142 error_msg)); 143 if (dex_file.get() != nullptr) { 144 dex_files->push_back(std::move(dex_file)); 145 return true; 146 } else { 147 return false; 148 } 149 } 150 *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename); 151 return false; 152} 153 154int DexFile::GetPermissions() const { 155 if (mem_map_.get() == NULL) { 156 return 0; 157 } else { 158 return mem_map_->GetProtect(); 159 } 160} 161 162bool DexFile::IsReadOnly() const { 163 return GetPermissions() == PROT_READ; 164} 165 166bool DexFile::EnableWrite() const { 167 CHECK(IsReadOnly()); 168 if (mem_map_.get() == NULL) { 169 return false; 170 } else { 171 return mem_map_->Protect(PROT_READ | PROT_WRITE); 172 } 173} 174 175bool DexFile::DisableWrite() const { 176 CHECK(!IsReadOnly()); 177 if (mem_map_.get() == NULL) { 178 return false; 179 } else { 180 return mem_map_->Protect(PROT_READ); 181 } 182} 183 184std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const char* location, bool verify, 185 std::string* error_msg) { 186 CHECK(location != nullptr); 187 std::unique_ptr<MemMap> map; 188 { 189 ScopedFd delayed_close(fd); 190 struct stat sbuf; 191 memset(&sbuf, 0, sizeof(sbuf)); 192 if (fstat(fd, &sbuf) == -1) { 193 *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location, strerror(errno)); 194 return nullptr; 195 } 196 if (S_ISDIR(sbuf.st_mode)) { 197 *error_msg = StringPrintf("Attempt to mmap directory '%s'", location); 198 return nullptr; 199 } 200 size_t length = sbuf.st_size; 201 map.reset(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0, location, error_msg)); 202 if (map.get() == nullptr) { 203 DCHECK(!error_msg->empty()); 204 return nullptr; 205 } 206 } 207 208 if (map->Size() < sizeof(DexFile::Header)) { 209 *error_msg = StringPrintf( 210 "DexFile: failed to open dex file '%s' that is too short to have a header", location); 211 return nullptr; 212 } 213 214 const Header* dex_header = reinterpret_cast<const Header*>(map->Begin()); 215 216 std::unique_ptr<const DexFile> dex_file(OpenMemory(location, dex_header->checksum_, map.release(), 217 error_msg)); 218 if (dex_file.get() == nullptr) { 219 *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location, 220 error_msg->c_str()); 221 return nullptr; 222 } 223 224 if (verify && !DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(), 225 location, error_msg)) { 226 return nullptr; 227 } 228 229 return dex_file; 230} 231 232const char* DexFile::kClassesDex = "classes.dex"; 233 234bool DexFile::OpenZip(int fd, const std::string& location, std::string* error_msg, 235 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 236 DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is NULL"; 237 std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg)); 238 if (zip_archive.get() == nullptr) { 239 DCHECK(!error_msg->empty()); 240 return false; 241 } 242 return DexFile::OpenFromZip(*zip_archive, location, error_msg, dex_files); 243} 244 245std::unique_ptr<const DexFile> DexFile::OpenMemory(const std::string& location, 246 uint32_t location_checksum, 247 MemMap* mem_map, 248 std::string* error_msg) { 249 return OpenMemory(mem_map->Begin(), 250 mem_map->Size(), 251 location, 252 location_checksum, 253 mem_map, 254 nullptr, 255 error_msg); 256} 257 258std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, const char* entry_name, 259 const std::string& location, std::string* error_msg, 260 ZipOpenErrorCode* error_code) { 261 CHECK(!location.empty()); 262 std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg)); 263 if (zip_entry.get() == NULL) { 264 *error_code = ZipOpenErrorCode::kEntryNotFound; 265 return nullptr; 266 } 267 std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg)); 268 if (map.get() == NULL) { 269 *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(), 270 error_msg->c_str()); 271 *error_code = ZipOpenErrorCode::kExtractToMemoryError; 272 return nullptr; 273 } 274 std::unique_ptr<const DexFile> dex_file(OpenMemory(location, zip_entry->GetCrc32(), map.release(), 275 error_msg)); 276 if (dex_file.get() == nullptr) { 277 *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(), 278 error_msg->c_str()); 279 *error_code = ZipOpenErrorCode::kDexFileError; 280 return nullptr; 281 } 282 if (!dex_file->DisableWrite()) { 283 *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str()); 284 *error_code = ZipOpenErrorCode::kMakeReadOnlyError; 285 return nullptr; 286 } 287 CHECK(dex_file->IsReadOnly()) << location; 288 if (!DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(), 289 location.c_str(), error_msg)) { 290 *error_code = ZipOpenErrorCode::kVerifyError; 291 return nullptr; 292 } 293 *error_code = ZipOpenErrorCode::kNoError; 294 return dex_file; 295} 296 297bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& location, 298 std::string* error_msg, 299 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 300 DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is NULL"; 301 ZipOpenErrorCode error_code; 302 std::unique_ptr<const DexFile> dex_file(Open(zip_archive, kClassesDex, location, error_msg, 303 &error_code)); 304 if (dex_file.get() == nullptr) { 305 return false; 306 } else { 307 // Had at least classes.dex. 308 dex_files->push_back(std::move(dex_file)); 309 310 // Now try some more. 311 size_t i = 2; 312 313 // We could try to avoid std::string allocations by working on a char array directly. As we 314 // do not expect a lot of iterations, this seems too involved and brittle. 315 316 while (i < 100) { 317 std::string name = StringPrintf("classes%zu.dex", i); 318 std::string fake_location = location + kMultiDexSeparator + name; 319 std::unique_ptr<const DexFile> next_dex_file(Open(zip_archive, name.c_str(), fake_location, 320 error_msg, &error_code)); 321 if (next_dex_file.get() == nullptr) { 322 if (error_code != ZipOpenErrorCode::kEntryNotFound) { 323 LOG(WARNING) << error_msg; 324 } 325 break; 326 } else { 327 dex_files->push_back(std::move(next_dex_file)); 328 } 329 330 i++; 331 } 332 333 return true; 334 } 335} 336 337 338std::unique_ptr<const DexFile> DexFile::OpenMemory(const uint8_t* base, 339 size_t size, 340 const std::string& location, 341 uint32_t location_checksum, 342 MemMap* mem_map, 343 const OatDexFile* oat_dex_file, 344 std::string* error_msg) { 345 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned 346 std::unique_ptr<DexFile> dex_file( 347 new DexFile(base, size, location, location_checksum, mem_map, oat_dex_file)); 348 if (!dex_file->Init(error_msg)) { 349 dex_file.reset(); 350 } 351 return std::unique_ptr<const DexFile>(dex_file.release()); 352} 353 354DexFile::DexFile(const uint8_t* base, size_t size, 355 const std::string& location, 356 uint32_t location_checksum, 357 MemMap* mem_map, 358 const OatDexFile* oat_dex_file) 359 : begin_(base), 360 size_(size), 361 location_(location), 362 location_checksum_(location_checksum), 363 mem_map_(mem_map), 364 header_(reinterpret_cast<const Header*>(base)), 365 string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)), 366 type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)), 367 field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)), 368 method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)), 369 proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)), 370 class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)), 371 find_class_def_misses_(0), 372 class_def_index_(nullptr), 373 oat_dex_file_(oat_dex_file) { 374 CHECK(begin_ != NULL) << GetLocation(); 375 CHECK_GT(size_, 0U) << GetLocation(); 376} 377 378DexFile::~DexFile() { 379 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and 380 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could 381 // re-attach, but cleaning up these global references is not obviously useful. It's not as if 382 // the global reference table is otherwise empty! 383 // Remove the index if one were created. 384 delete class_def_index_.LoadRelaxed(); 385} 386 387bool DexFile::Init(std::string* error_msg) { 388 if (!CheckMagicAndVersion(error_msg)) { 389 return false; 390 } 391 return true; 392} 393 394bool DexFile::CheckMagicAndVersion(std::string* error_msg) const { 395 if (!IsMagicValid(header_->magic_)) { 396 std::ostringstream oss; 397 oss << "Unrecognized magic number in " << GetLocation() << ":" 398 << " " << header_->magic_[0] 399 << " " << header_->magic_[1] 400 << " " << header_->magic_[2] 401 << " " << header_->magic_[3]; 402 *error_msg = oss.str(); 403 return false; 404 } 405 if (!IsVersionValid(header_->magic_)) { 406 std::ostringstream oss; 407 oss << "Unrecognized version number in " << GetLocation() << ":" 408 << " " << header_->magic_[4] 409 << " " << header_->magic_[5] 410 << " " << header_->magic_[6] 411 << " " << header_->magic_[7]; 412 *error_msg = oss.str(); 413 return false; 414 } 415 return true; 416} 417 418bool DexFile::IsMagicValid(const uint8_t* magic) { 419 return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0); 420} 421 422bool DexFile::IsVersionValid(const uint8_t* magic) { 423 const uint8_t* version = &magic[sizeof(kDexMagic)]; 424 return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0); 425} 426 427uint32_t DexFile::GetVersion() const { 428 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]); 429 return atoi(version); 430} 431 432const DexFile::ClassDef* DexFile::FindClassDef(const char* descriptor, size_t hash) const { 433 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash); 434 // If we have an index lookup the descriptor via that as its constant time to search. 435 Index* index = class_def_index_.LoadSequentiallyConsistent(); 436 if (index != nullptr) { 437 auto it = index->FindWithHash(descriptor, hash); 438 return (it == index->end()) ? nullptr : it->second; 439 } 440 // Fast path for rate no class defs case. 441 uint32_t num_class_defs = NumClassDefs(); 442 if (num_class_defs == 0) { 443 return nullptr; 444 } 445 // Search for class def with 2 binary searches and then a linear search. 446 const StringId* string_id = FindStringId(descriptor); 447 if (string_id != nullptr) { 448 const TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id)); 449 if (type_id != nullptr) { 450 uint16_t type_idx = GetIndexForTypeId(*type_id); 451 for (size_t i = 0; i < num_class_defs; ++i) { 452 const ClassDef& class_def = GetClassDef(i); 453 if (class_def.class_idx_ == type_idx) { 454 return &class_def; 455 } 456 } 457 } 458 } 459 // A miss. If we've had kMaxFailedDexClassDefLookups misses then build an index to speed things 460 // up. This isn't done eagerly at construction as construction is not performed in multi-threaded 461 // sections of tools like dex2oat. If we're lazy we hopefully increase the chance of balancing 462 // out which thread builds the index. 463 const uint32_t kMaxFailedDexClassDefLookups = 100; 464 uint32_t old_misses = find_class_def_misses_.FetchAndAddSequentiallyConsistent(1); 465 if (old_misses == kMaxFailedDexClassDefLookups) { 466 // Are we the ones moving the miss count past the max? Sanity check the index doesn't exist. 467 CHECK(class_def_index_.LoadSequentiallyConsistent() == nullptr); 468 // Build the index. 469 index = new Index(); 470 for (uint32_t i = 0; i < num_class_defs; ++i) { 471 const ClassDef& class_def = GetClassDef(i); 472 const char* class_descriptor = GetClassDescriptor(class_def); 473 index->Insert(std::make_pair(class_descriptor, &class_def)); 474 } 475 // Sanity check the index still doesn't exist, only 1 thread should build it. 476 CHECK(class_def_index_.LoadSequentiallyConsistent() == nullptr); 477 class_def_index_.StoreSequentiallyConsistent(index); 478 } 479 return nullptr; 480} 481 482const DexFile::ClassDef* DexFile::FindClassDef(uint16_t type_idx) const { 483 size_t num_class_defs = NumClassDefs(); 484 for (size_t i = 0; i < num_class_defs; ++i) { 485 const ClassDef& class_def = GetClassDef(i); 486 if (class_def.class_idx_ == type_idx) { 487 return &class_def; 488 } 489 } 490 return NULL; 491} 492 493const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass, 494 const DexFile::StringId& name, 495 const DexFile::TypeId& type) const { 496 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx 497 const uint16_t class_idx = GetIndexForTypeId(declaring_klass); 498 const uint32_t name_idx = GetIndexForStringId(name); 499 const uint16_t type_idx = GetIndexForTypeId(type); 500 int32_t lo = 0; 501 int32_t hi = NumFieldIds() - 1; 502 while (hi >= lo) { 503 int32_t mid = (hi + lo) / 2; 504 const DexFile::FieldId& field = GetFieldId(mid); 505 if (class_idx > field.class_idx_) { 506 lo = mid + 1; 507 } else if (class_idx < field.class_idx_) { 508 hi = mid - 1; 509 } else { 510 if (name_idx > field.name_idx_) { 511 lo = mid + 1; 512 } else if (name_idx < field.name_idx_) { 513 hi = mid - 1; 514 } else { 515 if (type_idx > field.type_idx_) { 516 lo = mid + 1; 517 } else if (type_idx < field.type_idx_) { 518 hi = mid - 1; 519 } else { 520 return &field; 521 } 522 } 523 } 524 } 525 return NULL; 526} 527 528const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass, 529 const DexFile::StringId& name, 530 const DexFile::ProtoId& signature) const { 531 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx 532 const uint16_t class_idx = GetIndexForTypeId(declaring_klass); 533 const uint32_t name_idx = GetIndexForStringId(name); 534 const uint16_t proto_idx = GetIndexForProtoId(signature); 535 int32_t lo = 0; 536 int32_t hi = NumMethodIds() - 1; 537 while (hi >= lo) { 538 int32_t mid = (hi + lo) / 2; 539 const DexFile::MethodId& method = GetMethodId(mid); 540 if (class_idx > method.class_idx_) { 541 lo = mid + 1; 542 } else if (class_idx < method.class_idx_) { 543 hi = mid - 1; 544 } else { 545 if (name_idx > method.name_idx_) { 546 lo = mid + 1; 547 } else if (name_idx < method.name_idx_) { 548 hi = mid - 1; 549 } else { 550 if (proto_idx > method.proto_idx_) { 551 lo = mid + 1; 552 } else if (proto_idx < method.proto_idx_) { 553 hi = mid - 1; 554 } else { 555 return &method; 556 } 557 } 558 } 559 } 560 return NULL; 561} 562 563const DexFile::StringId* DexFile::FindStringId(const char* string) const { 564 int32_t lo = 0; 565 int32_t hi = NumStringIds() - 1; 566 while (hi >= lo) { 567 int32_t mid = (hi + lo) / 2; 568 const DexFile::StringId& str_id = GetStringId(mid); 569 const char* str = GetStringData(str_id); 570 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str); 571 if (compare > 0) { 572 lo = mid + 1; 573 } else if (compare < 0) { 574 hi = mid - 1; 575 } else { 576 return &str_id; 577 } 578 } 579 return NULL; 580} 581 582const DexFile::StringId* DexFile::FindStringId(const uint16_t* string, size_t length) const { 583 int32_t lo = 0; 584 int32_t hi = NumStringIds() - 1; 585 while (hi >= lo) { 586 int32_t mid = (hi + lo) / 2; 587 const DexFile::StringId& str_id = GetStringId(mid); 588 const char* str = GetStringData(str_id); 589 int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string, length); 590 if (compare > 0) { 591 lo = mid + 1; 592 } else if (compare < 0) { 593 hi = mid - 1; 594 } else { 595 return &str_id; 596 } 597 } 598 return NULL; 599} 600 601const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const { 602 int32_t lo = 0; 603 int32_t hi = NumTypeIds() - 1; 604 while (hi >= lo) { 605 int32_t mid = (hi + lo) / 2; 606 const TypeId& type_id = GetTypeId(mid); 607 if (string_idx > type_id.descriptor_idx_) { 608 lo = mid + 1; 609 } else if (string_idx < type_id.descriptor_idx_) { 610 hi = mid - 1; 611 } else { 612 return &type_id; 613 } 614 } 615 return NULL; 616} 617 618const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx, 619 const uint16_t* signature_type_idxs, 620 uint32_t signature_length) const { 621 int32_t lo = 0; 622 int32_t hi = NumProtoIds() - 1; 623 while (hi >= lo) { 624 int32_t mid = (hi + lo) / 2; 625 const DexFile::ProtoId& proto = GetProtoId(mid); 626 int compare = return_type_idx - proto.return_type_idx_; 627 if (compare == 0) { 628 DexFileParameterIterator it(*this, proto); 629 size_t i = 0; 630 while (it.HasNext() && i < signature_length && compare == 0) { 631 compare = signature_type_idxs[i] - it.GetTypeIdx(); 632 it.Next(); 633 i++; 634 } 635 if (compare == 0) { 636 if (it.HasNext()) { 637 compare = -1; 638 } else if (i < signature_length) { 639 compare = 1; 640 } 641 } 642 } 643 if (compare > 0) { 644 lo = mid + 1; 645 } else if (compare < 0) { 646 hi = mid - 1; 647 } else { 648 return &proto; 649 } 650 } 651 return NULL; 652} 653 654// Given a signature place the type ids into the given vector 655bool DexFile::CreateTypeList(const StringPiece& signature, uint16_t* return_type_idx, 656 std::vector<uint16_t>* param_type_idxs) const { 657 if (signature[0] != '(') { 658 return false; 659 } 660 size_t offset = 1; 661 size_t end = signature.size(); 662 bool process_return = false; 663 while (offset < end) { 664 size_t start_offset = offset; 665 char c = signature[offset]; 666 offset++; 667 if (c == ')') { 668 process_return = true; 669 continue; 670 } 671 while (c == '[') { // process array prefix 672 if (offset >= end) { // expect some descriptor following [ 673 return false; 674 } 675 c = signature[offset]; 676 offset++; 677 } 678 if (c == 'L') { // process type descriptors 679 do { 680 if (offset >= end) { // unexpected early termination of descriptor 681 return false; 682 } 683 c = signature[offset]; 684 offset++; 685 } while (c != ';'); 686 } 687 // TODO: avoid creating a std::string just to get a 0-terminated char array 688 std::string descriptor(signature.data() + start_offset, offset - start_offset); 689 const DexFile::StringId* string_id = FindStringId(descriptor.c_str()); 690 if (string_id == NULL) { 691 return false; 692 } 693 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id)); 694 if (type_id == NULL) { 695 return false; 696 } 697 uint16_t type_idx = GetIndexForTypeId(*type_id); 698 if (!process_return) { 699 param_type_idxs->push_back(type_idx); 700 } else { 701 *return_type_idx = type_idx; 702 return offset == end; // return true if the signature had reached a sensible end 703 } 704 } 705 return false; // failed to correctly parse return type 706} 707 708const Signature DexFile::CreateSignature(const StringPiece& signature) const { 709 uint16_t return_type_idx; 710 std::vector<uint16_t> param_type_indices; 711 bool success = CreateTypeList(signature, &return_type_idx, ¶m_type_indices); 712 if (!success) { 713 return Signature::NoSignature(); 714 } 715 const ProtoId* proto_id = FindProtoId(return_type_idx, param_type_indices); 716 if (proto_id == NULL) { 717 return Signature::NoSignature(); 718 } 719 return Signature(this, *proto_id); 720} 721 722int32_t DexFile::GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const { 723 // For native method, lineno should be -2 to indicate it is native. Note that 724 // "line number == -2" is how libcore tells from StackTraceElement. 725 if (method->GetCodeItemOffset() == 0) { 726 return -2; 727 } 728 729 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset()); 730 DCHECK(code_item != NULL) << PrettyMethod(method) << " " << GetLocation(); 731 732 // A method with no line number info should return -1 733 LineNumFromPcContext context(rel_pc, -1); 734 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb, 735 NULL, &context); 736 return context.line_num_; 737} 738 739int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) { 740 // Note: Signed type is important for max and min. 741 int32_t min = 0; 742 int32_t max = code_item.tries_size_ - 1; 743 744 while (min <= max) { 745 int32_t mid = min + ((max - min) / 2); 746 747 const art::DexFile::TryItem* ti = GetTryItems(code_item, mid); 748 uint32_t start = ti->start_addr_; 749 uint32_t end = start + ti->insn_count_; 750 751 if (address < start) { 752 max = mid - 1; 753 } else if (address >= end) { 754 min = mid + 1; 755 } else { // We have a winner! 756 return mid; 757 } 758 } 759 // No match. 760 return -1; 761} 762 763int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, uint32_t address) { 764 int32_t try_item = FindTryItem(code_item, address); 765 if (try_item == -1) { 766 return -1; 767 } else { 768 return DexFile::GetTryItems(code_item, try_item)->handler_off_; 769 } 770} 771 772void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx, 773 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb, 774 void* context, const uint8_t* stream, LocalInfo* local_in_reg) const { 775 uint32_t line = DecodeUnsignedLeb128(&stream); 776 uint32_t parameters_size = DecodeUnsignedLeb128(&stream); 777 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_; 778 uint32_t address = 0; 779 bool need_locals = (local_cb != NULL); 780 781 if (!is_static) { 782 if (need_locals) { 783 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)); 784 local_in_reg[arg_reg].name_ = "this"; 785 local_in_reg[arg_reg].descriptor_ = descriptor; 786 local_in_reg[arg_reg].signature_ = NULL; 787 local_in_reg[arg_reg].start_address_ = 0; 788 local_in_reg[arg_reg].is_live_ = true; 789 } 790 arg_reg++; 791 } 792 793 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx))); 794 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) { 795 if (arg_reg >= code_item->registers_size_) { 796 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg 797 << " >= " << code_item->registers_size_ << ") in " << GetLocation(); 798 return; 799 } 800 uint32_t id = DecodeUnsignedLeb128P1(&stream); 801 const char* descriptor = it.GetDescriptor(); 802 if (need_locals && id != kDexNoIndex) { 803 const char* name = StringDataByIdx(id); 804 local_in_reg[arg_reg].name_ = name; 805 local_in_reg[arg_reg].descriptor_ = descriptor; 806 local_in_reg[arg_reg].signature_ = NULL; 807 local_in_reg[arg_reg].start_address_ = address; 808 local_in_reg[arg_reg].is_live_ = true; 809 } 810 switch (*descriptor) { 811 case 'D': 812 case 'J': 813 arg_reg += 2; 814 break; 815 default: 816 arg_reg += 1; 817 break; 818 } 819 } 820 821 if (it.HasNext()) { 822 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation() 823 << " for method " << PrettyMethod(method_idx, *this); 824 return; 825 } 826 827 for (;;) { 828 uint8_t opcode = *stream++; 829 uint16_t reg; 830 uint32_t name_idx; 831 uint32_t descriptor_idx; 832 uint32_t signature_idx = 0; 833 834 switch (opcode) { 835 case DBG_END_SEQUENCE: 836 return; 837 838 case DBG_ADVANCE_PC: 839 address += DecodeUnsignedLeb128(&stream); 840 break; 841 842 case DBG_ADVANCE_LINE: 843 line += DecodeSignedLeb128(&stream); 844 break; 845 846 case DBG_START_LOCAL: 847 case DBG_START_LOCAL_EXTENDED: 848 reg = DecodeUnsignedLeb128(&stream); 849 if (reg > code_item->registers_size_) { 850 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " 851 << code_item->registers_size_ << ") in " << GetLocation(); 852 return; 853 } 854 855 name_idx = DecodeUnsignedLeb128P1(&stream); 856 descriptor_idx = DecodeUnsignedLeb128P1(&stream); 857 if (opcode == DBG_START_LOCAL_EXTENDED) { 858 signature_idx = DecodeUnsignedLeb128P1(&stream); 859 } 860 861 // Emit what was previously there, if anything 862 if (need_locals) { 863 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb); 864 865 local_in_reg[reg].name_ = StringDataByIdx(name_idx); 866 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx); 867 if (opcode == DBG_START_LOCAL_EXTENDED) { 868 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx); 869 } 870 local_in_reg[reg].start_address_ = address; 871 local_in_reg[reg].is_live_ = true; 872 } 873 break; 874 875 case DBG_END_LOCAL: 876 reg = DecodeUnsignedLeb128(&stream); 877 if (reg > code_item->registers_size_) { 878 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " 879 << code_item->registers_size_ << ") in " << GetLocation(); 880 return; 881 } 882 883 if (need_locals) { 884 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb); 885 local_in_reg[reg].is_live_ = false; 886 } 887 break; 888 889 case DBG_RESTART_LOCAL: 890 reg = DecodeUnsignedLeb128(&stream); 891 if (reg > code_item->registers_size_) { 892 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " 893 << code_item->registers_size_ << ") in " << GetLocation(); 894 return; 895 } 896 897 if (need_locals) { 898 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) { 899 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation(); 900 return; 901 } 902 903 // If the register is live, the "restart" is superfluous, 904 // and we don't want to mess with the existing start address. 905 if (!local_in_reg[reg].is_live_) { 906 local_in_reg[reg].start_address_ = address; 907 local_in_reg[reg].is_live_ = true; 908 } 909 } 910 break; 911 912 case DBG_SET_PROLOGUE_END: 913 case DBG_SET_EPILOGUE_BEGIN: 914 case DBG_SET_FILE: 915 break; 916 917 default: { 918 int adjopcode = opcode - DBG_FIRST_SPECIAL; 919 920 address += adjopcode / DBG_LINE_RANGE; 921 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); 922 923 if (position_cb != NULL) { 924 if (position_cb(context, address, line)) { 925 // early exit 926 return; 927 } 928 } 929 break; 930 } 931 } 932 } 933} 934 935void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, 936 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb, 937 void* context) const { 938 DCHECK(code_item != nullptr); 939 const uint8_t* stream = GetDebugInfoStream(code_item); 940 std::unique_ptr<LocalInfo[]> local_in_reg(local_cb != NULL ? 941 new LocalInfo[code_item->registers_size_] : 942 NULL); 943 if (stream != NULL) { 944 DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]); 945 } 946 for (int reg = 0; reg < code_item->registers_size_; reg++) { 947 InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb); 948 } 949} 950 951bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) { 952 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context); 953 954 // We know that this callback will be called in 955 // ascending address order, so keep going until we find 956 // a match or we've just gone past it. 957 if (address > context->address_) { 958 // The line number from the previous positions callback 959 // wil be the final result. 960 return true; 961 } else { 962 context->line_num_ = line_num; 963 return address == context->address_; 964 } 965} 966 967bool DexFile::IsMultiDexLocation(const char* location) { 968 return strrchr(location, kMultiDexSeparator) != nullptr; 969} 970 971std::string DexFile::GetMultiDexClassesDexName(size_t number, const char* dex_location) { 972 if (number == 0) { 973 return dex_location; 974 } else { 975 return StringPrintf("%s" kMultiDexSeparatorString "classes%zu.dex", dex_location, number + 1); 976 } 977} 978 979std::string DexFile::GetDexCanonicalLocation(const char* dex_location) { 980 CHECK_NE(dex_location, static_cast<const char*>(nullptr)); 981 std::string base_location = GetBaseLocation(dex_location); 982 const char* suffix = dex_location + base_location.size(); 983 DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator); 984 UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr)); 985 if (path != nullptr && path.get() != base_location) { 986 return std::string(path.get()) + suffix; 987 } else if (suffix[0] == 0) { 988 return base_location; 989 } else { 990 return dex_location; 991 } 992} 993 994std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) { 995 os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]", 996 dex_file.GetLocation().c_str(), 997 dex_file.GetHeader().checksum_, dex_file.GetLocationChecksum(), 998 dex_file.Begin(), dex_file.Begin() + dex_file.Size()); 999 return os; 1000} 1001 1002std::string Signature::ToString() const { 1003 if (dex_file_ == nullptr) { 1004 CHECK(proto_id_ == nullptr); 1005 return "<no signature>"; 1006 } 1007 const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); 1008 std::string result; 1009 if (params == nullptr) { 1010 result += "()"; 1011 } else { 1012 result += "("; 1013 for (uint32_t i = 0; i < params->Size(); ++i) { 1014 result += dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_); 1015 } 1016 result += ")"; 1017 } 1018 result += dex_file_->StringByTypeIdx(proto_id_->return_type_idx_); 1019 return result; 1020} 1021 1022bool Signature::operator==(const StringPiece& rhs) const { 1023 if (dex_file_ == nullptr) { 1024 return false; 1025 } 1026 StringPiece tail(rhs); 1027 if (!tail.starts_with("(")) { 1028 return false; // Invalid signature 1029 } 1030 tail.remove_prefix(1); // "("; 1031 const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); 1032 if (params != nullptr) { 1033 for (uint32_t i = 0; i < params->Size(); ++i) { 1034 StringPiece param(dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_)); 1035 if (!tail.starts_with(param)) { 1036 return false; 1037 } 1038 tail.remove_prefix(param.length()); 1039 } 1040 } 1041 if (!tail.starts_with(")")) { 1042 return false; 1043 } 1044 tail.remove_prefix(1); // ")"; 1045 return tail == dex_file_->StringByTypeIdx(proto_id_->return_type_idx_); 1046} 1047 1048std::ostream& operator<<(std::ostream& os, const Signature& sig) { 1049 return os << sig.ToString(); 1050} 1051 1052// Decodes the header section from the class data bytes. 1053void ClassDataItemIterator::ReadClassDataHeader() { 1054 CHECK(ptr_pos_ != NULL); 1055 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); 1056 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); 1057 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); 1058 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); 1059} 1060 1061void ClassDataItemIterator::ReadClassDataField() { 1062 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); 1063 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); 1064 if (last_idx_ != 0 && field_.field_idx_delta_ == 0) { 1065 LOG(WARNING) << "Duplicate field in " << dex_file_.GetLocation(); 1066 } 1067} 1068 1069void ClassDataItemIterator::ReadClassDataMethod() { 1070 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); 1071 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); 1072 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_); 1073 if (last_idx_ != 0 && method_.method_idx_delta_ == 0) { 1074 LOG(WARNING) << "Duplicate method in " << dex_file_.GetLocation(); 1075 } 1076} 1077 1078// Read a signed integer. "zwidth" is the zero-based byte count. 1079static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) { 1080 int32_t val = 0; 1081 for (int i = zwidth; i >= 0; --i) { 1082 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); 1083 } 1084 val >>= (3 - zwidth) * 8; 1085 return val; 1086} 1087 1088// Read an unsigned integer. "zwidth" is the zero-based byte count, 1089// "fill_on_right" indicates which side we want to zero-fill from. 1090static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { 1091 uint32_t val = 0; 1092 if (!fill_on_right) { 1093 for (int i = zwidth; i >= 0; --i) { 1094 val = (val >> 8) | (((uint32_t)*ptr++) << 24); 1095 } 1096 val >>= (3 - zwidth) * 8; 1097 } else { 1098 for (int i = zwidth; i >= 0; --i) { 1099 val = (val >> 8) | (((uint32_t)*ptr++) << 24); 1100 } 1101 } 1102 return val; 1103} 1104 1105// Read a signed long. "zwidth" is the zero-based byte count. 1106static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) { 1107 int64_t val = 0; 1108 for (int i = zwidth; i >= 0; --i) { 1109 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); 1110 } 1111 val >>= (7 - zwidth) * 8; 1112 return val; 1113} 1114 1115// Read an unsigned long. "zwidth" is the zero-based byte count, 1116// "fill_on_right" indicates which side we want to zero-fill from. 1117static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { 1118 uint64_t val = 0; 1119 if (!fill_on_right) { 1120 for (int i = zwidth; i >= 0; --i) { 1121 val = (val >> 8) | (((uint64_t)*ptr++) << 56); 1122 } 1123 val >>= (7 - zwidth) * 8; 1124 } else { 1125 for (int i = zwidth; i >= 0; --i) { 1126 val = (val >> 8) | (((uint64_t)*ptr++) << 56); 1127 } 1128 } 1129 return val; 1130} 1131 1132EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file, 1133 Handle<mirror::DexCache>* dex_cache, 1134 Handle<mirror::ClassLoader>* class_loader, 1135 ClassLinker* linker, 1136 const DexFile::ClassDef& class_def) 1137 : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker), 1138 array_size_(), pos_(-1), type_(kByte) { 1139 DCHECK(dex_cache != nullptr); 1140 DCHECK(class_loader != nullptr); 1141 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def); 1142 if (ptr_ == NULL) { 1143 array_size_ = 0; 1144 } else { 1145 array_size_ = DecodeUnsignedLeb128(&ptr_); 1146 } 1147 if (array_size_ > 0) { 1148 Next(); 1149 } 1150} 1151 1152void EncodedStaticFieldValueIterator::Next() { 1153 pos_++; 1154 if (pos_ >= array_size_) { 1155 return; 1156 } 1157 uint8_t value_type = *ptr_++; 1158 uint8_t value_arg = value_type >> kEncodedValueArgShift; 1159 size_t width = value_arg + 1; // assume and correct later 1160 type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask); 1161 switch (type_) { 1162 case kBoolean: 1163 jval_.i = (value_arg != 0) ? 1 : 0; 1164 width = 0; 1165 break; 1166 case kByte: 1167 jval_.i = ReadSignedInt(ptr_, value_arg); 1168 CHECK(IsInt<8>(jval_.i)); 1169 break; 1170 case kShort: 1171 jval_.i = ReadSignedInt(ptr_, value_arg); 1172 CHECK(IsInt<16>(jval_.i)); 1173 break; 1174 case kChar: 1175 jval_.i = ReadUnsignedInt(ptr_, value_arg, false); 1176 CHECK(IsUint<16>(jval_.i)); 1177 break; 1178 case kInt: 1179 jval_.i = ReadSignedInt(ptr_, value_arg); 1180 break; 1181 case kLong: 1182 jval_.j = ReadSignedLong(ptr_, value_arg); 1183 break; 1184 case kFloat: 1185 jval_.i = ReadUnsignedInt(ptr_, value_arg, true); 1186 break; 1187 case kDouble: 1188 jval_.j = ReadUnsignedLong(ptr_, value_arg, true); 1189 break; 1190 case kString: 1191 case kType: 1192 jval_.i = ReadUnsignedInt(ptr_, value_arg, false); 1193 break; 1194 case kField: 1195 case kMethod: 1196 case kEnum: 1197 case kArray: 1198 case kAnnotation: 1199 UNIMPLEMENTED(FATAL) << ": type " << type_; 1200 UNREACHABLE(); 1201 case kNull: 1202 jval_.l = NULL; 1203 width = 0; 1204 break; 1205 default: 1206 LOG(FATAL) << "Unreached"; 1207 UNREACHABLE(); 1208 } 1209 ptr_ += width; 1210} 1211 1212template<bool kTransactionActive> 1213void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> field) const { 1214 switch (type_) { 1215 case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z); break; 1216 case kByte: field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break; 1217 case kShort: field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break; 1218 case kChar: field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break; 1219 case kInt: field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break; 1220 case kLong: field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break; 1221 case kFloat: field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break; 1222 case kDouble: field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break; 1223 case kNull: field->SetObject<kTransactionActive>(field->GetDeclaringClass(), NULL); break; 1224 case kString: { 1225 CHECK(!kMovingFields); 1226 mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_); 1227 field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved); 1228 break; 1229 } 1230 case kType: { 1231 CHECK(!kMovingFields); 1232 mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_, 1233 *class_loader_); 1234 field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved); 1235 break; 1236 } 1237 default: UNIMPLEMENTED(FATAL) << ": type " << type_; 1238 } 1239} 1240template void EncodedStaticFieldValueIterator::ReadValueToField<true>(Handle<mirror::ArtField> field) const; 1241template void EncodedStaticFieldValueIterator::ReadValueToField<false>(Handle<mirror::ArtField> field) const; 1242 1243CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) { 1244 handler_.address_ = -1; 1245 int32_t offset = -1; 1246 1247 // Short-circuit the overwhelmingly common cases. 1248 switch (code_item.tries_size_) { 1249 case 0: 1250 break; 1251 case 1: { 1252 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0); 1253 uint32_t start = tries->start_addr_; 1254 if (address >= start) { 1255 uint32_t end = start + tries->insn_count_; 1256 if (address < end) { 1257 offset = tries->handler_off_; 1258 } 1259 } 1260 break; 1261 } 1262 default: 1263 offset = DexFile::FindCatchHandlerOffset(code_item, address); 1264 } 1265 Init(code_item, offset); 1266} 1267 1268CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, 1269 const DexFile::TryItem& try_item) { 1270 handler_.address_ = -1; 1271 Init(code_item, try_item.handler_off_); 1272} 1273 1274void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item, 1275 int32_t offset) { 1276 if (offset >= 0) { 1277 Init(DexFile::GetCatchHandlerData(code_item, offset)); 1278 } else { 1279 // Not found, initialize as empty 1280 current_data_ = NULL; 1281 remaining_count_ = -1; 1282 catch_all_ = false; 1283 DCHECK(!HasNext()); 1284 } 1285} 1286 1287void CatchHandlerIterator::Init(const uint8_t* handler_data) { 1288 current_data_ = handler_data; 1289 remaining_count_ = DecodeSignedLeb128(¤t_data_); 1290 1291 // If remaining_count_ is non-positive, then it is the negative of 1292 // the number of catch types, and the catches are followed by a 1293 // catch-all handler. 1294 if (remaining_count_ <= 0) { 1295 catch_all_ = true; 1296 remaining_count_ = -remaining_count_; 1297 } else { 1298 catch_all_ = false; 1299 } 1300 Next(); 1301} 1302 1303void CatchHandlerIterator::Next() { 1304 if (remaining_count_ > 0) { 1305 handler_.type_idx_ = DecodeUnsignedLeb128(¤t_data_); 1306 handler_.address_ = DecodeUnsignedLeb128(¤t_data_); 1307 remaining_count_--; 1308 return; 1309 } 1310 1311 if (catch_all_) { 1312 handler_.type_idx_ = DexFile::kDexNoIndex16; 1313 handler_.address_ = DecodeUnsignedLeb128(¤t_data_); 1314 catch_all_ = false; 1315 return; 1316 } 1317 1318 // no more handler 1319 remaining_count_ = -1; 1320} 1321 1322} // namespace art 1323