oat_file.cc revision 957ca1cd025104fccb0b08928f955f9bdb4ab91c
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
17e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h"
18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
19700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include <dlfcn.h>
2022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include <sstream>
214e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle#include <string.h>
22daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe#include <unistd.h>
23700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
24ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h"
251aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h"
26761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
27700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "elf_file.h"
2884d7605f93f1e6e86a16e02017e305c90e93117aAlex Light#include "elf_utils.h"
29700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h"
30ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method.h"
31ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
334f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
34e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h"
3522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include "runtime.h"
362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h"
371809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers#include "vmap_table.h"
38e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art {
40e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
41700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromvoid OatFile::CheckLocation(const std::string& location) {
42700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(!location.empty());
43700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
44700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
4584d7605f93f1e6e86a16e02017e305c90e93117aAlex LightOatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
4684d7605f93f1e6e86a16e02017e305c90e93117aAlex Light                                  const std::string& location,
4784d7605f93f1e6e86a16e02017e305c90e93117aAlex Light                                  std::string* error_msg) {
4884d7605f93f1e6e86a16e02017e305c90e93117aAlex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, false));
4984d7605f93f1e6e86a16e02017e305c90e93117aAlex Light  oat_file->elf_file_.reset(elf_file);
5062d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  uint64_t offset, size;
5162d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
5262d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  CHECK(has_section);
5362d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  oat_file->begin_ = elf_file->Begin() + offset;
5462d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  oat_file->end_ = elf_file->Begin() + size + offset;
5584d7605f93f1e6e86a16e02017e305c90e93117aAlex Light  return oat_file->Setup(error_msg) ? oat_file.release() : nullptr;
5684d7605f93f1e6e86a16e02017e305c90e93117aAlex Light}
5784d7605f93f1e6e86a16e02017e305c90e93117aAlex Light
58265091e581c9f643b37e7966890911f09e223269Brian CarlstromOatFile* OatFile::OpenMemory(std::vector<uint8_t>& oat_contents,
598d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                             const std::string& location,
608d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                             std::string* error_msg) {
61700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(!oat_contents.empty()) << location;
62700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CheckLocation(location);
639dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, false));
64700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  oat_file->begin_ = &oat_contents[0];
65700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  oat_file->end_ = &oat_contents[oat_contents.size()];
668d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  return oat_file->Setup(error_msg) ? oat_file.release() : nullptr;
67700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
68700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
69e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile* OatFile::Open(const std::string& filename,
70a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom                       const std::string& location,
7113735955f39b3b304c37d2b2840663c131262c18Ian Rogers                       uint8_t* requested_base,
7246774767fcf7780d1455e755729198648d08742eIgor Murashkin                       uint8_t* oat_file_begin,
738d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                       bool executable,
748d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                       std::string* error_msg) {
757a967b3d4468ab56bf1b75ebd4d7bf9e6798761bBrian Carlstrom  CHECK(!filename.empty()) << location;
767ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe  CheckLocation(location);
7722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  std::unique_ptr<OatFile> ret;
7822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (kUsePortableCompiler && executable) {
79ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    // If we are using PORTABLE, use dlopen to deal with relocations.
80ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    //
81ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    // We use our own ELF loader for Quick to deal with legacy apps that
82ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    // open a generated dex file by name, remove the file, then open
83ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    // another generated dex file with the same name. http://b/10614658
8422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    ret.reset(OpenDlopen(filename, location, requested_base, error_msg));
8522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  } else {
8622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
8722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    //
8822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // On target, dlopen may fail when compiling due to selinux restrictions on installd.
8922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    //
9022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
9122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // This won't work for portable runtime execution because it doesn't process relocations.
9222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str()));
9322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (file.get() == NULL) {
9422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
9522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      return nullptr;
96ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
9746774767fcf7780d1455e755729198648d08742eIgor Murashkin    ret.reset(OpenElfFile(file.get(), location, requested_base, oat_file_begin, false, executable,
9846774767fcf7780d1455e755729198648d08742eIgor Murashkin                          error_msg));
99daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe
1009ef2b6c73b964754fbb9198b1e3ea3d56744a059Andreas Gampe    // It would be nice to unlink here. But we might have opened the file created by the
1019ef2b6c73b964754fbb9198b1e3ea3d56744a059Andreas Gampe    // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API
1029ef2b6c73b964754fbb9198b1e3ea3d56744a059Andreas Gampe    // to allow removal when we know the ELF must be borked.
10322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
10469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison  return ret.release();
1055b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom}
106e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1078d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan RogersOatFile* OatFile::OpenWritable(File* file, const std::string& location, std::string* error_msg) {
108700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CheckLocation(location);
10946774767fcf7780d1455e755729198648d08742eIgor Murashkin  return OpenElfFile(file, location, nullptr, nullptr, true, false, error_msg);
110700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
111700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
112a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex LightOatFile* OatFile::OpenReadable(File* file, const std::string& location, std::string* error_msg) {
113a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CheckLocation(location);
11446774767fcf7780d1455e755729198648d08742eIgor Murashkin  return OpenElfFile(file, location, nullptr, nullptr, false, false, error_msg);
115a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
116a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
117700c8d31733534a3d978b75a03f6f7e177dc7e81Brian CarlstromOatFile* OatFile::OpenDlopen(const std::string& elf_filename,
118700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                             const std::string& location,
11913735955f39b3b304c37d2b2840663c131262c18Ian Rogers                             uint8_t* requested_base,
1208d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                             std::string* error_msg) {
1219dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, true));
1228d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  bool success = oat_file->Dlopen(elf_filename, requested_base, error_msg);
123700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (!success) {
1248d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    return nullptr;
1257a967b3d4468ab56bf1b75ebd4d7bf9e6798761bBrian Carlstrom  }
126700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return oat_file.release();
127700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
128700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
129700c8d31733534a3d978b75a03f6f7e177dc7e81Brian CarlstromOatFile* OatFile::OpenElfFile(File* file,
130700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                              const std::string& location,
13113735955f39b3b304c37d2b2840663c131262c18Ian Rogers                              uint8_t* requested_base,
13246774767fcf7780d1455e755729198648d08742eIgor Murashkin                              uint8_t* oat_file_begin,
133f1d3455064792ac1c486a4a9c24279a37b4af473Brian Carlstrom                              bool writable,
1348d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              bool executable,
1358d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              std::string* error_msg) {
1369dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, executable));
13746774767fcf7780d1455e755729198648d08742eIgor Murashkin  bool success = oat_file->ElfFileOpen(file, requested_base, oat_file_begin, writable, executable,
13846774767fcf7780d1455e755729198648d08742eIgor Murashkin                                       error_msg);
139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  if (!success) {
1408d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    CHECK(!error_msg->empty());
1418d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    return nullptr;
142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return oat_file.release();
144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
145e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1469dcc4572949f6a8231a1b4ed859676ba6f411726Alex LightOatFile::OatFile(const std::string& location, bool is_executable)
1479dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light    : location_(location), begin_(NULL), end_(NULL), is_executable_(is_executable),
1489dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light      dlopen_handle_(NULL),
1493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
150a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  CHECK(!location_.empty());
151a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom}
152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
153e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::~OatFile() {
154aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  STLDeleteElements(&oat_dex_files_storage_);
155700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (dlopen_handle_ != NULL) {
156700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    dlclose(dlopen_handle_);
157700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
158e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
159e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
16013735955f39b3b304c37d2b2840663c131262c18Ian Rogersbool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
1618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                     std::string* error_msg) {
162700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  char* absolute_path = realpath(elf_filename.c_str(), NULL);
163700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (absolute_path == NULL) {
1648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
165e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
166e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
167700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  dlopen_handle_ = dlopen(absolute_path, RTLD_NOW);
168700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  free(absolute_path);
169700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (dlopen_handle_ == NULL) {
1708d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
172e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
17313735955f39b3b304c37d2b2840663c131262c18Ian Rogers  begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatdata"));
174700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (begin_ == NULL) {
1758d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(),
1768d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              dlerror());
177700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
178700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
179700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (requested_base != NULL && begin_ != requested_base) {
1808d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
1818d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              "oatdata=%p != expected=%p /proc/self/maps:\n",
1828d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              begin_, requested_base);
1838d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    ReadFileToString("/proc/self/maps", error_msg);
184700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
185e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
18613735955f39b3b304c37d2b2840663c131262c18Ian Rogers  end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatlastword"));
187700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (end_ == NULL) {
1888d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(),
1898d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              dlerror());
190700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
191700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
192700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  // Readjust to be non-inclusive upper bound.
193700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ += sizeof(uint32_t);
1948d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  return Setup(error_msg);
195700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
196e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
19746774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file_begin,
19846774767fcf7780d1455e755729198648d08742eIgor Murashkin                          bool writable, bool executable,
1998d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                          std::string* error_msg) {
20046774767fcf7780d1455e755729198648d08742eIgor Murashkin  // TODO: rename requested_base to oat_data_begin
20146774767fcf7780d1455e755729198648d08742eIgor Murashkin  elf_file_.reset(ElfFile::Open(file, writable, /*program_header_only*/true, error_msg,
20246774767fcf7780d1455e755729198648d08742eIgor Murashkin                                oat_file_begin));
2038d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  if (elf_file_.get() == nullptr) {
2048d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    DCHECK(!error_msg->empty());
205700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
206700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
2078d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  bool loaded = elf_file_->Load(executable, error_msg);
208700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (!loaded) {
2098d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    DCHECK(!error_msg->empty());
210700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
211700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
212700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  begin_ = elf_file_->FindDynamicSymbolAddress("oatdata");
213700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (begin_ == NULL) {
2148d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str());
215700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
216700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
217700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (requested_base != NULL && begin_ != requested_base) {
2188d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
2198d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              "oatdata=%p != expected=%p /proc/self/maps:\n",
2208d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              begin_, requested_base);
2218d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    ReadFileToString("/proc/self/maps", error_msg);
222700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
223700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
224700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ = elf_file_->FindDynamicSymbolAddress("oatlastword");
225700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (end_ == NULL) {
2268d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str());
227700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
228700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
229700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  // Readjust to be non-inclusive upper bound.
230700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ += sizeof(uint32_t);
2318d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  return Setup(error_msg);
232700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
2336e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom
2348d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersbool OatFile::Setup(std::string* error_msg) {
235f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  if (!GetOatHeader().IsValid()) {
2368d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Invalid oat magic for '%s'", GetLocation().c_str());
237f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom    return false;
238f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  }
23913735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat = Begin();
240e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  oat += sizeof(OatHeader);
241fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
2428d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
243fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
244fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
245fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom
24622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  oat += GetOatHeader().GetKeyValueStoreSize();
247fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
24822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
2498d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              "%p + %zd + %ud <= %p", GetLocation().c_str(),
25022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                              Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(),
2518d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              End());
252fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
253fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
25481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
255aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
256aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  oat_dex_files_storage_.reserve(dex_file_count);
257aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  for (size_t i = 0; i < dex_file_count; i++) {
25883bef92043a5b9020e99eac076db5f327b36cb7eDmitry Petrochenko    uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
2598d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_location_size == 0U)) {
2608d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name",
2618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                GetLocation().c_str(), i);
262fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
263fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
264e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += sizeof(dex_file_location_size);
2658d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
2668d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file "
2678d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "location size", GetLocation().c_str(), i);
268fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
269fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
270e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
271e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
272e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += dex_file_location_size;
2738d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
2748d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file "
2758d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "location", GetLocation().c_str(), i);
276fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
277fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
278e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
279e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    std::string dex_file_location(dex_file_location_data, dex_file_location_size);
280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
281e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
282e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += sizeof(dex_file_checksum);
2838d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
2848d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after "
2858d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "dex file checksum", GetLocation().c_str(), i,
2868d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
287fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
288fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
289e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
29089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom    uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
2918d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_offset == 0U)) {
2928d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex "
2938d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "file offset", GetLocation().c_str(), i, dex_file_location.c_str());
294fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
295fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
2968d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_offset > Size())) {
2978d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file "
2988d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "offset %ud > %zd", GetLocation().c_str(), i,
2998d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_offset, Size());
300fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
301fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
30289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom    oat += sizeof(dex_file_offset);
3038d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
3048d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
30537628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "after dex file offsets", GetLocation().c_str(), i,
3068d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
307fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
308fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
30989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
310700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
3118d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
3128d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
31337628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "dex file magic '%s'", GetLocation().c_str(), i,
3148d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_pointer);
315fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
316fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
3178d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
3188d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
31937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "dex file version '%s'", GetLocation().c_str(), i,
3208d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_pointer);
321fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
322fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
3236e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
3246e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
32589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
3266e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
3278d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
3288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
32937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "method offsets", GetLocation().c_str(), i,
3308d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
331fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
332fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
333e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
334aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
335aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
336aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Create the OatDexFile and add it to the owning container.
337539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    OatDexFile* oat_dex_file = new OatDexFile(this,
338539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_location,
339aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                              canonical_location,
340539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_checksum,
341539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_pointer,
342539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              methods_offsets_pointer);
343aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    oat_dex_files_storage_.push_back(oat_dex_file);
344aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
345aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Add the location and canonical location (if different) to the oat_dex_files_ table.
3463f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    StringPiece key(oat_dex_file->GetDexFileLocation());
347539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    oat_dex_files_.Put(key, oat_dex_file);
348aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    if (canonical_location != dex_file_location) {
349aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
350aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      oat_dex_files_.Put(canonical_key, oat_dex_file);
351aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    }
352e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
353f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  return true;
354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
355e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
356e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst OatHeader& OatFile::GetOatHeader() const {
35730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  return *reinterpret_cast<const OatHeader*>(Begin());
358e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
359e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
36013735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::Begin() const {
361700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(begin_ != NULL);
362700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return begin_;
363e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
364e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
36513735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::End() const {
366700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(end_ != NULL);
367700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return end_;
368e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
369e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
3708d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
3718d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                                  const uint32_t* dex_location_checksum,
3727fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers                                                  bool warn_if_not_found) const {
3733f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // NOTE: We assume here that the canonical location for a given dex_location never
3743f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // changes. If it does (i.e. some symlink used by the filename changes) we may return
3753f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
3763f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an identical file or fail; otherwise we may see some unpredictable failures.
3773f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
3783f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // TODO: Additional analysis of usage patterns to see if this can be simplified
3793f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // without any performance loss, for example by not doing the first lock-free lookup.
3803f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
3813f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  const OatFile::OatDexFile* oat_dex_file = nullptr;
3823f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  StringPiece key(dex_location);
3833f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
3843f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // directly mentioned in the oat file and doesn't require locking.
3853f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  auto primary_it = oat_dex_files_.find(key);
3863f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  if (primary_it != oat_dex_files_.end()) {
3873f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    oat_dex_file = primary_it->second;
3883f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    DCHECK(oat_dex_file != nullptr);
3893f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  } else {
3903f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // This dex_location is not one of the dex locations directly mentioned in the
3913f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // oat file. The correct lookup is via the canonical location but first see in
3923f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // the secondary_oat_dex_files_ whether we've looked up this location before.
3933f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    MutexLock mu(Thread::Current(), secondary_lookup_lock_);
3943f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
3953f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
3963f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      oat_dex_file = secondary_lb->second;  // May be nullptr.
3973f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    } else {
3983f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // We haven't seen this dex_location before, we must check the canonical location.
3993f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
400aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      if (dex_canonical_location != dex_location) {
401aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        StringPiece canonical_key(dex_canonical_location);
402aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        auto canonical_it = oat_dex_files_.find(canonical_key);
403aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        if (canonical_it != oat_dex_files_.end()) {
404aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko          oat_dex_file = canonical_it->second;
405aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        }  // else keep nullptr.
4063f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      }  // else keep nullptr.
4073f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
4083f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // Copy the key to the string_cache_ and store the result in secondary map.
4093f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      string_cache_.emplace_back(key.data(), key.length());
4103f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      StringPiece key_copy(string_cache_.back());
4113f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
412756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    }
413756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  }
4143f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  if (oat_dex_file != nullptr &&
4153f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      (dex_location_checksum == nullptr ||
4163f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko       oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) {
4173f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    return oat_dex_file;
4183f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  }
419756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom
420756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  if (warn_if_not_found) {
4213f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
4220d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom    std::string checksum("<unspecified>");
4230d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom    if (dex_location_checksum != NULL) {
4240d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom      checksum = StringPrintf("0x%08x", *dex_location_checksum);
4250d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom    }
426756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location
4274e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle                 << " ( canonical path " << dex_canonical_location << ")"
4280d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom                 << " with checksum " << checksum << " in OatFile " << GetLocation();
429756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    if (kIsDebugBuild) {
430aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      for (const OatDexFile* odf : oat_dex_files_storage_) {
431756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom        LOG(WARNING) << "OatFile " << GetLocation()
432aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " contains OatDexFile " << odf->GetDexFileLocation()
433aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")"
434aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum();
4357571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom      }
4367fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers    }
437aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
4384e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle
439756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  return NULL;
440aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
441aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
442e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
443aa6a588eb83288481389aa08b03105346a87e706Elliott Hughes                                const std::string& dex_file_location,
444aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                const std::string& canonical_dex_file_location,
4455b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom                                uint32_t dex_file_location_checksum,
44613735955f39b3b304c37d2b2840663c131262c18Ian Rogers                                const uint8_t* dex_file_pointer,
4470755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom                                const uint32_t* oat_class_offsets_pointer)
448e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    : oat_file_(oat_file),
449e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      dex_file_location_(dex_file_location),
450aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      canonical_dex_file_location_(canonical_dex_file_location),
4515b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      dex_file_location_checksum_(dex_file_location_checksum),
45289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom      dex_file_pointer_(dex_file_pointer),
4530755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      oat_class_offsets_pointer_(oat_class_offsets_pointer) {}
454e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
455e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::~OatDexFile() {}
456e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
45705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogerssize_t OatFile::OatDexFile::FileSize() const {
45805f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers  return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
45905f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers}
46005f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
4618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst DexFile* OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
46205f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers  return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
4638d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                       dex_file_location_checksum_, error_msg);
46489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom}
46589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
4662cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
4672cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return oat_class_offsets_pointer_[class_def_index];
4682cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
4692cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
470d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir MarkoOatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
4712cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
4720755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
47313735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
4747571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom  CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
4750755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
47613735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* status_pointer = oat_class_pointer;
477ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
478ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  mirror::Class::Status status =
479ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
480ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status, mirror::Class::kStatusMax);
481ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
48213735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
483ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
484ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
485ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type, kOatClassMax);
486ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
48713735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
488cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom  CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
489cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom
490ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  uint32_t bitmap_size = 0;
49113735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* bitmap_pointer = nullptr;
49213735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* methods_pointer = nullptr;
49397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers  if (type != kOatClassNoneCompiled) {
49497b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    if (type == kOatClassSomeCompiled) {
49597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
49697b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
49797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
49897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = bitmap_pointer + bitmap_size;
49997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    } else {
50097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = after_type_pointer;
50197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    }
50297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
503ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
5040755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
505d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko  return OatClass(oat_file_,
506d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko                  status,
507d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko                  type,
508d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko                  bitmap_size,
509d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko                  reinterpret_cast<const uint32_t*>(bitmap_pointer),
510d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko                  reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
511e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
512e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
5130755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatFile::OatClass::OatClass(const OatFile* oat_file,
5142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                            mirror::Class::Status status,
515ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            OatClassType type,
516ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            uint32_t bitmap_size,
517ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            const uint32_t* bitmap_pointer,
5180755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom                            const OatMethodOffsets* methods_pointer)
519ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    : oat_file_(oat_file), status_(status), type_(type),
520d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
521ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    switch (type_) {
522ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassAllCompiled: {
523ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
524cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
52597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
526ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
527ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
528ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassSomeCompiled: {
529ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_NE(0U, bitmap_size);
530cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer != nullptr);
53197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
532ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
533ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
534ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassNoneCompiled: {
535ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
536cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
53797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer_ == nullptr);
538ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
539ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
540ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassMax: {
541ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        LOG(FATAL) << "Invalid OatClassType " << type_;
542ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
543ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
544ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
545ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom}
546e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
5472cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
5482cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
5492cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
5502cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return 0u;
5512cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
5522cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
5532cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
5542cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
5552cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
556d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko  // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
5572cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (methods_pointer_ == nullptr) {
558ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassNoneCompiled, type_);
5592cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return nullptr;
560ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
561ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  size_t methods_pointer_index;
5622cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (bitmap_ == nullptr) {
563ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassAllCompiled, type_);
564ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    methods_pointer_index = method_index;
565ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  } else {
566ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassSomeCompiled, type_);
567d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    if (!BitVector::IsBitSet(bitmap_, method_index)) {
5682cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      return nullptr;
569ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
570d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
571d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    methods_pointer_index = num_set_bits;
572ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
573ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
5742cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return &oat_method_offsets;
5752cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
5762cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
5772cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
5782cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
5792cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
580957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(nullptr, 0);
5812cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
5822cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_file_->IsExecutable() ||
5832cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      Runtime::Current() == nullptr ||        // This case applies for oatdump.
5842cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      Runtime::Current()->IsCompiler()) {
585957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
5869dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  } else {
5879dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light    // We aren't allowed to use the compiled code. We just force it down the interpreted version.
588957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(oat_file_->Begin(), 0);
5899dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  }
5903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
5913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
592ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
5933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  CHECK(method != NULL);
594ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  method->SetEntryPointFromPortableCompiledCode(GetPortableCode());
595ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
596ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
597ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
5987ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampebool OatFile::IsPic() const {
59946774767fcf7780d1455e755729198648d08742eIgor Murashkin  return GetOatHeader().IsPic();
6007ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe  // TODO: Check against oat_patches. b/18144996
6017ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe}
6027ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe
603e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
604