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>
2106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko#include <type_traits>
22daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe#include <unistd.h>
23700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
247848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe#include <cstdlib>
251baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#ifndef __APPLE__
261baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#include <link.h>  // for dl_iterate_phdr.
271baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#endif
28e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler#include <sstream>
29e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler
30fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// dlopen_ext support from bionic.
31bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID
32fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#include "android/dlext.h"
33fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif
34fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
3546ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
3646ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
37c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "art_method.h"
38ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h"
39542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h"
401aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h"
4132ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h"
42761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
43a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe#include "dex_file_types.h"
44700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "elf_file.h"
4584d7605f93f1e6e86a16e02017e305c90e93117aAlex Light#include "elf_utils.h"
46aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko#include "gc_root.h"
47700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h"
481baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#include "mem_map.h"
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
504f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
51c04c800e7bda94abfadc8c2d30f58c50b261b612Nicolas Geoffray#include "oat_file-inl.h"
52f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier#include "oat_file_manager.h"
53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h"
5422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include "runtime.h"
559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko#include "type_lookup_table.h"
569aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr#include "utf-inl.h"
572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h"
5809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko#include "utils/dex_cache_arrays_layout-inl.h"
5997d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko#include "vdex_file.h"
60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art {
62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
6346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
6446ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
65049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
661baabf0726eb285284e0c908ccba9f209b399faeDavid Srbeckystatic constexpr bool kUseDlopen = true;
67fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
68049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
69fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// bionic, so cannot take advantage of the support for changed semantics (loading the same soname
70fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// multiple times). However, if/when we switch the above, we likely want to switch this, too,
71fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// to get test coverage of the code paths.
721baabf0726eb285284e0c908ccba9f209b399faeDavid Srbeckystatic constexpr bool kUseDlopenOnHost = true;
73fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
74fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// For debugging, Open will print DlOpen error message if set to true.
75fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampestatic constexpr bool kPrintDlOpenErrorMessage = false;
76fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
77049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Note for OatFileBase and descendents:
78049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//
79049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// These are used in OatFile::Open to try all our loaders.
80049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//
81049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// The process is simple:
82049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//
83049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 1) Allocate an instance through the standard constructor (location, executable)
84049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 2) Load() to try to open the file.
85049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
86049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 4) PreSetup() for any steps that should be done before the final setup.
87049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 5) Setup() to complete the procedure.
88049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
89049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass OatFileBase : public OatFile {
90049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public:
91049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  virtual ~OatFileBase() {}
92049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
93049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  template <typename kOatFileBaseSubType>
947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  static OatFileBase* OpenOatFile(const std::string& vdex_filename,
957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                  const std::string& elf_filename,
9684d7605f93f1e6e86a16e02017e305c90e93117aAlex Light                                  const std::string& location,
97049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  uint8_t* requested_base,
98049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  uint8_t* oat_file_begin,
99049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  bool writable,
100049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  bool executable,
1010b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                  bool low_4gb,
102e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler                                  const char* abs_dex_location,
103049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  std::string* error_msg);
104fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
105049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected:
106049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
107fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
108049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
109049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                  std::string* error_msg) const = 0;
110956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes
1114075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  virtual void PreLoad() = 0;
1124075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
1137b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  bool LoadVdex(const std::string& vdex_filename,
1147b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                bool writable,
1157b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                bool low_4gb,
1167b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                std::string* error_msg);
1177b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
118049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  virtual bool Load(const std::string& elf_filename,
119049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                    uint8_t* oat_file_begin,
120049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                    bool writable,
121049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                    bool executable,
1220b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                    bool low_4gb,
123049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                    std::string* error_msg) = 0;
124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
125049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool ComputeFields(uint8_t* requested_base,
126049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                     const std::string& file_path,
127049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                     std::string* error_msg);
128700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
129049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  virtual void PreSetup(const std::string& elf_filename) = 0;
130a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
131049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool Setup(const char* abs_dex_location, std::string* error_msg);
132fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
133049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Setters exposed for ElfOatFile.
134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
135049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  void SetBegin(const uint8_t* begin) {
136049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    begin_ = begin;
137e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  }
138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
139049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  void SetEnd(const uint8_t* end) {
140049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    end_ = end;
141700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
143c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil  void SetVdex(VdexFile* vdex) {
144c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil    vdex_.reset(vdex);
145c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil  }
146c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil
147049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private:
148049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DISALLOW_COPY_AND_ASSIGN(OatFileBase);
149049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe};
150049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
151049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampetemplate <typename kOatFileBaseSubType>
1527b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David BrazdilOatFileBase* OatFileBase::OpenOatFile(const std::string& vdex_filename,
1537b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                      const std::string& elf_filename,
154049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      const std::string& location,
155049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      uint8_t* requested_base,
156049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      uint8_t* oat_file_begin,
157049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      bool writable,
158049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      bool executable,
1590b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                      bool low_4gb,
160049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      const char* abs_dex_location,
161049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                      std::string* error_msg) {
162049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
1634075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
1644075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  ret->PreLoad();
1654075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
1667b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  if (kIsVdexEnabled && !ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
1677b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    return nullptr;
1687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  }
1697b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
170049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!ret->Load(elf_filename,
171049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                 oat_file_begin,
172049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                 writable,
173049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                 executable,
1740b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                 low_4gb,
175049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                 error_msg)) {
176049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
177fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
178fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
179049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) {
180049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  }
1824075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
183049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  ret->PreSetup(elf_filename);
1841baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky
185049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!ret->Setup(abs_dex_location, error_msg)) {
186049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
1875dedb808acf84712daf7dee3cf8137d4e34b4b78David Srbecky  }
1885dedb808acf84712daf7dee3cf8137d4e34b4b78David Srbecky
189049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return ret.release();
190fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe}
191fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe
1927b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilbool OatFileBase::LoadVdex(const std::string& vdex_filename,
1937b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                           bool writable,
1947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                           bool low_4gb,
1957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                           std::string* error_msg) {
196cab655799dc0c04d42b00642a813438efe46acf5Nicolas Geoffray  vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg);
1977b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  if (vdex_.get() == nullptr) {
1987b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
1997b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                              vdex_filename.c_str(),
2007b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                              error_msg->c_str());
2017b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    return false;
2027b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  }
2037b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  return true;
2047b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil}
2057b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
206049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool OatFileBase::ComputeFields(uint8_t* requested_base,
207049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                const std::string& file_path,
208049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                std::string* error_msg) {
209049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::string symbol_error_msg;
210049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
211fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (begin_ == nullptr) {
212049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
213049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                              file_path.c_str(),
214049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                              symbol_error_msg.c_str());
215700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
216700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
217fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (requested_base != nullptr && begin_ != requested_base) {
218f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray    // Host can fail this check. Do not dump there to avoid polluting the output.
2197ec0904eac1d799d3443b4c5e83545b72eae9ad3Andreas Gampe    if (kIsTargetBuild && (kIsDebugBuild || VLOG_IS_ON(oat))) {
220f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray      PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
221f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray    }
2228d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
223049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        "oatdata=%p != expected=%p. See process maps in the log.",
224049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        begin_, requested_base);
225700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
226700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
227049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
228fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  if (end_ == nullptr) {
229049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
230049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                              file_path.c_str(),
231049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                              symbol_error_msg.c_str());
232700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    return false;
233700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
234700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  // Readjust to be non-inclusive upper bound.
235700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  end_ += sizeof(uint32_t);
2365c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
237049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
2385c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  if (bss_begin_ == nullptr) {
239049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    // No .bss section.
2405c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    bss_end_ = nullptr;
2415c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  } else {
242049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
2435c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    if (bss_end_ == nullptr) {
244049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str());
2455c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko      return false;
2465c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    }
2475c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    // Readjust to be non-inclusive upper bound.
2485c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko    bss_end_ += sizeof(uint32_t);
249aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    // Find bss roots if present.
250aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
2515c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  }
2525c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
253049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return true;
254700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom}
2556e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom
25606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// Read an unaligned entry from the OatDexFile data in OatFile and advance the read
25706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// position by the number of bytes read, i.e. sizeof(T).
25806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// Return true on success, false if the read would go beyond the end of the OatFile.
25906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Markotemplate <typename T>
260722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Markoinline static bool ReadOatDexFileData(const OatFile& oat_file,
261722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Marko                                      /*inout*/const uint8_t** oat,
262722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Marko                                      /*out*/T* value) {
26306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  DCHECK(oat != nullptr);
26406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  DCHECK(value != nullptr);
26506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  DCHECK_LE(*oat, oat_file.End());
26606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
26706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    return false;
26806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  }
26906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  static_assert(std::is_trivial<T>::value, "T must be a trivial type");
27006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  typedef __attribute__((__aligned__(1))) T unaligned_type;
27106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  *value = *reinterpret_cast<const unaligned_type*>(*oat);
27206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  *oat += sizeof(T);
27306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko  return true;
27406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko}
27506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko
276c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodsonstatic bool FindDexFileMapItem(const uint8_t* dex_begin,
277c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                               const uint8_t* dex_end,
278c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                               DexFile::MapItemType map_item_type,
279c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                               const DexFile::MapItem** result_item) {
280c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  *result_item = nullptr;
281c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
282c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  const DexFile::Header* header =
283c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      BoundsCheckedCast<const DexFile::Header*>(dex_begin, dex_begin, dex_end);
284c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  if (nullptr == header) return false;
285c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
286c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  if (!DexFile::IsMagicValid(header->magic_)) return true;  // Not a dex file, not an error.
287c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
288c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  const DexFile::MapList* map_list =
289c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      BoundsCheckedCast<const DexFile::MapList*>(dex_begin + header->map_off_, dex_begin, dex_end);
290c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  if (nullptr == map_list) return false;
291c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
292c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  const DexFile::MapItem* map_item = map_list->list_;
293c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  size_t count = map_list->size_;
294c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  while (count--) {
295c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson    if (map_item->type_ == static_cast<uint16_t>(map_item_type)) {
296c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      *result_item = map_item;
297c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      break;
298c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson    }
299c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson    map_item = BoundsCheckedCast<const DexFile::MapItem*>(map_item + 1, dex_begin, dex_end);
300c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson    if (nullptr == map_item) return false;
301c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  }
302c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
303c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson  return true;
304c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson}
305c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson
306049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
307f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  if (!GetOatHeader().IsValid()) {
3082bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    std::string cause = GetOatHeader().GetValidationErrorMessage();
30906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    *error_msg = StringPrintf("Invalid oat header for '%s': %s",
31006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                              GetLocation().c_str(),
3112bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                              cause.c_str());
312f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom    return false;
313f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  }
31413735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat = Begin();
315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  oat += sizeof(OatHeader);
316fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
3178d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
318fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
319fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
320fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom
32122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  oat += GetOatHeader().GetKeyValueStoreSize();
322fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  if (oat > End()) {
32322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
32406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                  "%p + %zu + %u <= %p",
32506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                              GetLocation().c_str(),
32606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                              Begin(),
32706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                              sizeof(OatHeader),
32806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                              GetOatHeader().GetKeyValueStoreSize(),
3298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                              End());
330fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    return false;
331fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom  }
33281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
333aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  if (!IsAligned<alignof(GcRoot<mirror::Object>)>(bss_begin_) ||
334aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_roots_) ||
335aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
336aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
337aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                                  "begin = %p, roots = %p, end = %p",
338aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              GetLocation().c_str(),
339aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_begin_,
340aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_roots_,
341aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_end_);
342aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    return false;
343aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
344aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko
345aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  if (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) {
346aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    *error_msg = StringPrintf("In oat file '%s' found bss roots outside .bss: "
347aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                                  "%p is outside range [%p, %p]",
348aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              GetLocation().c_str(),
349aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_roots_,
350aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_begin_,
351aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                              bss_end_);
352aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    return false;
353aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
354aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko
355542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe  PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
3561998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko  uint8_t* dex_cache_arrays = (bss_begin_ == bss_roots_) ? nullptr : bss_begin_;
3571998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko  uint8_t* dex_cache_arrays_end =
3581998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko      (bss_begin_ == bss_roots_) ? nullptr : (bss_roots_ != nullptr) ? bss_roots_ : bss_end_;
3591998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko  DCHECK_EQ(dex_cache_arrays != nullptr, dex_cache_arrays_end != nullptr);
360aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
361aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  oat_dex_files_storage_.reserve(dex_file_count);
362aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko  for (size_t i = 0; i < dex_file_count; i++) {
36306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    uint32_t dex_file_location_size;
36406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
36506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
36606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "location size",
36706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
36806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i);
369fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
370fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
37106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    if (UNLIKELY(dex_file_location_size == 0U)) {
37206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
37306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
37406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i);
375fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
376fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
3779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
37806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
37906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "location",
38006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
38106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i);
382fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
383fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
3849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
3859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    oat += dex_file_location_size;
386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
387e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler    std::string dex_file_location = ResolveRelativeEncodedDexLocation(
388e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler        abs_dex_location,
389e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler        std::string(dex_file_location_data, dex_file_location_size));
390e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
39106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    uint32_t dex_file_checksum;
39206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
39306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
39406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "dex file checksum",
39506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
39606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
3978d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                dex_file_location.c_str());
398fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
399fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
400e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
40106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    uint32_t dex_file_offset;
40206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
40306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
40406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "after dex file offsets",
40506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
40606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
40706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_location.c_str());
408fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
409fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
41006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    if (UNLIKELY(dex_file_offset == 0U)) {
41106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
41206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "file offset",
41306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
41406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
41506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_location.c_str());
416fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
417fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4187b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    if (UNLIKELY(dex_file_offset > DexSize())) {
41906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
42006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "offset %u > %zu",
42106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
42206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
42306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_location.c_str(),
42406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_offset,
4257b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                DexSize());
426fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
427fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4287b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
4299bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
4309bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "offset %u of %zu but the size of dex file header is %zu",
4319bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
4329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
4339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_location.c_str(),
4349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_offset,
4357b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                DexSize(),
4369bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                sizeof(DexFile::Header));
4379bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      return false;
4389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    }
43989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
4407b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset;
4418d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
44206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
44306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "dex file magic '%s'",
44406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
44506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
44606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_location.c_str(),
44706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_pointer);
448fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
449fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4508d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
45106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
45206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    "dex file version '%s'",
45306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
45406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
45506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_location.c_str(),
45606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                dex_file_pointer);
457fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
458fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
4596e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom    const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
4607b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    if (DexSize() - dex_file_offset < header->file_size_) {
4619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
4629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "offset %u and size %u truncated at %zu",
4639bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
4649bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
4659bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_location.c_str(),
4669bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_offset,
4679bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                header->file_size_,
4687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                DexSize());
4699bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      return false;
4709bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    }
471d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko
4729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    uint32_t class_offsets_offset;
4739bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
4749bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
4759bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "after class offsets offset",
4769bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
4779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
478d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko                                dex_file_location.c_str());
479d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko      return false;
480d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko    }
4819bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (UNLIKELY(class_offsets_offset > Size()) ||
4829bdf108885a27ba05fae8501725649574d7c491bVladimir Marko        UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
4839bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
4849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "class offsets, offset %u of %zu, class defs %u",
4859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
4869bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
4879bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_location.c_str(),
4889bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                class_offsets_offset,
4899bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                Size(),
4909bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                header->class_defs_size_);
4919bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      return false;
4929bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    }
4939bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
4949bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
4959bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "class offsets, offset %u",
4969bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
4979bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
4989bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_location.c_str(),
4999bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                class_offsets_offset);
5009bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      return false;
5019bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    }
5029bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    const uint32_t* class_offsets_pointer =
5039bdf108885a27ba05fae8501725649574d7c491bVladimir Marko        reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
5049bdf108885a27ba05fae8501725649574d7c491bVladimir Marko
5059bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    uint32_t lookup_table_offset;
5069bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
5079bdf108885a27ba05fae8501725649574d7c491bVladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
5089bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "after lookup table offset",
5099bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                GetLocation().c_str(),
5109bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                i,
511d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko                                dex_file_location.c_str());
512d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko      return false;
513d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko    }
514d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko    const uint8_t* lookup_table_data = lookup_table_offset != 0u
515d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko        ? Begin() + lookup_table_offset
516d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko        : nullptr;
5179bdf108885a27ba05fae8501725649574d7c491bVladimir Marko    if (lookup_table_offset != 0u &&
5189bdf108885a27ba05fae8501725649574d7c491bVladimir Marko        (UNLIKELY(lookup_table_offset > Size()) ||
5199bdf108885a27ba05fae8501725649574d7c491bVladimir Marko            UNLIKELY(Size() - lookup_table_offset <
5209bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                     TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
52106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
5229bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                    "type lookup table, offset %u of %zu, class defs %u",
52306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                GetLocation().c_str(),
52406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                i,
5259bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                dex_file_location.c_str(),
5269bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                lookup_table_offset,
5279bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                Size(),
5289bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                header->class_defs_size_);
529fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom      return false;
530fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom    }
531e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
53206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    uint8_t* current_dex_cache_arrays = nullptr;
53309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    if (dex_cache_arrays != nullptr) {
534c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      // All DexCache types except for CallSite have their instance counts in the
535c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      // DexFile header. For CallSites, we need to read the info from the MapList.
536c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      const DexFile::MapItem* call_sites_item = nullptr;
537c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      if (!FindDexFileMapItem(DexBegin(),
538c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                              DexEnd(),
539c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                              DexFile::MapItemType::kDexTypeCallSiteIdItem,
540c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                              &call_sites_item)) {
541c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson        *error_msg = StringPrintf("In oat file '%s' could not read data from truncated DexFile map",
542c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson                                  GetLocation().c_str());
543c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson        return false;
544c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      }
545c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      size_t num_call_sites = call_sites_item == nullptr ? 0 : call_sites_item->size_;
546c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson      DexCacheArraysLayout layout(pointer_size, *header, num_call_sites);
54709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko      if (layout.Size() != 0u) {
548aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko        if (static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays) < layout.Size()) {
54906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko          *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
55006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                        "truncated dex cache arrays, %zu < %zu.",
55106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    GetLocation().c_str(),
55206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    i,
55306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    dex_file_location.c_str(),
554aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko                                    static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays),
55506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                    layout.Size());
55609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko          return false;
55709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko        }
55809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko        current_dex_cache_arrays = dex_cache_arrays;
55909d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko        dex_cache_arrays += layout.Size();
56009d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko      }
56109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    }
56209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko
563aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
564aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
565aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Create the OatDexFile and add it to the owning container.
566539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    OatDexFile* oat_dex_file = new OatDexFile(this,
567539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_location,
568aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                              canonical_location,
569539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_checksum,
570539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko                                              dex_file_pointer,
571d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko                                              lookup_table_data,
5729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko                                              class_offsets_pointer,
57309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko                                              current_dex_cache_arrays);
574aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    oat_dex_files_storage_.push_back(oat_dex_file);
575aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko
576aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    // Add the location and canonical location (if different) to the oat_dex_files_ table.
5773f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    StringPiece key(oat_dex_file->GetDexFileLocation());
578539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko    oat_dex_files_.Put(key, oat_dex_file);
579aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    if (canonical_location != dex_file_location) {
580aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
581aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      oat_dex_files_.Put(canonical_key, oat_dex_file);
582aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko    }
583e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
58409d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko
585aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  if (dex_cache_arrays != dex_cache_arrays_end) {
58609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
587aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    // both null) or contain just the dex cache arrays and optionally some GC roots.
58806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko    *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
58909d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko                              GetLocation().c_str(),
59009d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko                              static_cast<size_t>(bss_end_ - dex_cache_arrays));
59109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    return false;
59209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  }
593f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom  return true;
594e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
595e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
596049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////
597049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// OatFile via dlopen //
598049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////
599049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
600049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass DlOpenOatFile FINAL : public OatFileBase {
601049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public:
602049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DlOpenOatFile(const std::string& filename, bool executable)
603049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      : OatFileBase(filename, executable),
604049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        dlopen_handle_(nullptr),
605a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        shared_objects_before_(0) {
606049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
607049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
608049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  ~DlOpenOatFile() {
609049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (dlopen_handle_ != nullptr) {
610a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler      if (!kIsTargetBuild) {
611a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
612a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        host_dlopen_handles_.erase(dlopen_handle_);
613c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier        dlclose(dlopen_handle_);
614c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier      } else {
615c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier        dlclose(dlopen_handle_);
616a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler      }
617049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
618049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
619049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
620049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected:
621049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
622049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                          std::string* error_msg) const OVERRIDE {
623049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    const uint8_t* ptr =
624049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
625049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (ptr == nullptr) {
626049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      *error_msg = dlerror();
627049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
628049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return ptr;
629049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
630049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
6314075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  void PreLoad() OVERRIDE;
6324075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
633049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool Load(const std::string& elf_filename,
634049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            uint8_t* oat_file_begin,
635049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            bool writable,
636049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            bool executable,
6370b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier            bool low_4gb,
638049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            std::string* error_msg) OVERRIDE;
639049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
640049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
641049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  void PreSetup(const std::string& elf_filename) OVERRIDE;
642049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
643049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private:
644049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool Dlopen(const std::string& elf_filename,
645049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe              uint8_t* oat_file_begin,
646049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe              std::string* error_msg);
647049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
648a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // On the host, if the same library is loaded again with dlopen the same
649a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // file handle is returned. This differs from the behavior of dlopen on the
650a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // target, where dlopen reloads the library at a different address every
651a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // time you load it. The runtime relies on the target behavior to ensure
652a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // each instance of the loaded library has a unique dex cache. To avoid
653a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // problems, we fall back to our own linker in the case when the same
654a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // library is opened multiple times on host. dlopen_handles_ is used to
655a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // detect that case.
656a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  // Guarded by host_dlopen_handles_lock_;
657a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler  static std::unordered_set<void*> host_dlopen_handles_;
658a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler
659049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // dlopen handle during runtime.
660049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
661049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
662049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Dummy memory map objects corresponding to the regions mapped by dlopen.
663049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_;
664049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
6654075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  // The number of shared objects the linker told us about before loading. Used to
6664075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  // (optimistically) optimize the PreSetup stage (see comment there).
6674075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  size_t shared_objects_before_;
6684075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
669049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
670049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe};
671049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
672a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhlerstd::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
673a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler
6744075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampevoid DlOpenOatFile::PreLoad() {
6754075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#ifdef __APPLE__
67639004a6fa5566007354379dfc4ae59823146e23eAndreas Gampe  UNUSED(shared_objects_before_);
6774075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  LOG(FATAL) << "Should not reach here.";
6784075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  UNREACHABLE();
6794075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#else
6804075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  // Count the entries in dl_iterate_phdr we get at this point in time.
6814075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  struct dl_iterate_context {
6824075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED,
6834075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe                        size_t size ATTRIBUTE_UNUSED,
6844075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe                        void *data) {
6854075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      reinterpret_cast<dl_iterate_context*>(data)->count++;
6864075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      return 0;  // Continue iteration.
6874075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    }
6884075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    size_t count = 0;
6894075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  } context;
6904075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
6914075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  dl_iterate_phdr(dl_iterate_context::callback, &context);
6924075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  shared_objects_before_ = context.count;
6934075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#endif
6944075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe}
6954075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
696049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool DlOpenOatFile::Load(const std::string& elf_filename,
697049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                         uint8_t* oat_file_begin,
698049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                         bool writable,
699049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                         bool executable,
7000b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                         bool low_4gb,
701049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                         std::string* error_msg) {
702049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Use dlopen only when flagged to do so, and when it's OK to load things executable.
703049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
704049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //       !executable is a sign that we may want to patch), which may not be allowed for
705049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //       various reasons.
706049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!kUseDlopen) {
707049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = "DlOpen is disabled.";
708049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
709049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
7100b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier  if (low_4gb) {
7110b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier    *error_msg = "DlOpen does not support low 4gb loading.";
7120b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier    return false;
7130b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier  }
714049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (writable) {
715049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = "DlOpen does not support writable loading.";
716049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
717049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
718049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!executable) {
719049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = "DlOpen does not support non-executable loading.";
720049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
721049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
722049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
723049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // dlopen always returns the same library if it is already opened on the host. For this reason
724049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // we only use dlopen if we are the target or we do not already have the dex file opened. Having
725049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // the same library loaded multiple times at different addresses is required for class unloading
726049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // and for having dex caches arrays in the .bss section.
727049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!kIsTargetBuild) {
728049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (!kUseDlopenOnHost) {
729049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      *error_msg = "DlOpen disabled for host.";
730049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      return false;
731049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
732049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
733049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
734049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool success = Dlopen(elf_filename, oat_file_begin, error_msg);
735049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DCHECK(dlopen_handle_ != nullptr || !success);
736049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
737049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return success;
738049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
739049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
740049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool DlOpenOatFile::Dlopen(const std::string& elf_filename,
741049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                           uint8_t* oat_file_begin,
742049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                           std::string* error_msg) {
743049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#ifdef __APPLE__
744049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
745049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // but let's fallback to the custom loading code for the time being.
746049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  UNUSED(elf_filename, oat_file_begin);
747049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  *error_msg = "Dlopen unsupported on Mac.";
748049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return false;
749049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#else
750049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  {
751049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
752049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (absolute_path == nullptr) {
753049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
754049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      return false;
755049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
756bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID
7573a2e78ebade9f7e0444be6f6817cbf116b34e7b1Anton Kirilov    android_dlextinfo extinfo = {};
758049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    extinfo.flags = ANDROID_DLEXT_FORCE_LOAD |                  // Force-load, don't reuse handle
759049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                //   (open oat files multiple
760049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                //    times).
761049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                    ANDROID_DLEXT_FORCE_FIXED_VADDR;            // Take a non-zero vaddr as absolute
762049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                //   (non-pic boot image).
763226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe    if (oat_file_begin != nullptr) {                            //
764226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe      extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;     // Use the requested addr if
765226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe      extinfo.reserved_addr = oat_file_begin;                   // vaddr = 0.
766226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe    }                                                           //   (pic boot image).
767049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
768049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#else
769049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    UNUSED(oat_file_begin);
7701af0c4ff8b79ad44a4e12d7271a66d4e775ba224Julien Duraj    static_assert(!kIsTargetBuild || kIsTargetLinux, "host_dlopen_handles_ will leak handles");
771c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier    MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
772a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler    dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
773a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler    if (dlopen_handle_ != nullptr) {
774a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler      if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
775a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        dlclose(dlopen_handle_);
776a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        dlopen_handle_ = nullptr;
777a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
778a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler        return false;
779a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler      }
780a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler    }
781bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#endif  // ART_TARGET_ANDROID
782049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
783049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (dlopen_handle_ == nullptr) {
784049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
785049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
786049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
787049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return true;
788049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#endif
789049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
790049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
791049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampevoid DlOpenOatFile::PreSetup(const std::string& elf_filename) {
79274f07b5264811263497c39853549ccb321f0973cAndreas Gampe#ifdef __APPLE__
79374f07b5264811263497c39853549ccb321f0973cAndreas Gampe  UNUSED(elf_filename);
79474f07b5264811263497c39853549ccb321f0973cAndreas Gampe  LOG(FATAL) << "Should not reach here.";
79574f07b5264811263497c39853549ccb321f0973cAndreas Gampe  UNREACHABLE();
79674f07b5264811263497c39853549ccb321f0973cAndreas Gampe#else
797049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  struct dl_iterate_context {
798049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
799049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      auto* context = reinterpret_cast<dl_iterate_context*>(data);
8004075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      context->shared_objects_seen++;
8014075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      if (context->shared_objects_seen < context->shared_objects_before) {
8024075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe        // We haven't been called yet for anything we haven't seen before. Just continue.
8034075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe        // Note: this is aggressively optimistic. If another thread was unloading a library,
8044075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe        //       we may miss out here. However, this does not happen often in practice.
8054075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe        return 0;
8064075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      }
8074075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
808049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      // See whether this callback corresponds to the file which we have just loaded.
809049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      bool contains_begin = false;
810049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      for (int i = 0; i < info->dlpi_phnum; i++) {
811049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        if (info->dlpi_phdr[i].p_type == PT_LOAD) {
812049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
813049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe              info->dlpi_phdr[i].p_vaddr);
814049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          size_t memsz = info->dlpi_phdr[i].p_memsz;
815049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
816049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            contains_begin = true;
817049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            break;
818049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          }
819049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        }
820049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      }
821049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      // Add dummy mmaps for this file.
822049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      if (contains_begin) {
823049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        for (int i = 0; i < info->dlpi_phnum; i++) {
824049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          if (info->dlpi_phdr[i].p_type == PT_LOAD) {
825049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
826049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                info->dlpi_phdr[i].p_vaddr);
827049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            size_t memsz = info->dlpi_phdr[i].p_memsz;
828049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
829049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
830049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe          }
831049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        }
832049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
833049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      }
834049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
835049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
836049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    const uint8_t* const begin_;
837049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
8384075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    const size_t shared_objects_before;
8394075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    size_t shared_objects_seen;
8404075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  };
8414075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0};
842049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
843049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
8444075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
8454075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    // before giving up. This should be unusual.
8464075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
8474075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe              << shared_objects_before_;
8484075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0};
8494075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) {
8504075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      // OK, give up and print an error.
8514075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
8524075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe      LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
8534075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe    }
854049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
85574f07b5264811263497c39853549ccb321f0973cAndreas Gampe#endif
856049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
857049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
858049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////////////////////////////
859049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// OatFile via our own ElfFile implementation //
860049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////////////////////////////
861049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
862049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass ElfOatFile FINAL : public OatFileBase {
863049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public:
864049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
865049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
866049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  static ElfOatFile* OpenElfFile(File* file,
867049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 const std::string& location,
868049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 uint8_t* requested_base,
869049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 uint8_t* oat_file_begin,  // Override base if not null
870049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 bool writable,
871049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 bool executable,
8720b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                 bool low_4gb,
873049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 const char* abs_dex_location,
874049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 std::string* error_msg);
875049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
876049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool InitializeFromElfFile(ElfFile* elf_file,
877c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil                             VdexFile* vdex_file,
878049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             const char* abs_dex_location,
879049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             std::string* error_msg);
880049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
881049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected:
882049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
883049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                          std::string* error_msg) const OVERRIDE {
884049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
885049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (ptr == nullptr) {
886049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      *error_msg = "(Internal implementation could not find symbol)";
887049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
888049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return ptr;
889049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
890049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
8914075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  void PreLoad() OVERRIDE {
8924075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe  }
8934075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe
894049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool Load(const std::string& elf_filename,
895049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
896049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            bool writable,
897049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            bool executable,
8980b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier            bool low_4gb,
899049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe            std::string* error_msg) OVERRIDE;
900049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
901049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE {
902049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
903049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
904049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private:
905049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool ElfFileOpen(File* file,
906049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                   uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
907049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                   bool writable,
908049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                   bool executable,
9090b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                   bool low_4gb,
910049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                   std::string* error_msg);
911049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
912049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private:
913049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Backing memory map for oat file during cross compilation.
914049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::unique_ptr<ElfFile> elf_file_;
915049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
916049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
917049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe};
918049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
919049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeElfOatFile* ElfOatFile::OpenElfFile(File* file,
920049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    const std::string& location,
921049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    uint8_t* requested_base,
922049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    uint8_t* oat_file_begin,  // Override base if not null
923049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    bool writable,
924049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    bool executable,
9250b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                    bool low_4gb,
926049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    const char* abs_dex_location,
927049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                    std::string* error_msg) {
92832ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace("Open elf file " + location);
929049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
9300b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier  bool success = oat_file->ElfFileOpen(file,
9310b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                       oat_file_begin,
9320b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                       writable,
9330b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                       low_4gb,
9340b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                       executable,
9350b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                       error_msg);
936049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!success) {
937049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    CHECK(!error_msg->empty());
938049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
939049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
940049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
941049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Complete the setup.
942049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!oat_file->ComputeFields(requested_base, file->GetPath(), error_msg)) {
943049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
944049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
945049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
946049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (!oat_file->Setup(abs_dex_location, error_msg)) {
947049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return nullptr;
948049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
949049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
950049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return oat_file.release();
951049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
952049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
953049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
954c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil                                       VdexFile* vdex_file,
955049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                       const char* abs_dex_location,
956049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                       std::string* error_msg) {
95732ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
958049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (IsExecutable()) {
959049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = "Cannot initialize from elf file in executable mode.";
960049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
961049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
962049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  elf_file_.reset(elf_file);
963c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil  SetVdex(vdex_file);
964049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  uint64_t offset, size;
965049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
966049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  CHECK(has_section);
967049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  SetBegin(elf_file->Begin() + offset);
968049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  SetEnd(elf_file->Begin() + size + offset);
969049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Ignore the optional .bss section when opening non-executable.
970049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return Setup(abs_dex_location, error_msg);
971049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
972049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
973049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::Load(const std::string& elf_filename,
974049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                      uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
975049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                      bool writable,
976049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                      bool executable,
9770b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                      bool low_4gb,
978049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                      std::string* error_msg) {
97932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
980049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
981049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (file == nullptr) {
982049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
983049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
984049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
985049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return ElfOatFile::ElfFileOpen(file.get(),
986049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 oat_file_begin,
987049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 writable,
988049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 executable,
9890b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                 low_4gb,
990049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 error_msg);
991049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
992049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
993049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::ElfFileOpen(File* file,
994049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             uint8_t* oat_file_begin,
995049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             bool writable,
996049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             bool executable,
9970b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                             bool low_4gb,
998049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                             std::string* error_msg) {
99932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
1000049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // TODO: rename requested_base to oat_data_begin
1001049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  elf_file_.reset(ElfFile::Open(file,
1002049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                writable,
1003049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                /*program_header_only*/true,
10040b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                low_4gb,
1005049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                error_msg,
1006049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                oat_file_begin));
1007049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (elf_file_ == nullptr) {
1008049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    DCHECK(!error_msg->empty());
1009049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return false;
1010049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
1011f5b0f2cef8554efaa90adc6a1ae04c2b533970edBrian Carlstrom  bool loaded = elf_file_->Load(file, executable, low_4gb, error_msg);
1012049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  DCHECK(loaded || !error_msg->empty());
1013049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return loaded;
1014049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1015049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1016049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////////
1017049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// General OatFile code //
1018049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////////
1019049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1020049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampestd::string OatFile::ResolveRelativeEncodedDexLocation(
1021049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      const char* abs_dex_location, const std::string& rel_dex_location) {
1022049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
1023049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    // Strip :classes<N>.dex used for secondary multidex files.
1024049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    std::string base = DexFile::GetBaseLocation(rel_dex_location);
1025049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location);
1026049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1027049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    // Check if the base is a suffix of the provided abs_dex_location.
1028049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    std::string target_suffix = "/" + base;
1029049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    std::string abs_location(abs_dex_location);
1030049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    if (abs_location.size() > target_suffix.size()) {
1031049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      size_t pos = abs_location.size() - target_suffix.size();
1032049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) {
1033049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe        return abs_location + multidex_suffix;
1034049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      }
1035049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    }
1036049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
1037049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return rel_dex_location;
1038049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1039049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1040049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampestatic void CheckLocation(const std::string& location) {
1041049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  CHECK(!location.empty());
1042049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1043049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1044049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
1045c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil                                  VdexFile* vdex_file,
1046049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  const std::string& location,
1047049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  const char* abs_dex_location,
1048049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                  std::string* error_msg) {
1049049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */));
1050c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil  return oat_file->InitializeFromElfFile(elf_file, vdex_file, abs_dex_location, error_msg)
1051049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      ? oat_file.release()
1052049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      : nullptr;
1053049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1054049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
10557b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David BrazdilOatFile* OatFile::Open(const std::string& oat_filename,
10567b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                       const std::string& oat_location,
1057049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                       uint8_t* requested_base,
1058049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                       uint8_t* oat_file_begin,
1059049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                       bool executable,
10600b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                       bool low_4gb,
1061049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                       const char* abs_dex_location,
1062049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                       std::string* error_msg) {
10637b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  ScopedTrace trace("Open oat file " + oat_location);
10647b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  CHECK(!oat_filename.empty()) << oat_location;
10657b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  CheckLocation(oat_location);
106654315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe
1067cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  std::string vdex_filename = GetVdexFilename(oat_filename);
10687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
10697b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  // Check that the files even exist, fast-fail.
10707b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  if (kIsVdexEnabled && !OS::FileExists(vdex_filename.c_str())) {
10717b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
10727b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    return nullptr;
10737b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  } else if (!OS::FileExists(oat_filename.c_str())) {
10747b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    *error_msg = StringPrintf("File %s does not exist.", oat_filename.c_str());
107554315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe    return nullptr;
107654315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe  }
1077049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1078049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1079049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // disabled.
10807b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(vdex_filename,
10817b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                 oat_filename,
10827b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                 oat_location,
1083049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                 requested_base,
1084049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                 oat_file_begin,
10857b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                 false /* writable */,
1086049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                 executable,
10870b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                                                 low_4gb,
1088049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                 abs_dex_location,
1089049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                 error_msg);
1090049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (with_dlopen != nullptr) {
1091049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    return with_dlopen;
1092049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
1093049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  if (kPrintDlOpenErrorMessage) {
10947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil    LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1095049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  }
1096049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1097049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //
1098049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1099049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //
1100049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // We use our own ELF loader for Quick to deal with legacy apps that
1101049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // open a generated dex file by name, remove the file, then open
1102049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // another generated dex file with the same name. http://b/10614658
1103049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //
1104049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
1105049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //
1106049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  //
1107049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1108049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
11097b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_filename,
11107b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                oat_filename,
11117b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                oat_location,
1112049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                requested_base,
1113049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                oat_file_begin,
11147b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil                                                                false /* writable */,
1115049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                executable,
11160b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                                                low_4gb,
1117049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                abs_dex_location,
1118049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                                                error_msg);
1119049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return with_internal;
1120049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1121049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1122049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenWritable(File* file,
1123049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               const std::string& location,
1124049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               const char* abs_dex_location,
1125049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               std::string* error_msg) {
1126049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  CheckLocation(location);
1127049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return ElfOatFile::OpenElfFile(file,
1128049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 location,
1129049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 nullptr,
1130049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 nullptr,
1131049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 true,
1132049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 false,
11330b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                 /*low_4gb*/false,
1134049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 abs_dex_location,
1135049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 error_msg);
1136049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1137049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1138049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenReadable(File* file,
1139049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               const std::string& location,
1140049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               const char* abs_dex_location,
1141049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                               std::string* error_msg) {
1142049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  CheckLocation(location);
1143049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  return ElfOatFile::OpenElfFile(file,
1144049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 location,
1145049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 nullptr,
1146049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 nullptr,
1147049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 false,
1148049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 false,
11490b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier                                 /*low_4gb*/false,
1150049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 abs_dex_location,
1151049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe                                 error_msg);
1152049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1153049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1154049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile::OatFile(const std::string& location, bool is_executable)
1155049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe    : location_(location),
11567b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil      vdex_(nullptr),
1157049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      begin_(nullptr),
1158049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      end_(nullptr),
1159049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      bss_begin_(nullptr),
1160049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      bss_end_(nullptr),
1161aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      bss_roots_(nullptr),
1162049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      is_executable_(is_executable),
1163049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe      secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1164049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  CHECK(!location_.empty());
1165049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1166049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1167049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile::~OatFile() {
1168049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe  STLDeleteElements(&oat_dex_files_storage_);
1169049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}
1170049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe
1171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst OatHeader& OatFile::GetOatHeader() const {
117230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  return *reinterpret_cast<const OatHeader*>(Begin());
1173e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1174e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
117513735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::Begin() const {
1176fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(begin_ != nullptr);
1177700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return begin_;
1178e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1179e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
118013735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::End() const {
1181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(end_ != nullptr);
1182700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return end_;
1183e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1184e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
11855c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssBegin() const {
11865c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  return bss_begin_;
11875c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko}
11885c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
11895c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssEnd() const {
11905c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  return bss_end_;
11915c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko}
11925c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko
11937b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilconst uint8_t* OatFile::DexBegin() const {
11947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  return kIsVdexEnabled ? vdex_->Begin() : Begin();
11957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil}
11967b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
11977b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilconst uint8_t* OatFile::DexEnd() const {
11987b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil  return kIsVdexEnabled ? vdex_->End() : End();
11997b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil}
12007b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil
1201aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir MarkoArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
1202aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  if (bss_roots_ != nullptr) {
1203aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
1204aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
1205aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
1206aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  } else {
1207aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    return ArrayRef<GcRoot<mirror::Object>>();
1208aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
1209aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko}
1210aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko
12118d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
12128d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers                                                  const uint32_t* dex_location_checksum,
12139a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler                                                  std::string* error_msg) const {
12143f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // NOTE: We assume here that the canonical location for a given dex_location never
12153f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // changes. If it does (i.e. some symlink used by the filename changes) we may return
12163f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
12173f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // an identical file or fail; otherwise we may see some unpredictable failures.
12183f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
12193f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // TODO: Additional analysis of usage patterns to see if this can be simplified
12203f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // without any performance loss, for example by not doing the first lock-free lookup.
12213f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
12223f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  const OatFile::OatDexFile* oat_dex_file = nullptr;
12233f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  StringPiece key(dex_location);
12243f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
12253f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  // directly mentioned in the oat file and doesn't require locking.
12263f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  auto primary_it = oat_dex_files_.find(key);
12273f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  if (primary_it != oat_dex_files_.end()) {
12283f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    oat_dex_file = primary_it->second;
12293f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    DCHECK(oat_dex_file != nullptr);
12303f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko  } else {
12313f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // This dex_location is not one of the dex locations directly mentioned in the
12323f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // oat file. The correct lookup is via the canonical location but first see in
12333f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    // the secondary_oat_dex_files_ whether we've looked up this location before.
12343f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    MutexLock mu(Thread::Current(), secondary_lookup_lock_);
12353f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
12363f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
12372cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      oat_dex_file = secondary_lb->second;  // May be null.
12383f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko    } else {
12393f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // We haven't seen this dex_location before, we must check the canonical location.
12403f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1241aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      if (dex_canonical_location != dex_location) {
1242aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        StringPiece canonical_key(dex_canonical_location);
1243aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        auto canonical_it = oat_dex_files_.find(canonical_key);
1244aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko        if (canonical_it != oat_dex_files_.end()) {
1245aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko          oat_dex_file = canonical_it->second;
12462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        }  // else keep null.
12472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      }  // else keep null.
12483f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko
12493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      // Copy the key to the string_cache_ and store the result in secondary map.
12503f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      string_cache_.emplace_back(key.data(), key.length());
12513f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      StringPiece key_copy(string_cache_.back());
12523f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko      secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
1253756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom    }
1254756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom  }
1255756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom
12569a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler  if (oat_dex_file == nullptr) {
12579a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler    if (error_msg != nullptr) {
12589a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
12599a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
12609a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler          + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
12617fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers    }
12629a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler    return nullptr;
1263aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
12644e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle
12659a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler  if (dex_location_checksum != nullptr &&
12669a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
12679a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler    if (error_msg != nullptr) {
12689a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
12699a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
12709a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
12719a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler      *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
12729a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler          + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
12739a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler          + " has checksum " + checksum + " but " + required_checksum + " was required";
12749a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler    }
12759a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler    return nullptr;
12769a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler  }
12779a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler  return oat_dex_file;
1278aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
1279aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
1281aa6a588eb83288481389aa08b03105346a87e706Elliott Hughes                                const std::string& dex_file_location,
1282aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko                                const std::string& canonical_dex_file_location,
12835b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom                                uint32_t dex_file_location_checksum,
128413735955f39b3b304c37d2b2840663c131262c18Ian Rogers                                const uint8_t* dex_file_pointer,
1285d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko                                const uint8_t* lookup_table_data,
128609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko                                const uint32_t* oat_class_offsets_pointer,
128706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko                                uint8_t* dex_cache_arrays)
1288e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    : oat_file_(oat_file),
1289e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      dex_file_location_(dex_file_location),
1290aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko      canonical_dex_file_location_(canonical_dex_file_location),
12915b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      dex_file_location_checksum_(dex_file_location_checksum),
129289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom      dex_file_pointer_(dex_file_pointer),
1293d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko      lookup_table_data_(lookup_table_data),
129409d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko      oat_class_offsets_pointer_(oat_class_offsets_pointer),
12959aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr      dex_cache_arrays_(dex_cache_arrays) {
12969aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  // Initialize TypeLookupTable.
12979aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  if (lookup_table_data_ != nullptr) {
12989aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    // Peek the number of classes from the DexFile.
12999aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
13009aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    const uint32_t num_class_defs = dex_header->class_defs_size_;
13019aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
13029aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr      LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
13039aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    } else {
13041b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier      lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
13059aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    }
13069aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  }
13079aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr}
1308e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
13091b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu ChartierOatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
13101b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier    : lookup_table_(std::move(lookup_table)) {}
13111b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier
1312e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::~OatDexFile() {}
1313e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
131405f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogerssize_t OatFile::OatDexFile::FileSize() const {
131505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers  return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
131605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers}
131705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
1318b1d8c314b55bb2df2b2bb72a3daaf5db65b7ebc7Igor Murashkinstd::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
131932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
132037d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik  static constexpr bool kVerify = false;
132137d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik  static constexpr bool kVerifyChecksum = false;
13223a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe  return DexFile::Open(dex_file_pointer_,
13233a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe                       FileSize(),
13243a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe                       dex_file_location_,
13253a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe                       dex_file_location_checksum_,
13263a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe                       this,
132737d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik                       kVerify,
132837d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik                       kVerifyChecksum,
13293a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe                       error_msg);
133089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom}
133189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom
13322cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
13332cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return oat_class_offsets_pointer_[class_def_index];
13342cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
13352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
1336d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir MarkoOatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
13372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
13380755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
133913735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
13407571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom  CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
13410755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
134213735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* status_pointer = oat_class_pointer;
1343ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
1344ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  mirror::Class::Status status =
1345ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
1346ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(status, mirror::Class::kStatusMax);
1347ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
134813735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
1349ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
1350ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
1351ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  CHECK_LT(type, kOatClassMax);
1352ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom
135313735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
1354cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom  CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
1355cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom
1356ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  uint32_t bitmap_size = 0;
135713735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* bitmap_pointer = nullptr;
135813735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* methods_pointer = nullptr;
135997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers  if (type != kOatClassNoneCompiled) {
136097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    if (type == kOatClassSomeCompiled) {
136197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
136297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
136397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
136497b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = bitmap_pointer + bitmap_size;
136597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    } else {
136697b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers      methods_pointer = after_type_pointer;
136797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    }
136897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers    CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
1369ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
13700755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
137107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler  return OatFile::OatClass(oat_file_,
137207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           status,
137307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           type,
137407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           bitmap_size,
137507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           reinterpret_cast<const uint32_t*>(bitmap_pointer),
137607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler                           reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
1377e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
1378e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
13799aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehrconst DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_file,
13809aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr                                                           const char* descriptor,
13819aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr                                                           size_t hash) {
13829aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
13839aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
13849aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) {
13859aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash);
13869aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    return (class_def_idx != DexFile::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr;
13879aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  }
13889aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  // Fast path for rare no class defs case.
13899aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  const uint32_t num_class_defs = dex_file.NumClassDefs();
13909aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  if (num_class_defs == 0) {
13919aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    return nullptr;
13929aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  }
13939aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor);
13949aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  if (type_id != nullptr) {
1395a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe    dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
13969aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    return dex_file.FindClassDef(type_idx);
13979aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  }
13989aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr  return nullptr;
13999aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr}
14009aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr
14010755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatFile::OatClass::OatClass(const OatFile* oat_file,
14022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                            mirror::Class::Status status,
1403ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            OatClassType type,
1404ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            uint32_t bitmap_size,
1405ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom                            const uint32_t* bitmap_pointer,
14060755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom                            const OatMethodOffsets* methods_pointer)
1407ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    : oat_file_(oat_file), status_(status), type_(type),
1408d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
1409ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    switch (type_) {
1410ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassAllCompiled: {
1411ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
1412cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
141397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
1414ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
1415ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
1416ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassSomeCompiled: {
1417ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_NE(0U, bitmap_size);
1418cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer != nullptr);
141997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer != nullptr);
1420ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
1421ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
1422ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassNoneCompiled: {
1423ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        CHECK_EQ(0U, bitmap_size);
1424cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom        CHECK(bitmap_pointer == nullptr);
142597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers        CHECK(methods_pointer_ == nullptr);
1426ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
1427ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
1428ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      case kOatClassMax: {
1429ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        LOG(FATAL) << "Invalid OatClassType " << type_;
1430ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom        break;
1431ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      }
1432ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
1433ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom}
1434e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
14352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
14362cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
14372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
14382cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return 0u;
14392cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
14402cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
14412cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
14422cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
14432cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
1444d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko  // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
14452cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (methods_pointer_ == nullptr) {
1446ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassNoneCompiled, type_);
14472cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom    return nullptr;
1448ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
1449ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  size_t methods_pointer_index;
14502cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (bitmap_ == nullptr) {
1451ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassAllCompiled, type_);
1452ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    methods_pointer_index = method_index;
1453ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  } else {
1454ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    CHECK_EQ(kOatClassSomeCompiled, type_);
1455d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    if (!BitVector::IsBitSet(bitmap_, method_index)) {
14562cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      return nullptr;
1457ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom    }
1458d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
1459d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko    methods_pointer_index = num_set_bits;
1460ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  }
1461ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom  const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
14622cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  return &oat_method_offsets;
14632cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom}
14642cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom
14652cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
14662cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
14672cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_method_offsets == nullptr) {
1468957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(nullptr, 0);
14692cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  }
14702cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom  if (oat_file_->IsExecutable() ||
14712cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom      Runtime::Current() == nullptr ||        // This case applies for oatdump.
1472e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier      Runtime::Current()->IsAotCompiler()) {
1473957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
14749dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light  }
1475e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
1476e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // version.
1477e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  return OatMethod(oat_file_->Begin(), 0);
14783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
14793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
1480e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
1481fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe  CHECK(method != nullptr);
1482ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
1483ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
1484ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
14857ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampebool OatFile::IsPic() const {
148646774767fcf7780d1455e755729198648d08742eIgor Murashkin  return GetOatHeader().IsPic();
14877ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe  // TODO: Check against oat_patches. b/18144996
14887ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe}
14897ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe
14900de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatFile::IsDebuggable() const {
14910de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return GetOatHeader().IsDebuggable();
14920de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
14930de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
149429d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas GampeCompilerFilter::Filter OatFile::GetCompilerFilter() const {
149529d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe  return GetOatHeader().GetCompilerFilter();
1496b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle}
1497b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle
14987848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestatic constexpr char kDexClassPathEncodingSeparator = '*';
14997848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
150016d4843433e024100b4ecd183f827ad5bd8772a6Jeff Haostd::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files,
150116d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao                                               std::string& base_dir) {
15027848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  std::ostringstream out;
15037848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
15047848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  for (const DexFile* dex_file : dex_files) {
150516d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao    const std::string& location = dex_file->GetLocation();
150616d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao    // Find paths that were relative and convert them back from absolute.
150716d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao    if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) {
150816d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao      out << location.substr(base_dir.length() + 1).c_str();
150916d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao    } else {
151016d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao      out << dex_file->GetLocation().c_str();
151116d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao    }
15127848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << kDexClassPathEncodingSeparator;
15137848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << dex_file->GetLocationChecksum();
15147848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe    out << kDexClassPathEncodingSeparator;
15157848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  }
15167848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
15177848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe  return out.str();
15187848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe}
15197848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe
152097d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir MarkoOatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
152197d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko                                        uint16_t class_def_idx,
152297d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko                                        bool* found) {
152397d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko  DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
152497d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko  const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
15251b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier  if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
152697d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko    *found = false;
152797d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko    return OatFile::OatClass::Invalid();
152897d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko  }
152997d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko  *found = true;
153097d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko  return oat_dex_file->GetOatClass(class_def_idx);
153197d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko}
153297d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko
15331b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartiervoid OatFile::OatDexFile::AssertAotCompiler() {
15341b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier  CHECK(Runtime::Current()->IsAotCompiler());
15351b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier}
15361b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier
1537e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
1538