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>
204e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle#include <string.h>
21daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe#include <unistd.h>
22700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
237848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe#include <cstdlib>
24a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#ifndef __APPLE__
25a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#include <link.h>  // for dl_iterate_phdr.
26a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#endif
27e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler#include <sstream>
28e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler
29fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// dlopen_ext support from bionic.
30fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#ifdef HAVE_ANDROID_OS
31fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#include "android/dlext.h"
32fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif
33fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
343d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h"
35ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h"
361aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h"
37761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
38700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "elf_file.h"
3984d7605f93f1e6e86a16e02017e305c90e93117aAlex Light#include "elf_utils.h"
40700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h"
41a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#include "mem_map.h"
422dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
434f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
44e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h"
4522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include "runtime.h"
462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h"
471809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers#include "vmap_table.h"
48e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
49e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art {
50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
51fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// Whether OatFile::Open will try DlOpen() first. Fallback is our own ELF loader.
52a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckystatic constexpr bool kUseDlopen = true;
53fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
54fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// Whether OatFile::Open will try DlOpen() on the host. On the host we're not linking against
55fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// bionic, so cannot take advantage of the support for changed semantics (loading the same soname
56fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// multiple times). However, if/when we switch the above, we likely want to switch this, too,
57fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// to get test coverage of the code paths.
58a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckystatic constexpr bool kUseDlopenOnHost = true;
59fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
60fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// For debugging, Open will print DlOpen error message if set to true.
61fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampestatic constexpr bool kPrintDlOpenErrorMessage = false;
62fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
63e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhlerstd::string OatFile::ResolveRelativeEncodedDexLocation(
64e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler      const char* abs_dex_location, const std::string& rel_dex_location) {
65e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
66e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    // Strip :classes<N>.dex used for secondary multidex files.
67e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string base = DexFile::GetBaseLocation(rel_dex_location);
68e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location);
69e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler
70e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    // Check if the base is a suffix of the provided abs_dex_location.
71e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string target_suffix = "/" + base;
72e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string abs_location(abs_dex_location);
73e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    if (abs_location.size() > target_suffix.size()) {
74e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler      size_t pos = abs_location.size() - target_suffix.size();
75e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler      if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) {
76e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler        return abs_location + multidex_suffix;
77e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler      }
78e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    }
79e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  }
80e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  return rel_dex_location;
81e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler}
82e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler
83700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromvoid OatFile::CheckLocation(const std::string& location) {
84700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(!location.empty());
85700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
86700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
8784d7605f93f1e6e86a16e02017e305c90e93117aAlex LightOatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
8884d7605f93f1e6e86a16e02017e305c90e93117aAlex Light                                  const std::string& location,
89e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                                  const char* abs_dex_location,
9084d7605f93f1e6e86a16e02017e305c90e93117aAlex Light                                  std::string* error_msg) {
9184d7605f93f1e6e86a16e02017e305c90e93117aAlex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, false));
9284d7605f93f1e6e86a16e02017e305c90e93117aAlex Light  oat_file->elf_file_.reset(elf_file);
9362d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  uint64_t offset, size;
9462d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
9562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  CHECK(has_section);
9662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  oat_file->begin_ = elf_file->Begin() + offset;
9762d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  oat_file->end_ = elf_file->Begin() + size + offset;
985c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  // Ignore the optional .bss section when opening non-executable.
99e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  return oat_file->Setup(abs_dex_location, error_msg) ? oat_file.release() : nullptr;
100700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
101700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
102e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile* OatFile::Open(const std::string& filename,
103a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom                       const std::string& location,
10413735955f39b3b304c37d2b2840663c131262c18Ian Rogers                       uint8_t* requested_base,
10546774767fcf7780d1455e755729198648d08742eIgor Murashkin                       uint8_t* oat_file_begin,
1068d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                       bool executable,
107e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                       const char* abs_dex_location,
1088d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                       std::string* error_msg) {
1097a967b3d4468ab56bf1b75ebd4d7bf9e6798761bBrian Carlstrom  CHECK(!filename.empty()) << location;
1107ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe  CheckLocation(location);
11122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  std::unique_ptr<OatFile> ret;
112fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
113fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  // Use dlopen only when flagged to do so, and when it's OK to load things executable.
114fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
115fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  //       !executable is a sign that we may want to patch), which may not be allowed for
116fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  //       various reasons.
117fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (kUseDlopen && (kIsTargetBuild || kUseDlopenOnHost) && executable) {
118fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    // Try to use dlopen. This may fail for various reasons, outlined below. We try dlopen, as
119fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    // this will register the oat file with the linker and allows libunwind to find our info.
120fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    ret.reset(OpenDlopen(filename, location, requested_base, abs_dex_location, error_msg));
121fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    if (ret.get() != nullptr) {
122fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe      return ret.release();
123fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    }
124fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    if (kPrintDlOpenErrorMessage) {
125fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe      LOG(ERROR) << "Failed to dlopen: " << *error_msg;
126fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    }
127fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
128fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
129956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
130956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  //
131956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // On target, dlopen may fail when compiling due to selinux restrictions on installd.
132956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  //
133956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // We use our own ELF loader for Quick to deal with legacy apps that
134956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // open a generated dex file by name, remove the file, then open
135956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // another generated dex file with the same name. http://b/10614658
136956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  //
137956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
138fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  //
139fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  //
140fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
141fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
142956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str()));
143fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (file == nullptr) {
144956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes    *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
145956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes    return nullptr;
14622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
147956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  ret.reset(OpenElfFile(file.get(), location, requested_base, oat_file_begin, false, executable,
148e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                        abs_dex_location, error_msg));
149956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes
150956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // It would be nice to unlink here. But we might have opened the file created by the
151956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API
152956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  // to allow removal when we know the ELF must be borked.
15369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison  return ret.release();
1545b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom}
155e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
156e5fed03772144595c0904faf3d6974cc55214c8cRichard UhlerOatFile* OatFile::OpenWritable(File* file, const std::string& location,
157e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                               const char* abs_dex_location,
158e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                               std::string* error_msg) {
159700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CheckLocation(location);
160e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  return OpenElfFile(file, location, nullptr, nullptr, true, false, abs_dex_location, error_msg);
161700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
162700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
163e5fed03772144595c0904faf3d6974cc55214c8cRichard UhlerOatFile* OatFile::OpenReadable(File* file, const std::string& location,
164e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                               const char* abs_dex_location,
165e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                               std::string* error_msg) {
166a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CheckLocation(location);
167e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  return OpenElfFile(file, location, nullptr, nullptr, false, false, abs_dex_location, error_msg);
168a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
169a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
170fa8429b967fe2260ece572337534c9dda6c50d8aAndreas GampeOatFile* OatFile::OpenDlopen(const std::string& elf_filename,
171fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                             const std::string& location,
172fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                             uint8_t* requested_base,
173fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                             const char* abs_dex_location,
174fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                             std::string* error_msg) {
175fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  std::unique_ptr<OatFile> oat_file(new OatFile(location, true));
176fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  bool success = oat_file->Dlopen(elf_filename, requested_base, abs_dex_location, error_msg);
177fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (!success) {
178fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return nullptr;
179fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
180fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  return oat_file.release();
181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe}
182fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
183700c8d31733534a3d978b75a03f6f7e177dc7e81Brian CarlstromOatFile* OatFile::OpenElfFile(File* file,
184700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                              const std::string& location,
18513735955f39b3b304c37d2b2840663c131262c18Ian Rogers                              uint8_t* requested_base,
18646774767fcf7780d1455e755729198648d08742eIgor Murashkin                              uint8_t* oat_file_begin,
187f1d3455064792ac1c486a4a9c24279a37b4af473Brian Carlstrom                              bool writable,
1888d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              bool executable,
189e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                              const char* abs_dex_location,
1908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              std::string* error_msg) {
1919dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  std::unique_ptr<OatFile> oat_file(new OatFile(location, executable));
19246774767fcf7780d1455e755729198648d08742eIgor Murashkin  bool success = oat_file->ElfFileOpen(file, requested_base, oat_file_begin, writable, executable,
193e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                                       abs_dex_location, error_msg);
194e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  if (!success) {
1958d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    CHECK(!error_msg->empty());
1968d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    return nullptr;
197e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
198e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return oat_file.release();
199e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
200e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
2019dcc4572949f6a8231a1b4ed859676ba6f411726Alex LightOatFile::OatFile(const std::string& location, bool is_executable)
202fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    : location_(location), begin_(nullptr), end_(nullptr), bss_begin_(nullptr), bss_end_(nullptr),
203fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe      is_executable_(is_executable), dlopen_handle_(nullptr),
2043f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
205a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  CHECK(!location_.empty());
206a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom}
207e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
208e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::~OatFile() {
209aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  STLDeleteElements(&oat_dex_files_storage_);
210fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (dlopen_handle_ != nullptr) {
211700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    dlclose(dlopen_handle_);
212700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
213e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
214e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
215fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampebool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
216fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                     const char* abs_dex_location, std::string* error_msg) {
217a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#ifdef __APPLE__
218a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
219a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  // but let's fallback to the custom loading code for the time being.
220a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  UNUSED(elf_filename);
221a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  UNUSED(requested_base);
222a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  UNUSED(abs_dex_location);
223a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  UNUSED(error_msg);
224a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  return false;
225a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#else
226fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  std::unique_ptr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
227fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (absolute_path == nullptr) {
228fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
229fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return false;
230fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
231fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#ifdef HAVE_ANDROID_OS
232fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  android_dlextinfo extinfo;
233a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_FORCE_FIXED_VADDR;
234fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
235fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#else
236fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
237fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif
238fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (dlopen_handle_ == nullptr) {
239fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
240fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return false;
241fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
242fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatdata"));
243fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (begin_ == nullptr) {
244fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(),
245fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                              dlerror());
246fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return false;
247fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
248fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (requested_base != nullptr && begin_ != requested_base) {
249fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
250fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
251fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                              "oatdata=%p != expected=%p, %s. See process maps in the log.",
252fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                              begin_, requested_base, elf_filename.c_str());
253fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return false;
254fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
255fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatlastword"));
256fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (end_ == nullptr) {
257fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(),
258fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                              dlerror());
259fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    return false;
260fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
261fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  // Readjust to be non-inclusive upper bound.
262fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  end_ += sizeof(uint32_t);
263fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
264fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  bss_begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbss"));
265fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (bss_begin_ == nullptr) {
266fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    // No .bss section. Clear dlerror().
267fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    bss_end_ = nullptr;
268fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    dlerror();
269fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  } else {
270fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    bss_end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbsslastword"));
271fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    if (bss_end_ == nullptr) {
272fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe      *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'",
273fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe                                elf_filename.c_str());
274fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe      return false;
275fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    }
276fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    // Readjust to be non-inclusive upper bound.
277fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    bss_end_ += sizeof(uint32_t);
278fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
279fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
280a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
281a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  struct dl_iterate_context {
282a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
283a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      auto* context = reinterpret_cast<dl_iterate_context*>(data);
284a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      // See whether this callback corresponds to the file which we have just loaded.
285a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      bool contains_begin = false;
286a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      for (int i = 0; i < info->dlpi_phnum; i++) {
287a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky        if (info->dlpi_phdr[i].p_type == PT_LOAD) {
288a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
289a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky                                                      info->dlpi_phdr[i].p_vaddr);
290a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          size_t memsz = info->dlpi_phdr[i].p_memsz;
291a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
292a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            contains_begin = true;
293a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            break;
294a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          }
295a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky        }
296a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      }
297a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      // Add dummy mmaps for this file.
298a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      if (contains_begin) {
299a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky        for (int i = 0; i < info->dlpi_phnum; i++) {
300a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          if (info->dlpi_phdr[i].p_type == PT_LOAD) {
301a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
302a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky                                                        info->dlpi_phdr[i].p_vaddr);
303a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            size_t memsz = info->dlpi_phdr[i].p_memsz;
304a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
305a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky            context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
306a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky          }
307a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky        }
308a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky        return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
309a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      }
310a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky      return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
311a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    }
312a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    const uint8_t* const begin_;
313a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
314a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  } context = { begin_, &dlopen_mmaps_ };
315a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky
316a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
317a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
318a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky    LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but can not find its mmaps.";
319a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky  }
320a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky
321fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  return Setup(abs_dex_location, error_msg);
322a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#endif  // __APPLE__
323fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe}
324fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
32546774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file_begin,
32646774767fcf7780d1455e755729198648d08742eIgor Murashkin                          bool writable, bool executable,
327e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                          const char* abs_dex_location,
3288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                          std::string* error_msg) {
32946774767fcf7780d1455e755729198648d08742eIgor Murashkin  // TODO: rename requested_base to oat_data_begin
33046774767fcf7780d1455e755729198648d08742eIgor Murashkin  elf_file_.reset(ElfFile::Open(file, writable, /*program_header_only*/true, error_msg,
33146774767fcf7780d1455e755729198648d08742eIgor Murashkin                                oat_file_begin));
332fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (elf_file_ == nullptr) {
3338d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    DCHECK(!error_msg->empty());
334700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
335700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
3368d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  bool loaded = elf_file_->Load(executable, error_msg);
337700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (!loaded) {
3388d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    DCHECK(!error_msg->empty());
339700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
340700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
341700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  begin_ = elf_file_->FindDynamicSymbolAddress("oatdata");
342fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (begin_ == nullptr) {
3438d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str());
344700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
345700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
346fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (requested_base != nullptr && begin_ != requested_base) {
347a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe    PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
3488d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
349a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe                              "oatdata=%p != expected=%p. See process maps in the log.",
3508d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              begin_, requested_base);
351700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
352700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
353700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ = elf_file_->FindDynamicSymbolAddress("oatlastword");
354fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (end_ == nullptr) {
3558d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str());
356700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
357700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
358700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  // Readjust to be non-inclusive upper bound.
359700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ += sizeof(uint32_t);
3605c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
3615c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  bss_begin_ = elf_file_->FindDynamicSymbolAddress("oatbss");
3625c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  if (bss_begin_ == nullptr) {
3635c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    // No .bss section. Clear dlerror().
3645c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    bss_end_ = nullptr;
3655c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    dlerror();
3665c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  } else {
3675c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    bss_end_ = elf_file_->FindDynamicSymbolAddress("oatbsslastword");
3685c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    if (bss_end_ == nullptr) {
3695c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko      *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'",
3705c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko                                file->GetPath().c_str());
3715c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko      return false;
3725c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    }
3735c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    // Readjust to be non-inclusive upper bound.
3745c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    bss_end_ += sizeof(uint32_t);
3755c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  }
3765c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
377e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  return Setup(abs_dex_location, error_msg);
378700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
3796e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom
380e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhlerbool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
381f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  if (!GetOatHeader().IsValid()) {
3822bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    std::string cause = GetOatHeader().GetValidationErrorMessage();
3832bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    *error_msg = StringPrintf("Invalid oat header for '%s': %s", GetLocation().c_str(),
3842bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                              cause.c_str());
385f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom    return false;
386f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  }
38713735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat = Begin();
388e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  oat += sizeof(OatHeader);
389fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
3908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
391fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
392fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
393fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom
39422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  oat += GetOatHeader().GetKeyValueStoreSize();
395fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
39622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
3978d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              "%p + %zd + %ud <= %p", GetLocation().c_str(),
39822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                              Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(),
3998d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              End());
400fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
401fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
40281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
403aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
404aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  oat_dex_files_storage_.reserve(dex_file_count);
405aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  for (size_t i = 0; i < dex_file_count; i++) {
40683bef92043a5b9020e99eac076db5f327b36cb7eDmitry Petrochenko    uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
4078d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_location_size == 0U)) {
4088d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name",
4098d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                GetLocation().c_str(), i);
410fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
411fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
412e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += sizeof(dex_file_location_size);
4138d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
4148d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file "
4158d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "location size", GetLocation().c_str(), i);
416fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
417fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
418e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
419e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
420e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += dex_file_location_size;
4218d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
4228d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file "
4238d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "location", GetLocation().c_str(), i);
424fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
425fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
426e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
427e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string dex_file_location = ResolveRelativeEncodedDexLocation(
428e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler        abs_dex_location,
429e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler        std::string(dex_file_location_data, dex_file_location_size));
430e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
431e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
432e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    oat += sizeof(dex_file_checksum);
4338d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
4348d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after "
4358d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "dex file checksum", GetLocation().c_str(), i,
4368d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
437fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
438fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
439e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
44089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom    uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
4418d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_offset == 0U)) {
4428d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex "
4438d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "file offset", GetLocation().c_str(), i, dex_file_location.c_str());
444fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
445fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4468d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(dex_file_offset > Size())) {
4478d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file "
4488d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                "offset %ud > %zd", GetLocation().c_str(), i,
4498d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_offset, Size());
450fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
451fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
45289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom    oat += sizeof(dex_file_offset);
4538d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
4548d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
45537628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "after dex file offsets", GetLocation().c_str(), i,
4568d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
457fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
458fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
45989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
460700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
4618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
4628d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
46337628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "dex file magic '%s'", GetLocation().c_str(), i,
4648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_pointer);
465fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
466fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4678d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
4688d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
46937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "dex file version '%s'", GetLocation().c_str(), i,
4708d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str(), dex_file_pointer);
471fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
472fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4736e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
4746e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
47589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
4766e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
4778d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(oat > End())) {
4788d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
47937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom                                "method offsets", GetLocation().c_str(), i,
4808d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
481fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
482fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
483e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
484aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
485aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
486aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Create the OatDexFile and add it to the owning container.
487539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    OatDexFile* oat_dex_file = new OatDexFile(this,
488539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_location,
489aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                              canonical_location,
490539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_checksum,
491539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_pointer,
492539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              methods_offsets_pointer);
493aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    oat_dex_files_storage_.push_back(oat_dex_file);
494aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
495aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Add the location and canonical location (if different) to the oat_dex_files_ table.
4963f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    StringPiece key(oat_dex_file->GetDexFileLocation());
497539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    oat_dex_files_.Put(key, oat_dex_file);
498aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    if (canonical_location != dex_file_location) {
499aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
500aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      oat_dex_files_.Put(canonical_key, oat_dex_file);
501aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    }
502e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
503f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  return true;
504e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
505e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
506e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst OatHeader& OatFile::GetOatHeader() const {
50730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  return *reinterpret_cast<const OatHeader*>(Begin());
508e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
509e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
51013735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::Begin() const {
511fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(begin_ != nullptr);
512700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return begin_;
513e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
514e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
51513735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::End() const {
516fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(end_ != nullptr);
517700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return end_;
518e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
519e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
5205c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssBegin() const {
5215c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  return bss_begin_;
5225c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko}
5235c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
5245c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssEnd() const {
5255c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  return bss_end_;
5265c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko}
5275c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
5288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
5298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                                  const uint32_t* dex_location_checksum,
5307fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers                                                  bool warn_if_not_found) const {
5313f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // NOTE: We assume here that the canonical location for a given dex_location never
5323f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // changes. If it does (i.e. some symlink used by the filename changes) we may return
5333f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
5343f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an identical file or fail; otherwise we may see some unpredictable failures.
5353f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
5363f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // TODO: Additional analysis of usage patterns to see if this can be simplified
5373f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // without any performance loss, for example by not doing the first lock-free lookup.
5383f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
5393f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  const OatFile::OatDexFile* oat_dex_file = nullptr;
5403f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  StringPiece key(dex_location);
5413f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
5423f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // directly mentioned in the oat file and doesn't require locking.
5433f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  auto primary_it = oat_dex_files_.find(key);
5443f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  if (primary_it != oat_dex_files_.end()) {
5453f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    oat_dex_file = primary_it->second;
5463f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    DCHECK(oat_dex_file != nullptr);
5473f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  } else {
5483f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // This dex_location is not one of the dex locations directly mentioned in the
5493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // oat file. The correct lookup is via the canonical location but first see in
5503f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // the secondary_oat_dex_files_ whether we've looked up this location before.
5513f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    MutexLock mu(Thread::Current(), secondary_lookup_lock_);
5523f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
5533f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
5542cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      oat_dex_file = secondary_lb->second;  // May be null.
5553f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    } else {
5563f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // We haven't seen this dex_location before, we must check the canonical location.
5573f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
558aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      if (dex_canonical_location != dex_location) {
559aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        StringPiece canonical_key(dex_canonical_location);
560aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        auto canonical_it = oat_dex_files_.find(canonical_key);
561aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        if (canonical_it != oat_dex_files_.end()) {
562aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko          oat_dex_file = canonical_it->second;
5632cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        }  // else keep null.
5642cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      }  // else keep null.
5653f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
5663f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // Copy the key to the string_cache_ and store the result in secondary map.
5673f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      string_cache_.emplace_back(key.data(), key.length());
5683f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      StringPiece key_copy(string_cache_.back());
5693f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
570756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    }
571756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  }
5723f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  if (oat_dex_file != nullptr &&
5733f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      (dex_location_checksum == nullptr ||
5743f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko       oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) {
5753f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    return oat_dex_file;
5763f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  }
577756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom
578756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  if (warn_if_not_found) {
5793f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
5800d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom    std::string checksum("<unspecified>");
581fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe    if (dex_location_checksum != nullptr) {
5820d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom      checksum = StringPrintf("0x%08x", *dex_location_checksum);
5830d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom    }
584756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location
5854e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle                 << " ( canonical path " << dex_canonical_location << ")"
5860d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom                 << " with checksum " << checksum << " in OatFile " << GetLocation();
587756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    if (kIsDebugBuild) {
588aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      for (const OatDexFile* odf : oat_dex_files_storage_) {
589756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom        LOG(WARNING) << "OatFile " << GetLocation()
590aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " contains OatDexFile " << odf->GetDexFileLocation()
591aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")"
592aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                     << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum();
5937571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom      }
5947fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers    }
595aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
5964e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle
597fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  return nullptr;
598aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
599aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
600e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
601aa6a588eb83288481389aa08b03105346a87e706Elliott Hughes                                const std::string& dex_file_location,
602aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                const std::string& canonical_dex_file_location,
6035b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom                                uint32_t dex_file_location_checksum,
60413735955f39b3b304c37d2b2840663c131262c18Ian Rogers                                const uint8_t* dex_file_pointer,
6050755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom                                const uint32_t* oat_class_offsets_pointer)
606e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    : oat_file_(oat_file),
607e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      dex_file_location_(dex_file_location),
608aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      canonical_dex_file_location_(canonical_dex_file_location),
6095b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      dex_file_location_checksum_(dex_file_location_checksum),
61089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom      dex_file_pointer_(dex_file_pointer),
6110755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      oat_class_offsets_pointer_(oat_class_offsets_pointer) {}
612e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
613e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::~OatDexFile() {}
614e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
61505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogerssize_t OatFile::OatDexFile::FileSize() const {
61605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers  return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
61705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers}
61805f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
619fbef44de596d298dc6430f482dffc933a046dd28Richard Uhlerstd::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
62005f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers  return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
62107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                       dex_file_location_checksum_, this, error_msg);
62289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom}
62389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
6242cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
6252cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return oat_class_offsets_pointer_[class_def_index];
6262cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
6272cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
628d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir MarkoOatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
6292cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
6300755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
63113735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
6327571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom  CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
6330755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
63413735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* status_pointer = oat_class_pointer;
635ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
636ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  mirror::Class::Status status =
637ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
638ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status, mirror::Class::kStatusMax);
639ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
64013735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
641ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
642ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
643ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type, kOatClassMax);
644ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
64513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
646cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom  CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
647cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom
648ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  uint32_t bitmap_size = 0;
64913735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* bitmap_pointer = nullptr;
65013735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* methods_pointer = nullptr;
65197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers  if (type != kOatClassNoneCompiled) {
65297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    if (type == kOatClassSomeCompiled) {
65397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
65497b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
65597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
65697b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = bitmap_pointer + bitmap_size;
65797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    } else {
65897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = after_type_pointer;
65997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    }
66097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
661ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
6620755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
66307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler  return OatFile::OatClass(oat_file_,
66407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           status,
66507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           type,
66607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           bitmap_size,
66707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           reinterpret_cast<const uint32_t*>(bitmap_pointer),
66807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
669e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
670e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
6710755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatFile::OatClass::OatClass(const OatFile* oat_file,
6722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                            mirror::Class::Status status,
673ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            OatClassType type,
674ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            uint32_t bitmap_size,
675ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            const uint32_t* bitmap_pointer,
6760755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom                            const OatMethodOffsets* methods_pointer)
677ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    : oat_file_(oat_file), status_(status), type_(type),
678d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
679ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    switch (type_) {
680ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassAllCompiled: {
681ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
682cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
68397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
684ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
685ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
686ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassSomeCompiled: {
687ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_NE(0U, bitmap_size);
688cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer != nullptr);
68997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
690ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
691ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
692ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassNoneCompiled: {
693ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
694cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
69597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer_ == nullptr);
696ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
697ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
698ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassMax: {
699ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        LOG(FATAL) << "Invalid OatClassType " << type_;
700ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
701ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
702ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
703ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom}
704e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
7052cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
7062cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
7072cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
7082cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return 0u;
7092cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
7102cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
7112cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
7122cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
7132cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
714d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko  // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
7152cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (methods_pointer_ == nullptr) {
716ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassNoneCompiled, type_);
7172cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return nullptr;
718ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
719ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  size_t methods_pointer_index;
7202cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (bitmap_ == nullptr) {
721ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassAllCompiled, type_);
722ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    methods_pointer_index = method_index;
723ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  } else {
724ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassSomeCompiled, type_);
725d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    if (!BitVector::IsBitSet(bitmap_, method_index)) {
7262cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      return nullptr;
727ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
728d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
729d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    methods_pointer_index = num_set_bits;
730ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
731ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
7322cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return &oat_method_offsets;
7332cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
7342cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
7352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
7362cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
7372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
738957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(nullptr, 0);
7392cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
7402cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_file_->IsExecutable() ||
7412cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      Runtime::Current() == nullptr ||        // This case applies for oatdump.
742e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier      Runtime::Current()->IsAotCompiler()) {
743957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
7449dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  }
745e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
746e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // version.
747e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  return OatMethod(oat_file_->Begin(), 0);
7483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
7493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
7503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
751fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(method != nullptr);
752ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
753ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
754ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
7557ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampebool OatFile::IsPic() const {
75646774767fcf7780d1455e755729198648d08742eIgor Murashkin  return GetOatHeader().IsPic();
7577ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe  // TODO: Check against oat_patches. b/18144996
7587ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe}
7597ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe
760094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertzbool OatFile::IsDebuggable() const {
761094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz  return GetOatHeader().IsDebuggable();
762094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz}
763094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz
7647848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestatic constexpr char kDexClassPathEncodingSeparator = '*';
7657848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7667848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestd::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) {
7677848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  std::ostringstream out;
7687848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7697848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  for (const DexFile* dex_file : dex_files) {
7707848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << dex_file->GetLocation().c_str();
7717848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << kDexClassPathEncodingSeparator;
7727848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << dex_file->GetLocationChecksum();
7737848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << kDexClassPathEncodingSeparator;
7747848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
7757848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7767848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  return out.str();
7777848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe}
7787848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7797848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampebool OatFile::CheckStaticDexFileDependencies(const char* dex_dependencies, std::string* msg) {
7807848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  if (dex_dependencies == nullptr || dex_dependencies[0] == 0) {
7817848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    // No dependencies.
7827848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    return true;
7837848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
7847848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7857848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  // Assumption: this is not performance-critical. So it's OK to do this with a std::string and
7867848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  //             Split() instead of manual parsing of the combined char*.
7877848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  std::vector<std::string> split;
7887848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  Split(dex_dependencies, kDexClassPathEncodingSeparator, &split);
7897848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  if (split.size() % 2 != 0) {
7907848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    // Expected pairs of location and checksum.
7917848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    *msg = StringPrintf("Odd number of elements in dependency list %s", dex_dependencies);
7927848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    return false;
7937848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
7947848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
7957848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  for (auto it = split.begin(), end = split.end(); it != end; it += 2) {
7967848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    std::string& location = *it;
7977848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    std::string& checksum = *(it + 1);
7987848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    int64_t converted = strtoll(checksum.c_str(), nullptr, 10);
7997848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    if (converted == 0) {
8007848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      // Conversion error.
8017848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      *msg = StringPrintf("Conversion error for %s", checksum.c_str());
8027848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      return false;
8037848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    }
8047848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8057848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    uint32_t dex_checksum;
8067848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    std::string error_msg;
8077848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    if (DexFile::GetChecksum(DexFile::GetDexCanonicalLocation(location.c_str()).c_str(),
8087848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe                             &dex_checksum,
8097848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe                             &error_msg)) {
8107848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      if (converted != dex_checksum) {
8117848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe        *msg = StringPrintf("Checksums don't match for %s: %" PRId64 " vs %u",
8127848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe                            location.c_str(), converted, dex_checksum);
8137848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe        return false;
8147848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      }
8157848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    } else {
8167848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      // Problem retrieving checksum.
8177848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      // TODO: odex files?
8187848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      *msg = StringPrintf("Could not retrieve checksum for %s: %s", location.c_str(),
8197848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe                          error_msg.c_str());
8207848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe      return false;
8217848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    }
8227848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
8237848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8247848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  return true;
8257848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe}
8267848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8277848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampebool OatFile::GetDexLocationsFromDependencies(const char* dex_dependencies,
8287848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe                                              std::vector<std::string>* locations) {
8297848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  DCHECK(locations != nullptr);
8307848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  if (dex_dependencies == nullptr || dex_dependencies[0] == 0) {
8317848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    return true;
8327848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
8337848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8347848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  // Assumption: this is not performance-critical. So it's OK to do this with a std::string and
8357848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  //             Split() instead of manual parsing of the combined char*.
8367848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  std::vector<std::string> split;
8377848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  Split(dex_dependencies, kDexClassPathEncodingSeparator, &split);
8387848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  if (split.size() % 2 != 0) {
8397848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    // Expected pairs of location and checksum.
8407848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    return false;
8417848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
8427848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8437848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  for (auto it = split.begin(), end = split.end(); it != end; it += 2) {
8447848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    locations->push_back(*it);
8457848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
8467848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
8477848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  return true;
8487848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe}
8497848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
850e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
851