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 <sstream> 21 #include <string.h> 22 #include <unistd.h> 23 24 #include "base/bit_vector.h" 25 #include "base/stl_util.h" 26 #include "base/unix_file/fd_file.h" 27 #include "elf_file.h" 28 #include "elf_utils.h" 29 #include "oat.h" 30 #include "mirror/art_method.h" 31 #include "mirror/art_method-inl.h" 32 #include "mirror/class.h" 33 #include "mirror/object-inl.h" 34 #include "os.h" 35 #include "runtime.h" 36 #include "utils.h" 37 #include "vmap_table.h" 38 39 namespace art { 40 41 void OatFile::CheckLocation(const std::string& location) { 42 CHECK(!location.empty()); 43 } 44 45 OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file, 46 const std::string& location, 47 std::string* error_msg) { 48 std::unique_ptr<OatFile> oat_file(new OatFile(location, false)); 49 oat_file->elf_file_.reset(elf_file); 50 Elf32_Shdr* hdr = elf_file->FindSectionByName(".rodata"); 51 oat_file->begin_ = elf_file->Begin() + hdr->sh_offset; 52 oat_file->end_ = elf_file->Begin() + hdr->sh_size + hdr->sh_offset; 53 return oat_file->Setup(error_msg) ? oat_file.release() : nullptr; 54 } 55 56 OatFile* OatFile::OpenMemory(std::vector<uint8_t>& oat_contents, 57 const std::string& location, 58 std::string* error_msg) { 59 CHECK(!oat_contents.empty()) << location; 60 CheckLocation(location); 61 std::unique_ptr<OatFile> oat_file(new OatFile(location, false)); 62 oat_file->begin_ = &oat_contents[0]; 63 oat_file->end_ = &oat_contents[oat_contents.size()]; 64 return oat_file->Setup(error_msg) ? oat_file.release() : nullptr; 65 } 66 67 OatFile* OatFile::Open(const std::string& filename, 68 const std::string& location, 69 byte* requested_base, 70 uint8_t* oat_file_begin, 71 bool executable, 72 std::string* error_msg) { 73 CHECK(!filename.empty()) << location; 74 CheckLocation(location); 75 std::unique_ptr<OatFile> ret; 76 if (kUsePortableCompiler && executable) { 77 // If we are using PORTABLE, use dlopen to deal with relocations. 78 // 79 // We use our own ELF loader for Quick to deal with legacy apps that 80 // open a generated dex file by name, remove the file, then open 81 // another generated dex file with the same name. http://b/10614658 82 ret.reset(OpenDlopen(filename, location, requested_base, error_msg)); 83 } else { 84 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons: 85 // 86 // On target, dlopen may fail when compiling due to selinux restrictions on installd. 87 // 88 // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile. 89 // This won't work for portable runtime execution because it doesn't process relocations. 90 std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str())); 91 if (file.get() == NULL) { 92 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno)); 93 return nullptr; 94 } 95 ret.reset(OpenElfFile(file.get(), location, requested_base, oat_file_begin, false, executable, 96 error_msg)); 97 98 // It would be nice to unlink here. But we might have opened the file created by the 99 // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API 100 // to allow removal when we know the ELF must be borked. 101 } 102 return ret.release(); 103 } 104 105 OatFile* OatFile::OpenWritable(File* file, const std::string& location, std::string* error_msg) { 106 CheckLocation(location); 107 return OpenElfFile(file, location, nullptr, nullptr, true, false, error_msg); 108 } 109 110 OatFile* OatFile::OpenReadable(File* file, const std::string& location, std::string* error_msg) { 111 CheckLocation(location); 112 return OpenElfFile(file, location, nullptr, nullptr, false, false, error_msg); 113 } 114 115 OatFile* OatFile::OpenDlopen(const std::string& elf_filename, 116 const std::string& location, 117 byte* requested_base, 118 std::string* error_msg) { 119 std::unique_ptr<OatFile> oat_file(new OatFile(location, true)); 120 bool success = oat_file->Dlopen(elf_filename, requested_base, error_msg); 121 if (!success) { 122 return nullptr; 123 } 124 return oat_file.release(); 125 } 126 127 OatFile* OatFile::OpenElfFile(File* file, 128 const std::string& location, 129 byte* requested_base, 130 uint8_t* oat_file_begin, 131 bool writable, 132 bool executable, 133 std::string* error_msg) { 134 std::unique_ptr<OatFile> oat_file(new OatFile(location, executable)); 135 bool success = oat_file->ElfFileOpen(file, requested_base, oat_file_begin, writable, executable, 136 error_msg); 137 if (!success) { 138 CHECK(!error_msg->empty()); 139 return nullptr; 140 } 141 return oat_file.release(); 142 } 143 144 OatFile::OatFile(const std::string& location, bool is_executable) 145 : location_(location), begin_(NULL), end_(NULL), is_executable_(is_executable), 146 dlopen_handle_(NULL), 147 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { 148 CHECK(!location_.empty()); 149 } 150 151 OatFile::~OatFile() { 152 STLDeleteElements(&oat_dex_files_storage_); 153 if (dlopen_handle_ != NULL) { 154 dlclose(dlopen_handle_); 155 } 156 } 157 158 bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base, 159 std::string* error_msg) { 160 char* absolute_path = realpath(elf_filename.c_str(), NULL); 161 if (absolute_path == NULL) { 162 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str()); 163 return false; 164 } 165 dlopen_handle_ = dlopen(absolute_path, RTLD_NOW); 166 free(absolute_path); 167 if (dlopen_handle_ == NULL) { 168 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror()); 169 return false; 170 } 171 begin_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatdata")); 172 if (begin_ == NULL) { 173 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(), 174 dlerror()); 175 return false; 176 } 177 if (requested_base != NULL && begin_ != requested_base) { 178 *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 179 "oatdata=%p != expected=%p /proc/self/maps:\n", 180 begin_, requested_base); 181 ReadFileToString("/proc/self/maps", error_msg); 182 return false; 183 } 184 end_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatlastword")); 185 if (end_ == NULL) { 186 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(), 187 dlerror()); 188 return false; 189 } 190 // Readjust to be non-inclusive upper bound. 191 end_ += sizeof(uint32_t); 192 return Setup(error_msg); 193 } 194 195 bool OatFile::ElfFileOpen(File* file, byte* requested_base, uint8_t* oat_file_begin, 196 bool writable, bool executable, 197 std::string* error_msg) { 198 // TODO: rename requested_base to oat_data_begin 199 elf_file_.reset(ElfFile::Open(file, writable, /*program_header_only*/true, error_msg, 200 oat_file_begin)); 201 if (elf_file_.get() == nullptr) { 202 DCHECK(!error_msg->empty()); 203 return false; 204 } 205 bool loaded = elf_file_->Load(executable, error_msg); 206 if (!loaded) { 207 DCHECK(!error_msg->empty()); 208 return false; 209 } 210 begin_ = elf_file_->FindDynamicSymbolAddress("oatdata"); 211 if (begin_ == NULL) { 212 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str()); 213 return false; 214 } 215 if (requested_base != NULL && begin_ != requested_base) { 216 *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 217 "oatdata=%p != expected=%p /proc/self/maps:\n", 218 begin_, requested_base); 219 ReadFileToString("/proc/self/maps", error_msg); 220 return false; 221 } 222 end_ = elf_file_->FindDynamicSymbolAddress("oatlastword"); 223 if (end_ == NULL) { 224 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str()); 225 return false; 226 } 227 // Readjust to be non-inclusive upper bound. 228 end_ += sizeof(uint32_t); 229 return Setup(error_msg); 230 } 231 232 bool OatFile::Setup(std::string* error_msg) { 233 if (!GetOatHeader().IsValid()) { 234 *error_msg = StringPrintf("Invalid oat magic for '%s'", GetLocation().c_str()); 235 return false; 236 } 237 const byte* oat = Begin(); 238 oat += sizeof(OatHeader); 239 if (oat > End()) { 240 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str()); 241 return false; 242 } 243 244 oat += GetOatHeader().GetKeyValueStoreSize(); 245 if (oat > End()) { 246 *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: " 247 "%p + %zd + %ud <= %p", GetLocation().c_str(), 248 Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(), 249 End()); 250 return false; 251 } 252 253 uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); 254 oat_dex_files_storage_.reserve(dex_file_count); 255 for (size_t i = 0; i < dex_file_count; i++) { 256 uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat); 257 if (UNLIKELY(dex_file_location_size == 0U)) { 258 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name", 259 GetLocation().c_str(), i); 260 return false; 261 } 262 oat += sizeof(dex_file_location_size); 263 if (UNLIKELY(oat > End())) { 264 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file " 265 "location size", GetLocation().c_str(), i); 266 return false; 267 } 268 269 const char* dex_file_location_data = reinterpret_cast<const char*>(oat); 270 oat += dex_file_location_size; 271 if (UNLIKELY(oat > End())) { 272 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file " 273 "location", GetLocation().c_str(), i); 274 return false; 275 } 276 277 std::string dex_file_location(dex_file_location_data, dex_file_location_size); 278 279 uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat); 280 oat += sizeof(dex_file_checksum); 281 if (UNLIKELY(oat > End())) { 282 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after " 283 "dex file checksum", GetLocation().c_str(), i, 284 dex_file_location.c_str()); 285 return false; 286 } 287 288 uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat); 289 if (UNLIKELY(dex_file_offset == 0U)) { 290 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex " 291 "file offset", GetLocation().c_str(), i, dex_file_location.c_str()); 292 return false; 293 } 294 if (UNLIKELY(dex_file_offset > Size())) { 295 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file " 296 "offset %ud > %zd", GetLocation().c_str(), i, 297 dex_file_location.c_str(), dex_file_offset, Size()); 298 return false; 299 } 300 oat += sizeof(dex_file_offset); 301 if (UNLIKELY(oat > End())) { 302 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated " 303 " after dex file offsets", GetLocation().c_str(), i, 304 dex_file_location.c_str()); 305 return false; 306 } 307 308 const uint8_t* dex_file_pointer = Begin() + dex_file_offset; 309 if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) { 310 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 311 " dex file magic '%s'", GetLocation().c_str(), i, 312 dex_file_location.c_str(), dex_file_pointer); 313 return false; 314 } 315 if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) { 316 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 317 " dex file version '%s'", GetLocation().c_str(), i, 318 dex_file_location.c_str(), dex_file_pointer); 319 return false; 320 } 321 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer); 322 const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat); 323 324 oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_); 325 if (UNLIKELY(oat > End())) { 326 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated " 327 " method offsets", GetLocation().c_str(), i, 328 dex_file_location.c_str()); 329 return false; 330 } 331 332 std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str()); 333 334 // Create the OatDexFile and add it to the owning container. 335 OatDexFile* oat_dex_file = new OatDexFile(this, 336 dex_file_location, 337 canonical_location, 338 dex_file_checksum, 339 dex_file_pointer, 340 methods_offsets_pointer); 341 oat_dex_files_storage_.push_back(oat_dex_file); 342 343 // Add the location and canonical location (if different) to the oat_dex_files_ table. 344 StringPiece key(oat_dex_file->GetDexFileLocation()); 345 oat_dex_files_.Put(key, oat_dex_file); 346 if (canonical_location != dex_file_location) { 347 StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation()); 348 oat_dex_files_.Put(canonical_key, oat_dex_file); 349 } 350 } 351 return true; 352 } 353 354 const OatHeader& OatFile::GetOatHeader() const { 355 return *reinterpret_cast<const OatHeader*>(Begin()); 356 } 357 358 const byte* OatFile::Begin() const { 359 CHECK(begin_ != NULL); 360 return begin_; 361 } 362 363 const byte* OatFile::End() const { 364 CHECK(end_ != NULL); 365 return end_; 366 } 367 368 const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, 369 const uint32_t* dex_location_checksum, 370 bool warn_if_not_found) const { 371 // NOTE: We assume here that the canonical location for a given dex_location never 372 // changes. If it does (i.e. some symlink used by the filename changes) we may return 373 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return 374 // an identical file or fail; otherwise we may see some unpredictable failures. 375 376 // TODO: Additional analysis of usage patterns to see if this can be simplified 377 // without any performance loss, for example by not doing the first lock-free lookup. 378 379 const OatFile::OatDexFile* oat_dex_file = nullptr; 380 StringPiece key(dex_location); 381 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations 382 // directly mentioned in the oat file and doesn't require locking. 383 auto primary_it = oat_dex_files_.find(key); 384 if (primary_it != oat_dex_files_.end()) { 385 oat_dex_file = primary_it->second; 386 DCHECK(oat_dex_file != nullptr); 387 } else { 388 // This dex_location is not one of the dex locations directly mentioned in the 389 // oat file. The correct lookup is via the canonical location but first see in 390 // the secondary_oat_dex_files_ whether we've looked up this location before. 391 MutexLock mu(Thread::Current(), secondary_lookup_lock_); 392 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key); 393 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) { 394 oat_dex_file = secondary_lb->second; // May be nullptr. 395 } else { 396 // We haven't seen this dex_location before, we must check the canonical location. 397 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 398 if (dex_canonical_location != dex_location) { 399 StringPiece canonical_key(dex_canonical_location); 400 auto canonical_it = oat_dex_files_.find(canonical_key); 401 if (canonical_it != oat_dex_files_.end()) { 402 oat_dex_file = canonical_it->second; 403 } // else keep nullptr. 404 } // else keep nullptr. 405 406 // Copy the key to the string_cache_ and store the result in secondary map. 407 string_cache_.emplace_back(key.data(), key.length()); 408 StringPiece key_copy(string_cache_.back()); 409 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file); 410 } 411 } 412 if (oat_dex_file != nullptr && 413 (dex_location_checksum == nullptr || 414 oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) { 415 return oat_dex_file; 416 } 417 418 if (warn_if_not_found) { 419 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 420 std::string checksum("<unspecified>"); 421 if (dex_location_checksum != NULL) { 422 checksum = StringPrintf("0x%08x", *dex_location_checksum); 423 } 424 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location 425 << " ( canonical path " << dex_canonical_location << ")" 426 << " with checksum " << checksum << " in OatFile " << GetLocation(); 427 if (kIsDebugBuild) { 428 for (const OatDexFile* odf : oat_dex_files_storage_) { 429 LOG(WARNING) << "OatFile " << GetLocation() 430 << " contains OatDexFile " << odf->GetDexFileLocation() 431 << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")" 432 << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum(); 433 } 434 } 435 } 436 437 return NULL; 438 } 439 440 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, 441 const std::string& dex_file_location, 442 const std::string& canonical_dex_file_location, 443 uint32_t dex_file_location_checksum, 444 const byte* dex_file_pointer, 445 const uint32_t* oat_class_offsets_pointer) 446 : oat_file_(oat_file), 447 dex_file_location_(dex_file_location), 448 canonical_dex_file_location_(canonical_dex_file_location), 449 dex_file_location_checksum_(dex_file_location_checksum), 450 dex_file_pointer_(dex_file_pointer), 451 oat_class_offsets_pointer_(oat_class_offsets_pointer) {} 452 453 OatFile::OatDexFile::~OatDexFile() {} 454 455 size_t OatFile::OatDexFile::FileSize() const { 456 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_; 457 } 458 459 const DexFile* OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const { 460 return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_, 461 dex_file_location_checksum_, GetOatFile(), error_msg); 462 } 463 464 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { 465 return oat_class_offsets_pointer_[class_def_index]; 466 } 467 468 OatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const { 469 uint32_t oat_class_offset = GetOatClassOffset(class_def_index); 470 471 const byte* oat_class_pointer = oat_file_->Begin() + oat_class_offset; 472 CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation(); 473 474 const byte* status_pointer = oat_class_pointer; 475 CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation(); 476 mirror::Class::Status status = 477 static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer)); 478 CHECK_LT(status, mirror::Class::kStatusMax); 479 480 const byte* type_pointer = status_pointer + sizeof(uint16_t); 481 CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 482 OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer)); 483 CHECK_LT(type, kOatClassMax); 484 485 const byte* after_type_pointer = type_pointer + sizeof(int16_t); 486 CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 487 488 uint32_t bitmap_size = 0; 489 const byte* bitmap_pointer = nullptr; 490 const byte* methods_pointer = nullptr; 491 if (type == kOatClassSomeCompiled) { 492 bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer)); 493 bitmap_pointer = after_type_pointer + sizeof(bitmap_size); 494 CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation(); 495 methods_pointer = bitmap_pointer + bitmap_size; 496 } else { 497 methods_pointer = after_type_pointer; 498 } 499 CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation(); 500 501 return OatClass(oat_file_, 502 status, 503 type, 504 bitmap_size, 505 reinterpret_cast<const uint32_t*>(bitmap_pointer), 506 reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); 507 } 508 509 OatFile::OatClass::OatClass(const OatFile* oat_file, 510 mirror::Class::Status status, 511 OatClassType type, 512 uint32_t bitmap_size, 513 const uint32_t* bitmap_pointer, 514 const OatMethodOffsets* methods_pointer) 515 : oat_file_(oat_file), status_(status), type_(type), 516 bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) { 517 CHECK(methods_pointer != nullptr); 518 switch (type_) { 519 case kOatClassAllCompiled: { 520 CHECK_EQ(0U, bitmap_size); 521 CHECK(bitmap_pointer == nullptr); 522 break; 523 } 524 case kOatClassSomeCompiled: { 525 CHECK_NE(0U, bitmap_size); 526 CHECK(bitmap_pointer != nullptr); 527 break; 528 } 529 case kOatClassNoneCompiled: { 530 CHECK_EQ(0U, bitmap_size); 531 CHECK(bitmap_pointer == nullptr); 532 methods_pointer_ = nullptr; 533 break; 534 } 535 case kOatClassMax: { 536 LOG(FATAL) << "Invalid OatClassType " << type_; 537 break; 538 } 539 } 540 } 541 542 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const { 543 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 544 if (oat_method_offsets == nullptr) { 545 return 0u; 546 } 547 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin(); 548 } 549 550 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const { 551 // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index. 552 if (methods_pointer_ == nullptr) { 553 CHECK_EQ(kOatClassNoneCompiled, type_); 554 return nullptr; 555 } 556 size_t methods_pointer_index; 557 if (bitmap_ == nullptr) { 558 CHECK_EQ(kOatClassAllCompiled, type_); 559 methods_pointer_index = method_index; 560 } else { 561 CHECK_EQ(kOatClassSomeCompiled, type_); 562 if (!BitVector::IsBitSet(bitmap_, method_index)) { 563 return nullptr; 564 } 565 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index); 566 methods_pointer_index = num_set_bits; 567 } 568 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index]; 569 return &oat_method_offsets; 570 } 571 572 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { 573 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 574 if (oat_method_offsets == nullptr) { 575 return OatMethod(nullptr, 0); 576 } 577 if (oat_file_->IsExecutable() || 578 Runtime::Current() == nullptr || // This case applies for oatdump. 579 Runtime::Current()->IsCompiler()) { 580 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_); 581 } else { 582 // We aren't allowed to use the compiled code. We just force it down the interpreted version. 583 return OatMethod(oat_file_->Begin(), 0); 584 } 585 } 586 587 OatFile::OatMethod::OatMethod(const byte* base, 588 const uint32_t code_offset) 589 : begin_(base), 590 code_offset_(code_offset) { 591 } 592 593 OatFile::OatMethod::~OatMethod() {} 594 595 void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const { 596 CHECK(method != NULL); 597 #if defined(ART_USE_PORTABLE_COMPILER) 598 method->SetEntryPointFromPortableCompiledCode(GetPortableCode()); 599 #endif 600 method->SetEntryPointFromQuickCompiledCode(GetQuickCode()); 601 } 602 603 bool OatFile::IsPic() const { 604 return GetOatHeader().IsPic(); 605 // TODO: Check against oat_patches. b/18144996 606 } 607 608 } // namespace art 609