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 "oat_file.h" 18 19 #include <dlfcn.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 #include <cstdlib> 24 #ifndef __APPLE__ 25 #include <link.h> // for dl_iterate_phdr. 26 #endif 27 #include <sstream> 28 29 // dlopen_ext support from bionic. 30 #ifdef HAVE_ANDROID_OS 31 #include "android/dlext.h" 32 #endif 33 34 #include "art_method-inl.h" 35 #include "base/bit_vector.h" 36 #include "base/stl_util.h" 37 #include "base/unix_file/fd_file.h" 38 #include "elf_file.h" 39 #include "elf_utils.h" 40 #include "oat.h" 41 #include "mem_map.h" 42 #include "mirror/class.h" 43 #include "mirror/object-inl.h" 44 #include "os.h" 45 #include "runtime.h" 46 #include "utils.h" 47 #include "vmap_table.h" 48 49 namespace art { 50 51 // Whether OatFile::Open will try DlOpen() first. Fallback is our own ELF loader. 52 static constexpr bool kUseDlopen = true; 53 54 // Whether OatFile::Open will try DlOpen() on the host. On the host we're not linking against 55 // bionic, so cannot take advantage of the support for changed semantics (loading the same soname 56 // multiple times). However, if/when we switch the above, we likely want to switch this, too, 57 // to get test coverage of the code paths. 58 static constexpr bool kUseDlopenOnHost = true; 59 60 // For debugging, Open will print DlOpen error message if set to true. 61 static constexpr bool kPrintDlOpenErrorMessage = false; 62 63 std::string OatFile::ResolveRelativeEncodedDexLocation( 64 const char* abs_dex_location, const std::string& rel_dex_location) { 65 if (abs_dex_location != nullptr && rel_dex_location[0] != '/') { 66 // Strip :classes<N>.dex used for secondary multidex files. 67 std::string base = DexFile::GetBaseLocation(rel_dex_location); 68 std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location); 69 70 // Check if the base is a suffix of the provided abs_dex_location. 71 std::string target_suffix = "/" + base; 72 std::string abs_location(abs_dex_location); 73 if (abs_location.size() > target_suffix.size()) { 74 size_t pos = abs_location.size() - target_suffix.size(); 75 if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) { 76 return abs_location + multidex_suffix; 77 } 78 } 79 } 80 return rel_dex_location; 81 } 82 83 void OatFile::CheckLocation(const std::string& location) { 84 CHECK(!location.empty()); 85 } 86 87 OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file, 88 const std::string& location, 89 const char* abs_dex_location, 90 std::string* error_msg) { 91 std::unique_ptr<OatFile> oat_file(new OatFile(location, false)); 92 oat_file->elf_file_.reset(elf_file); 93 uint64_t offset, size; 94 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size); 95 CHECK(has_section); 96 oat_file->begin_ = elf_file->Begin() + offset; 97 oat_file->end_ = elf_file->Begin() + size + offset; 98 // Ignore the optional .bss section when opening non-executable. 99 return oat_file->Setup(abs_dex_location, error_msg) ? oat_file.release() : nullptr; 100 } 101 102 OatFile* OatFile::Open(const std::string& filename, 103 const std::string& location, 104 uint8_t* requested_base, 105 uint8_t* oat_file_begin, 106 bool executable, 107 const char* abs_dex_location, 108 std::string* error_msg) { 109 CHECK(!filename.empty()) << location; 110 CheckLocation(location); 111 std::unique_ptr<OatFile> ret; 112 113 // Use dlopen only when flagged to do so, and when it's OK to load things executable. 114 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as 115 // !executable is a sign that we may want to patch), which may not be allowed for 116 // various reasons. 117 if (kUseDlopen && (kIsTargetBuild || kUseDlopenOnHost) && executable) { 118 // Try to use dlopen. This may fail for various reasons, outlined below. We try dlopen, as 119 // this will register the oat file with the linker and allows libunwind to find our info. 120 ret.reset(OpenDlopen(filename, location, requested_base, abs_dex_location, error_msg)); 121 if (ret.get() != nullptr) { 122 return ret.release(); 123 } 124 if (kPrintDlOpenErrorMessage) { 125 LOG(ERROR) << "Failed to dlopen: " << *error_msg; 126 } 127 } 128 129 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons: 130 // 131 // On target, dlopen may fail when compiling due to selinux restrictions on installd. 132 // 133 // We use our own ELF loader for Quick to deal with legacy apps that 134 // open a generated dex file by name, remove the file, then open 135 // another generated dex file with the same name. http://b/10614658 136 // 137 // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile. 138 // 139 // 140 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually 141 // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN. 142 std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str())); 143 if (file == nullptr) { 144 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno)); 145 return nullptr; 146 } 147 ret.reset(OpenElfFile(file.get(), location, requested_base, oat_file_begin, false, executable, 148 abs_dex_location, error_msg)); 149 150 // It would be nice to unlink here. But we might have opened the file created by the 151 // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API 152 // to allow removal when we know the ELF must be borked. 153 return ret.release(); 154 } 155 156 OatFile* OatFile::OpenWritable(File* file, const std::string& location, 157 const char* abs_dex_location, 158 std::string* error_msg) { 159 CheckLocation(location); 160 return OpenElfFile(file, location, nullptr, nullptr, true, false, abs_dex_location, error_msg); 161 } 162 163 OatFile* OatFile::OpenReadable(File* file, const std::string& location, 164 const char* abs_dex_location, 165 std::string* error_msg) { 166 CheckLocation(location); 167 return OpenElfFile(file, location, nullptr, nullptr, false, false, abs_dex_location, error_msg); 168 } 169 170 OatFile* OatFile::OpenDlopen(const std::string& elf_filename, 171 const std::string& location, 172 uint8_t* requested_base, 173 const char* abs_dex_location, 174 std::string* error_msg) { 175 std::unique_ptr<OatFile> oat_file(new OatFile(location, true)); 176 bool success = oat_file->Dlopen(elf_filename, requested_base, abs_dex_location, error_msg); 177 if (!success) { 178 return nullptr; 179 } 180 return oat_file.release(); 181 } 182 183 OatFile* OatFile::OpenElfFile(File* file, 184 const std::string& location, 185 uint8_t* requested_base, 186 uint8_t* oat_file_begin, 187 bool writable, 188 bool executable, 189 const char* abs_dex_location, 190 std::string* error_msg) { 191 std::unique_ptr<OatFile> oat_file(new OatFile(location, executable)); 192 bool success = oat_file->ElfFileOpen(file, requested_base, oat_file_begin, writable, executable, 193 abs_dex_location, error_msg); 194 if (!success) { 195 CHECK(!error_msg->empty()); 196 return nullptr; 197 } 198 return oat_file.release(); 199 } 200 201 OatFile::OatFile(const std::string& location, bool is_executable) 202 : location_(location), begin_(nullptr), end_(nullptr), bss_begin_(nullptr), bss_end_(nullptr), 203 is_executable_(is_executable), dlopen_handle_(nullptr), 204 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { 205 CHECK(!location_.empty()); 206 } 207 208 OatFile::~OatFile() { 209 STLDeleteElements(&oat_dex_files_storage_); 210 if (dlopen_handle_ != nullptr) { 211 dlclose(dlopen_handle_); 212 } 213 } 214 215 bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base, 216 const char* abs_dex_location, std::string* error_msg) { 217 #ifdef __APPLE__ 218 // The dl_iterate_phdr syscall is missing. There is similar API on OSX, 219 // but let's fallback to the custom loading code for the time being. 220 UNUSED(elf_filename); 221 UNUSED(requested_base); 222 UNUSED(abs_dex_location); 223 UNUSED(error_msg); 224 return false; 225 #else 226 std::unique_ptr<char> absolute_path(realpath(elf_filename.c_str(), nullptr)); 227 if (absolute_path == nullptr) { 228 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str()); 229 return false; 230 } 231 #ifdef HAVE_ANDROID_OS 232 android_dlextinfo extinfo; 233 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_FORCE_FIXED_VADDR; 234 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo); 235 #else 236 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW); 237 #endif 238 if (dlopen_handle_ == nullptr) { 239 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror()); 240 return false; 241 } 242 begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatdata")); 243 if (begin_ == nullptr) { 244 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(), 245 dlerror()); 246 return false; 247 } 248 if (requested_base != nullptr && begin_ != requested_base) { 249 PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 250 *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 251 "oatdata=%p != expected=%p, %s. See process maps in the log.", 252 begin_, requested_base, elf_filename.c_str()); 253 return false; 254 } 255 end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatlastword")); 256 if (end_ == nullptr) { 257 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(), 258 dlerror()); 259 return false; 260 } 261 // Readjust to be non-inclusive upper bound. 262 end_ += sizeof(uint32_t); 263 264 bss_begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbss")); 265 if (bss_begin_ == nullptr) { 266 // No .bss section. Clear dlerror(). 267 bss_end_ = nullptr; 268 dlerror(); 269 } else { 270 bss_end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbsslastword")); 271 if (bss_end_ == nullptr) { 272 *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", 273 elf_filename.c_str()); 274 return false; 275 } 276 // Readjust to be non-inclusive upper bound. 277 bss_end_ += sizeof(uint32_t); 278 } 279 280 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions. 281 struct dl_iterate_context { 282 static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) { 283 auto* context = reinterpret_cast<dl_iterate_context*>(data); 284 // See whether this callback corresponds to the file which we have just loaded. 285 bool contains_begin = false; 286 for (int i = 0; i < info->dlpi_phnum; i++) { 287 if (info->dlpi_phdr[i].p_type == PT_LOAD) { 288 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 289 info->dlpi_phdr[i].p_vaddr); 290 size_t memsz = info->dlpi_phdr[i].p_memsz; 291 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) { 292 contains_begin = true; 293 break; 294 } 295 } 296 } 297 // Add dummy mmaps for this file. 298 if (contains_begin) { 299 for (int i = 0; i < info->dlpi_phnum; i++) { 300 if (info->dlpi_phdr[i].p_type == PT_LOAD) { 301 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 302 info->dlpi_phdr[i].p_vaddr); 303 size_t memsz = info->dlpi_phdr[i].p_memsz; 304 MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz); 305 context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap)); 306 } 307 } 308 return 1; // Stop iteration and return 1 from dl_iterate_phdr. 309 } 310 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished. 311 } 312 const uint8_t* const begin_; 313 std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_; 314 } context = { begin_, &dlopen_mmaps_ }; 315 316 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) { 317 PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 318 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but can not find its mmaps."; 319 } 320 321 return Setup(abs_dex_location, error_msg); 322 #endif // __APPLE__ 323 } 324 325 bool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file_begin, 326 bool writable, bool executable, 327 const char* abs_dex_location, 328 std::string* error_msg) { 329 // TODO: rename requested_base to oat_data_begin 330 elf_file_.reset(ElfFile::Open(file, writable, /*program_header_only*/true, error_msg, 331 oat_file_begin)); 332 if (elf_file_ == nullptr) { 333 DCHECK(!error_msg->empty()); 334 return false; 335 } 336 bool loaded = elf_file_->Load(executable, error_msg); 337 if (!loaded) { 338 DCHECK(!error_msg->empty()); 339 return false; 340 } 341 begin_ = elf_file_->FindDynamicSymbolAddress("oatdata"); 342 if (begin_ == nullptr) { 343 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str()); 344 return false; 345 } 346 if (requested_base != nullptr && begin_ != requested_base) { 347 PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 348 *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 349 "oatdata=%p != expected=%p. See process maps in the log.", 350 begin_, requested_base); 351 return false; 352 } 353 end_ = elf_file_->FindDynamicSymbolAddress("oatlastword"); 354 if (end_ == nullptr) { 355 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str()); 356 return false; 357 } 358 // Readjust to be non-inclusive upper bound. 359 end_ += sizeof(uint32_t); 360 361 bss_begin_ = elf_file_->FindDynamicSymbolAddress("oatbss"); 362 if (bss_begin_ == nullptr) { 363 // No .bss section. Clear dlerror(). 364 bss_end_ = nullptr; 365 dlerror(); 366 } else { 367 bss_end_ = elf_file_->FindDynamicSymbolAddress("oatbsslastword"); 368 if (bss_end_ == nullptr) { 369 *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", 370 file->GetPath().c_str()); 371 return false; 372 } 373 // Readjust to be non-inclusive upper bound. 374 bss_end_ += sizeof(uint32_t); 375 } 376 377 return Setup(abs_dex_location, error_msg); 378 } 379 380 bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) { 381 if (!GetOatHeader().IsValid()) { 382 std::string cause = GetOatHeader().GetValidationErrorMessage(); 383 *error_msg = StringPrintf("Invalid oat header for '%s': %s", GetLocation().c_str(), 384 cause.c_str()); 385 return false; 386 } 387 const uint8_t* oat = Begin(); 388 oat += sizeof(OatHeader); 389 if (oat > End()) { 390 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str()); 391 return false; 392 } 393 394 oat += GetOatHeader().GetKeyValueStoreSize(); 395 if (oat > End()) { 396 *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: " 397 "%p + %zd + %ud <= %p", GetLocation().c_str(), 398 Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(), 399 End()); 400 return false; 401 } 402 403 uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); 404 oat_dex_files_storage_.reserve(dex_file_count); 405 for (size_t i = 0; i < dex_file_count; i++) { 406 uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat); 407 if (UNLIKELY(dex_file_location_size == 0U)) { 408 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name", 409 GetLocation().c_str(), i); 410 return false; 411 } 412 oat += sizeof(dex_file_location_size); 413 if (UNLIKELY(oat > End())) { 414 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file " 415 "location size", GetLocation().c_str(), i); 416 return false; 417 } 418 419 const char* dex_file_location_data = reinterpret_cast<const char*>(oat); 420 oat += dex_file_location_size; 421 if (UNLIKELY(oat > End())) { 422 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file " 423 "location", GetLocation().c_str(), i); 424 return false; 425 } 426 427 std::string dex_file_location = ResolveRelativeEncodedDexLocation( 428 abs_dex_location, 429 std::string(dex_file_location_data, dex_file_location_size)); 430 431 uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat); 432 oat += sizeof(dex_file_checksum); 433 if (UNLIKELY(oat > End())) { 434 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after " 435 "dex file checksum", GetLocation().c_str(), i, 436 dex_file_location.c_str()); 437 return false; 438 } 439 440 uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat); 441 if (UNLIKELY(dex_file_offset == 0U)) { 442 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex " 443 "file offset", GetLocation().c_str(), i, dex_file_location.c_str()); 444 return false; 445 } 446 if (UNLIKELY(dex_file_offset > Size())) { 447 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file " 448 "offset %ud > %zd", GetLocation().c_str(), i, 449 dex_file_location.c_str(), dex_file_offset, Size()); 450 return false; 451 } 452 oat += sizeof(dex_file_offset); 453 if (UNLIKELY(oat > End())) { 454 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated " 455 "after dex file offsets", GetLocation().c_str(), i, 456 dex_file_location.c_str()); 457 return false; 458 } 459 460 const uint8_t* dex_file_pointer = Begin() + dex_file_offset; 461 if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) { 462 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 463 "dex file magic '%s'", GetLocation().c_str(), i, 464 dex_file_location.c_str(), dex_file_pointer); 465 return false; 466 } 467 if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) { 468 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 469 "dex file version '%s'", GetLocation().c_str(), i, 470 dex_file_location.c_str(), dex_file_pointer); 471 return false; 472 } 473 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer); 474 const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat); 475 476 oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_); 477 if (UNLIKELY(oat > End())) { 478 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated " 479 "method offsets", GetLocation().c_str(), i, 480 dex_file_location.c_str()); 481 return false; 482 } 483 484 std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str()); 485 486 // Create the OatDexFile and add it to the owning container. 487 OatDexFile* oat_dex_file = new OatDexFile(this, 488 dex_file_location, 489 canonical_location, 490 dex_file_checksum, 491 dex_file_pointer, 492 methods_offsets_pointer); 493 oat_dex_files_storage_.push_back(oat_dex_file); 494 495 // Add the location and canonical location (if different) to the oat_dex_files_ table. 496 StringPiece key(oat_dex_file->GetDexFileLocation()); 497 oat_dex_files_.Put(key, oat_dex_file); 498 if (canonical_location != dex_file_location) { 499 StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation()); 500 oat_dex_files_.Put(canonical_key, oat_dex_file); 501 } 502 } 503 return true; 504 } 505 506 const OatHeader& OatFile::GetOatHeader() const { 507 return *reinterpret_cast<const OatHeader*>(Begin()); 508 } 509 510 const uint8_t* OatFile::Begin() const { 511 CHECK(begin_ != nullptr); 512 return begin_; 513 } 514 515 const uint8_t* OatFile::End() const { 516 CHECK(end_ != nullptr); 517 return end_; 518 } 519 520 const uint8_t* OatFile::BssBegin() const { 521 return bss_begin_; 522 } 523 524 const uint8_t* OatFile::BssEnd() const { 525 return bss_end_; 526 } 527 528 const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, 529 const uint32_t* dex_location_checksum, 530 bool warn_if_not_found) const { 531 // NOTE: We assume here that the canonical location for a given dex_location never 532 // changes. If it does (i.e. some symlink used by the filename changes) we may return 533 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return 534 // an identical file or fail; otherwise we may see some unpredictable failures. 535 536 // TODO: Additional analysis of usage patterns to see if this can be simplified 537 // without any performance loss, for example by not doing the first lock-free lookup. 538 539 const OatFile::OatDexFile* oat_dex_file = nullptr; 540 StringPiece key(dex_location); 541 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations 542 // directly mentioned in the oat file and doesn't require locking. 543 auto primary_it = oat_dex_files_.find(key); 544 if (primary_it != oat_dex_files_.end()) { 545 oat_dex_file = primary_it->second; 546 DCHECK(oat_dex_file != nullptr); 547 } else { 548 // This dex_location is not one of the dex locations directly mentioned in the 549 // oat file. The correct lookup is via the canonical location but first see in 550 // the secondary_oat_dex_files_ whether we've looked up this location before. 551 MutexLock mu(Thread::Current(), secondary_lookup_lock_); 552 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key); 553 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) { 554 oat_dex_file = secondary_lb->second; // May be null. 555 } else { 556 // We haven't seen this dex_location before, we must check the canonical location. 557 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 558 if (dex_canonical_location != dex_location) { 559 StringPiece canonical_key(dex_canonical_location); 560 auto canonical_it = oat_dex_files_.find(canonical_key); 561 if (canonical_it != oat_dex_files_.end()) { 562 oat_dex_file = canonical_it->second; 563 } // else keep null. 564 } // else keep null. 565 566 // Copy the key to the string_cache_ and store the result in secondary map. 567 string_cache_.emplace_back(key.data(), key.length()); 568 StringPiece key_copy(string_cache_.back()); 569 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file); 570 } 571 } 572 if (oat_dex_file != nullptr && 573 (dex_location_checksum == nullptr || 574 oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) { 575 return oat_dex_file; 576 } 577 578 if (warn_if_not_found) { 579 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 580 std::string checksum("<unspecified>"); 581 if (dex_location_checksum != nullptr) { 582 checksum = StringPrintf("0x%08x", *dex_location_checksum); 583 } 584 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location 585 << " ( canonical path " << dex_canonical_location << ")" 586 << " with checksum " << checksum << " in OatFile " << GetLocation(); 587 if (kIsDebugBuild) { 588 for (const OatDexFile* odf : oat_dex_files_storage_) { 589 LOG(WARNING) << "OatFile " << GetLocation() 590 << " contains OatDexFile " << odf->GetDexFileLocation() 591 << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")" 592 << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum(); 593 } 594 } 595 } 596 597 return nullptr; 598 } 599 600 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, 601 const std::string& dex_file_location, 602 const std::string& canonical_dex_file_location, 603 uint32_t dex_file_location_checksum, 604 const uint8_t* dex_file_pointer, 605 const uint32_t* oat_class_offsets_pointer) 606 : oat_file_(oat_file), 607 dex_file_location_(dex_file_location), 608 canonical_dex_file_location_(canonical_dex_file_location), 609 dex_file_location_checksum_(dex_file_location_checksum), 610 dex_file_pointer_(dex_file_pointer), 611 oat_class_offsets_pointer_(oat_class_offsets_pointer) {} 612 613 OatFile::OatDexFile::~OatDexFile() {} 614 615 size_t OatFile::OatDexFile::FileSize() const { 616 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_; 617 } 618 619 std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const { 620 return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_, 621 dex_file_location_checksum_, this, error_msg); 622 } 623 624 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { 625 return oat_class_offsets_pointer_[class_def_index]; 626 } 627 628 OatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const { 629 uint32_t oat_class_offset = GetOatClassOffset(class_def_index); 630 631 const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset; 632 CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation(); 633 634 const uint8_t* status_pointer = oat_class_pointer; 635 CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation(); 636 mirror::Class::Status status = 637 static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer)); 638 CHECK_LT(status, mirror::Class::kStatusMax); 639 640 const uint8_t* type_pointer = status_pointer + sizeof(uint16_t); 641 CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 642 OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer)); 643 CHECK_LT(type, kOatClassMax); 644 645 const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t); 646 CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 647 648 uint32_t bitmap_size = 0; 649 const uint8_t* bitmap_pointer = nullptr; 650 const uint8_t* methods_pointer = nullptr; 651 if (type != kOatClassNoneCompiled) { 652 if (type == kOatClassSomeCompiled) { 653 bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer)); 654 bitmap_pointer = after_type_pointer + sizeof(bitmap_size); 655 CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation(); 656 methods_pointer = bitmap_pointer + bitmap_size; 657 } else { 658 methods_pointer = after_type_pointer; 659 } 660 CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation(); 661 } 662 663 return OatFile::OatClass(oat_file_, 664 status, 665 type, 666 bitmap_size, 667 reinterpret_cast<const uint32_t*>(bitmap_pointer), 668 reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); 669 } 670 671 OatFile::OatClass::OatClass(const OatFile* oat_file, 672 mirror::Class::Status status, 673 OatClassType type, 674 uint32_t bitmap_size, 675 const uint32_t* bitmap_pointer, 676 const OatMethodOffsets* methods_pointer) 677 : oat_file_(oat_file), status_(status), type_(type), 678 bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) { 679 switch (type_) { 680 case kOatClassAllCompiled: { 681 CHECK_EQ(0U, bitmap_size); 682 CHECK(bitmap_pointer == nullptr); 683 CHECK(methods_pointer != nullptr); 684 break; 685 } 686 case kOatClassSomeCompiled: { 687 CHECK_NE(0U, bitmap_size); 688 CHECK(bitmap_pointer != nullptr); 689 CHECK(methods_pointer != nullptr); 690 break; 691 } 692 case kOatClassNoneCompiled: { 693 CHECK_EQ(0U, bitmap_size); 694 CHECK(bitmap_pointer == nullptr); 695 CHECK(methods_pointer_ == nullptr); 696 break; 697 } 698 case kOatClassMax: { 699 LOG(FATAL) << "Invalid OatClassType " << type_; 700 break; 701 } 702 } 703 } 704 705 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const { 706 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 707 if (oat_method_offsets == nullptr) { 708 return 0u; 709 } 710 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin(); 711 } 712 713 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const { 714 // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index. 715 if (methods_pointer_ == nullptr) { 716 CHECK_EQ(kOatClassNoneCompiled, type_); 717 return nullptr; 718 } 719 size_t methods_pointer_index; 720 if (bitmap_ == nullptr) { 721 CHECK_EQ(kOatClassAllCompiled, type_); 722 methods_pointer_index = method_index; 723 } else { 724 CHECK_EQ(kOatClassSomeCompiled, type_); 725 if (!BitVector::IsBitSet(bitmap_, method_index)) { 726 return nullptr; 727 } 728 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index); 729 methods_pointer_index = num_set_bits; 730 } 731 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index]; 732 return &oat_method_offsets; 733 } 734 735 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { 736 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 737 if (oat_method_offsets == nullptr) { 738 return OatMethod(nullptr, 0); 739 } 740 if (oat_file_->IsExecutable() || 741 Runtime::Current() == nullptr || // This case applies for oatdump. 742 Runtime::Current()->IsAotCompiler()) { 743 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_); 744 } 745 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit 746 // version. 747 return OatMethod(oat_file_->Begin(), 0); 748 } 749 750 void OatFile::OatMethod::LinkMethod(ArtMethod* method) const { 751 CHECK(method != nullptr); 752 method->SetEntryPointFromQuickCompiledCode(GetQuickCode()); 753 } 754 755 bool OatFile::IsPic() const { 756 return GetOatHeader().IsPic(); 757 // TODO: Check against oat_patches. b/18144996 758 } 759 760 bool OatFile::IsDebuggable() const { 761 return GetOatHeader().IsDebuggable(); 762 } 763 764 static constexpr char kDexClassPathEncodingSeparator = '*'; 765 766 std::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) { 767 std::ostringstream out; 768 769 for (const DexFile* dex_file : dex_files) { 770 out << dex_file->GetLocation().c_str(); 771 out << kDexClassPathEncodingSeparator; 772 out << dex_file->GetLocationChecksum(); 773 out << kDexClassPathEncodingSeparator; 774 } 775 776 return out.str(); 777 } 778 779 bool OatFile::CheckStaticDexFileDependencies(const char* dex_dependencies, std::string* msg) { 780 if (dex_dependencies == nullptr || dex_dependencies[0] == 0) { 781 // No dependencies. 782 return true; 783 } 784 785 // Assumption: this is not performance-critical. So it's OK to do this with a std::string and 786 // Split() instead of manual parsing of the combined char*. 787 std::vector<std::string> split; 788 Split(dex_dependencies, kDexClassPathEncodingSeparator, &split); 789 if (split.size() % 2 != 0) { 790 // Expected pairs of location and checksum. 791 *msg = StringPrintf("Odd number of elements in dependency list %s", dex_dependencies); 792 return false; 793 } 794 795 for (auto it = split.begin(), end = split.end(); it != end; it += 2) { 796 std::string& location = *it; 797 std::string& checksum = *(it + 1); 798 int64_t converted = strtoll(checksum.c_str(), nullptr, 10); 799 if (converted == 0) { 800 // Conversion error. 801 *msg = StringPrintf("Conversion error for %s", checksum.c_str()); 802 return false; 803 } 804 805 uint32_t dex_checksum; 806 std::string error_msg; 807 if (DexFile::GetChecksum(DexFile::GetDexCanonicalLocation(location.c_str()).c_str(), 808 &dex_checksum, 809 &error_msg)) { 810 if (converted != dex_checksum) { 811 *msg = StringPrintf("Checksums don't match for %s: %" PRId64 " vs %u", 812 location.c_str(), converted, dex_checksum); 813 return false; 814 } 815 } else { 816 // Problem retrieving checksum. 817 // TODO: odex files? 818 *msg = StringPrintf("Could not retrieve checksum for %s: %s", location.c_str(), 819 error_msg.c_str()); 820 return false; 821 } 822 } 823 824 return true; 825 } 826 827 bool OatFile::GetDexLocationsFromDependencies(const char* dex_dependencies, 828 std::vector<std::string>* locations) { 829 DCHECK(locations != nullptr); 830 if (dex_dependencies == nullptr || dex_dependencies[0] == 0) { 831 return true; 832 } 833 834 // Assumption: this is not performance-critical. So it's OK to do this with a std::string and 835 // Split() instead of manual parsing of the combined char*. 836 std::vector<std::string> split; 837 Split(dex_dependencies, kDexClassPathEncodingSeparator, &split); 838 if (split.size() % 2 != 0) { 839 // Expected pairs of location and checksum. 840 return false; 841 } 842 843 for (auto it = split.begin(), end = split.end(); it != end; it += 2) { 844 locations->push_back(*it); 845 } 846 847 return true; 848 } 849 850 } // namespace art 851